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())
|
|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)]
|
#[derive(Subcommand, Clone, Debug)]
|
||||||
pub enum MnemonicSubcommands {
|
pub enum MnemonicSubcommands {
|
||||||
/// Generate a mnemonic using a given entropy source.
|
/// Generate a mnemonic using a given entropy source.
|
||||||
|
@ -292,6 +312,16 @@ pub enum MnemonicSubcommands {
|
||||||
#[arg(long, requires = "provision", default_value_t = Options::default())]
|
#[arg(long, requires = "provision", default_value_t = Options::default())]
|
||||||
provision_config: Options,
|
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.
|
// 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("pgp" | "gpg") => false,
|
||||||
Some("asc") => true,
|
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!("use .gpg, .pgp, or .asc extension, or `armor=true`");
|
||||||
eprintln!("defaulting to armored");
|
eprintln!("defaulting to armored");
|
||||||
true
|
true
|
||||||
|
@ -460,7 +493,9 @@ fn do_shard(
|
||||||
return Err(MissingThresholdOrMax.into());
|
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())?;
|
let len = u8::try_from(certs.len())?;
|
||||||
(len, len)
|
(len, len)
|
||||||
};
|
};
|
||||||
|
@ -942,6 +977,32 @@ impl MnemonicSubcommands {
|
||||||
}
|
}
|
||||||
Ok(())
|
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