156 lines
4.3 KiB
Rust
156 lines
4.3 KiB
Rust
use super::Keyfork;
|
|
use clap::{Parser, Subcommand, ValueEnum, builder::PossibleValue};
|
|
use std::fmt::Display;
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
pub enum SeedSize {
|
|
Bits128,
|
|
|
|
#[default]
|
|
Bits256,
|
|
}
|
|
|
|
// custom impl to override names in ValueEnum
|
|
impl ValueEnum for SeedSize {
|
|
fn value_variants<'a>() -> &'a [Self] {
|
|
&[Self::Bits128, Self::Bits256]
|
|
}
|
|
|
|
fn to_possible_value(&self) -> Option<PossibleValue> {
|
|
Some(PossibleValue::new(match self {
|
|
SeedSize::Bits128 => "128",
|
|
SeedSize::Bits256 => "256",
|
|
}))
|
|
}
|
|
}
|
|
|
|
#[derive(thiserror::Error, Debug, Clone)]
|
|
pub enum SeedSizeError {
|
|
#[error("Expected one of 128, 256")]
|
|
InvalidChoice,
|
|
}
|
|
|
|
impl Display for SeedSize {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
SeedSize::Bits128 => write!(f, "128"),
|
|
SeedSize::Bits256 => write!(f, "256"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::str::FromStr for SeedSize {
|
|
type Err = SeedSizeError;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
Ok(match s {
|
|
"128" => SeedSize::Bits128,
|
|
"256" => SeedSize::Bits256,
|
|
_ => return Err(SeedSizeError::InvalidChoice),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl From<&SeedSize> for usize {
|
|
fn from(value: &SeedSize) -> Self {
|
|
match value {
|
|
SeedSize::Bits128 => 128,
|
|
SeedSize::Bits256 => 256,
|
|
}
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, thiserror::Error)]
|
|
pub enum MnemonicSeedSourceParseError {
|
|
#[error("Expected one of system, playing, tarot, dice")]
|
|
InvalidChoice,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, ValueEnum)]
|
|
pub enum MnemonicSeedSource {
|
|
/// System entropy
|
|
#[default]
|
|
System,
|
|
|
|
/// Playing cards
|
|
Playing,
|
|
|
|
/// Tarot cards
|
|
Tarot,
|
|
|
|
/// Dice
|
|
Dice,
|
|
}
|
|
|
|
impl std::str::FromStr for MnemonicSeedSource {
|
|
type Err = MnemonicSeedSourceParseError;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
Ok(match s {
|
|
"system" => Self::System,
|
|
"playing" => Self::Playing,
|
|
"tarot" => Self::Tarot,
|
|
"dice" => Self::Dice,
|
|
_ => return Err(Self::Err::InvalidChoice),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl MnemonicSeedSource {
|
|
pub fn handle(&self, size: &SeedSize) -> Result<String, Box<dyn std::error::Error>> {
|
|
let size = match size {
|
|
SeedSize::Bits128 => 128,
|
|
SeedSize::Bits256 => 256,
|
|
};
|
|
let seed = match self {
|
|
MnemonicSeedSource::System => {
|
|
keyfork_plumbing::ensure_safe();
|
|
keyfork_plumbing::generate_entropy_of_size(size / 8)?
|
|
}
|
|
MnemonicSeedSource::Playing => todo!(),
|
|
MnemonicSeedSource::Tarot => todo!(),
|
|
MnemonicSeedSource::Dice => todo!(),
|
|
};
|
|
let mnemonic = keyfork_mnemonic_util::Mnemonic::from_entropy(&seed, Default::default())?;
|
|
Ok(mnemonic.to_string())
|
|
}
|
|
}
|
|
|
|
#[derive(Subcommand, Clone, Debug)]
|
|
pub enum MnemonicSubcommands {
|
|
/// Generate a mnemonic using a given entropy source.
|
|
///
|
|
/// Mnemonics are a form of encoding a given form of entropy and are used to create a master
|
|
/// seed for BIP-0032 hierarchial derivation. The mnemonic is like the "password" for all of
|
|
/// Keyfork's derivations, and should be treated securely. This command provides a secure
|
|
/// method of generating a seed using system entropy, as well as various forms of loading
|
|
/// physicalized entropy into a mnemonic. The mnemonic should be stored in a safe location
|
|
/// (such as a Trezor "recovery seed card") and never persisted digitally.
|
|
Generate {
|
|
/// The source from where a seed is created.
|
|
#[arg(long, value_enum, default_value_t = Default::default())]
|
|
source: MnemonicSeedSource,
|
|
|
|
/// The size of the mnemonic, in bits.
|
|
#[arg(long, default_value_t = Default::default())]
|
|
size: SeedSize,
|
|
},
|
|
}
|
|
|
|
impl MnemonicSubcommands {
|
|
pub fn handle(
|
|
&self,
|
|
_m: &Mnemonic,
|
|
_keyfork: &Keyfork,
|
|
) -> Result<String, Box<dyn std::error::Error>> {
|
|
match self {
|
|
MnemonicSubcommands::Generate { source, size } => source.handle(size),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Parser, Debug, Clone)]
|
|
pub struct Mnemonic {
|
|
#[command(subcommand)]
|
|
pub command: MnemonicSubcommands,
|
|
}
|