Skip to content

Commit

Permalink
display mnemonic key (#694)
Browse files Browse the repository at this point in the history
  • Loading branch information
conradludgate committed Feb 6, 2023
1 parent 3abc96f commit 5611bc5
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 6 deletions.
74 changes: 74 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ whoami = "1.1.2"
rpassword = "7.0"
semver = "1.0.14"
runtime-format = "0.1.2"
tiny-bip39 = "1"

[dependencies.tracing-subscriber]
version = "0.3"
Expand Down
1 change: 1 addition & 0 deletions atuin-client/src/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub fn load_encoded_key(settings: &Settings) -> Result<String> {
}
}

pub type Key = secretbox::Key;
pub fn encode_key(key: secretbox::Key) -> Result<String> {
let buf = rmp_serde::to_vec(&key).wrap_err("could not encode key to message pack")?;
let buf = base64::encode(buf);
Expand Down
19 changes: 15 additions & 4 deletions src/command/client/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ pub enum Cmd {
Register(register::Cmd),

/// Print the encryption key for transfer to another machine
Key,
Key {
/// Switch to base64 output of the key
#[arg(long)]
base64: bool,
},
}

impl Cmd {
Expand All @@ -37,11 +41,18 @@ impl Cmd {
Self::Login(l) => l.run(&settings).await,
Self::Logout => logout::run(),
Self::Register(r) => r.run(&settings).await,
Self::Key => {
Self::Key { base64 } => {
use atuin_client::encryption::{encode_key, load_key};
let key = load_key(&settings).wrap_err("could not load encryption key")?;
let encode = encode_key(key).wrap_err("could not encode encryption key")?;
println!("{encode}");

if base64 {
let encode = encode_key(key).wrap_err("could not encode encryption key")?;
println!("{encode}");
} else {
let mnemonic = bip39::Mnemonic::from_entropy(&key.0, bip39::Language::English)
.map_err(|_| eyre::eyre!("invalid key"))?;
println!("{mnemonic}");
}
Ok(())
}
}
Expand Down
54 changes: 52 additions & 2 deletions src/command/client/sync/login.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use std::io;

use clap::Parser;
use eyre::Result;
use eyre::{bail, ContextCompat, Result};
use tokio::{fs::File, io::AsyncWriteExt};

use atuin_client::{api_client, settings::Settings};
use atuin_client::{
api_client,
encryption::{encode_key, Key},
settings::Settings,
};
use atuin_common::api::LoginRequest;
use rpassword::prompt_password;

Expand Down Expand Up @@ -54,6 +58,31 @@ impl Cmd {

let key_path = settings.key_path.as_str();
let mut file = File::create(key_path).await?;

// try parse the key as a mnemonic...
let key = match bip39::Mnemonic::from_phrase(&key, bip39::Language::English) {
Ok(mnemonic) => encode_key(
Key::from_slice(mnemonic.entropy()).context("key was not the correct length")?,
)?,
Err(err) => {
if let Some(err) = err.downcast_ref::<bip39::ErrorKind>() {
match err {
// assume they copied in the base64 key
bip39::ErrorKind::InvalidWord => key,
bip39::ErrorKind::InvalidChecksum => bail!("key mnemonic was not valid"),
bip39::ErrorKind::InvalidKeysize(_)
| bip39::ErrorKind::InvalidWordLength(_)
| bip39::ErrorKind::InvalidEntropyLength(_, _) => {
bail!("key was not the correct length")
}
}
} else {
// unknown error. assume they copied the base64 key
key
}
}
};

file.write_all(key.as_bytes()).await?;

println!("Logged in!");
Expand All @@ -75,3 +104,24 @@ fn read_user_input(name: &'static str) -> String {
eprint!("Please enter {name}: ");
get_input().expect("Failed to read from input")
}

#[cfg(test)]
mod tests {
use atuin_client::encryption::Key;

#[test]
fn mnemonic_round_trip() {
let key = Key {
0: [
3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3,
2, 7, 9, 5,
],
};
let phrase = bip39::Mnemonic::from_entropy(&key.0, bip39::Language::English)
.unwrap()
.into_phrase();
let mnemonic = bip39::Mnemonic::from_phrase(&phrase, bip39::Language::English).unwrap();
assert_eq!(mnemonic.entropy(), &key.0);
assert_eq!(phrase, "adapt amused able anxiety mother adapt beef gaze amount else seat alcohol cage lottery avoid scare alcohol cactus school avoid coral adjust catch pink");
}
}

0 comments on commit 5611bc5

Please sign in to comment.