keyfork: add mnemonic {from-entropy,to-seed}
This commit is contained in:
parent
4714f616ea
commit
fa47bc28a8
|
@ -168,6 +168,26 @@ fn context_stub(path: &Path) -> impl Fn(std::io::Error) -> Error + use<'_> {
|
|||
|e| Error::IOContext(e, path.to_path_buf())
|
||||
}
|
||||
|
||||
/// Options on how to parse a mnemonic input.
|
||||
#[derive(ValueEnum, Clone, Debug)]
|
||||
pub enum MnemonicInputOptions {
|
||||
/// Parse the input as hex-encoded.
|
||||
Hex,
|
||||
|
||||
/// Parse the input as a wordlist.
|
||||
Wordlist,
|
||||
}
|
||||
|
||||
impl Display for MnemonicInputOptions {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MnemonicInputOptions::Hex => f.write_str("hex"),
|
||||
MnemonicInputOptions::Wordlist => f.write_str("wordlist"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Subcommand, Clone, Debug)]
|
||||
pub enum MnemonicSubcommands {
|
||||
/// Generate a mnemonic using a given entropy source.
|
||||
|
@ -292,6 +312,16 @@ pub enum MnemonicSubcommands {
|
|||
#[arg(long, requires = "provision", default_value_t = Options::default())]
|
||||
provision_config: Options,
|
||||
},
|
||||
|
||||
/// Convert the provided data to a mnemonic wordlist.
|
||||
FromEntropy,
|
||||
|
||||
/// Convert a mnemonic (wordlist or hex encoded) to a seed.
|
||||
ToSeed {
|
||||
/// The format of the mnemonic.
|
||||
#[arg(long, default_value_t = MnemonicInputOptions::Wordlist)]
|
||||
format: MnemonicInputOptions,
|
||||
},
|
||||
}
|
||||
|
||||
// NOTE: This function defaults to `.asc` in the event no extension is found.
|
||||
|
@ -318,7 +348,10 @@ fn is_extension_armored(path: &Path) -> bool {
|
|||
Some("pgp" | "gpg") => false,
|
||||
Some("asc") => true,
|
||||
_ => {
|
||||
eprintln!("unable to determine whether to armor file: {path}", path = path.display());
|
||||
eprintln!(
|
||||
"unable to determine whether to armor file: {path}",
|
||||
path = path.display()
|
||||
);
|
||||
eprintln!("use .gpg, .pgp, or .asc extension, or `armor=true`");
|
||||
eprintln!("defaulting to armored");
|
||||
true
|
||||
|
@ -460,7 +493,9 @@ fn do_shard(
|
|||
return Err(MissingThresholdOrMax.into());
|
||||
}
|
||||
|
||||
let (threshold, max) = if let Some(t) = threshold.zip(max) { t } else {
|
||||
let (threshold, max) = if let Some(t) = threshold.zip(max) {
|
||||
t
|
||||
} else {
|
||||
let len = u8::try_from(certs.len())?;
|
||||
(len, len)
|
||||
};
|
||||
|
@ -942,6 +977,32 @@ impl MnemonicSubcommands {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
MnemonicSubcommands::FromEntropy => {
|
||||
let stdin = std::io::stdin();
|
||||
let hex = std::io::read_to_string(stdin)?;
|
||||
let trimmed = hex.trim();
|
||||
let decoded = smex::decode(trimmed)?;
|
||||
let mnemonic = keyfork_mnemonic::Mnemonic::try_from_slice(&decoded)?;
|
||||
println!("{mnemonic}");
|
||||
Ok(())
|
||||
},
|
||||
MnemonicSubcommands::ToSeed { format } => {
|
||||
let stdin = std::io::stdin();
|
||||
let input = std::io::read_to_string(stdin)?;
|
||||
let trimmed = input.trim();
|
||||
let mnemonic = match format {
|
||||
MnemonicInputOptions::Hex => {
|
||||
let decoded = smex::decode(trimmed)?;
|
||||
keyfork_mnemonic::Mnemonic::try_from_slice(&decoded)?
|
||||
},
|
||||
MnemonicInputOptions::Wordlist => {
|
||||
keyfork_mnemonic::Mnemonic::from_str(trimmed)?
|
||||
},
|
||||
};
|
||||
println!("{}", smex::encode(mnemonic.generate_seed(None)));
|
||||
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue