aboutsummaryrefslogtreecommitdiffstats
path: root/crates/turtle/src/command/client/store/rekey.rs
blob: 2b3793274db79ed192b1d09797e6abb003132cbe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
use clap::Args;
use eyre::Result;
use tokio::{fs::File, io::AsyncWriteExt};

use crate::atuin_client::{
    encryption::{decode_key, generate_encoded_key, load_key},
    record::sqlite_store::SqliteStore,
    settings::Settings,
};

#[derive(Args, Debug)]
pub(crate) struct Rekey {
    /// The new key to use for encryption. Omit for a randomly-generated key
    key: Option<String>,
}

impl Rekey {
    pub(crate) async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> {
        let key = if let Some(key) = self.key.clone() {
            println!("Re-encrypting store with specified key");

            key
        } else {
            println!("Re-encrypting store with freshly-generated key");
            let (_, encoded) = generate_encoded_key()?;
            encoded
        };

        let current_key: [u8; 32] = load_key(settings)?.into();
        let new_key: [u8; 32] = decode_key(&key)?.into();

        store.re_encrypt(&current_key, &new_key).await?;

        if let Some(key_path) = settings.sync.encryption_key_path.as_ref() {
            println!("Store rewritten. Saving new key");
            let mut file = File::create(key_path).await?;
            file.write_all(key.as_bytes()).await?;
        } else {
            println!(
                "No key-path (settings.sync.encryption_key_path) set in config, will not save new key."
            );
        }

        Ok(())
    }
}