From 883e0cdf65522cf00d8c0fd4f3b4e94ca33526a4 Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 18 Feb 2024 18:01:18 -0500 Subject: [PATCH] keyfork-mnemonic-util: deprecate seed() in favor of generate_seed() --- crates/daemon/keyforkd/src/lib.rs | 2 +- .../derive/keyfork-derive-util/src/request.rs | 2 +- crates/util/keyfork-mnemonic-util/src/lib.rs | 42 +++++++++++++++---- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/crates/daemon/keyforkd/src/lib.rs b/crates/daemon/keyforkd/src/lib.rs index 2fa0b20..40eafd4 100644 --- a/crates/daemon/keyforkd/src/lib.rs +++ b/crates/daemon/keyforkd/src/lib.rs @@ -57,7 +57,7 @@ pub async fn start_and_run_server_on( let service = ServiceBuilder::new() .layer(middleware::BincodeLayer::new()) // TODO: passphrase support and/or store passphrase with mnemonic - .service(Keyforkd::new(mnemonic.seed(None)?)); + .service(Keyforkd::new(mnemonic.generate_seed(None))); let mut server = match UnixServer::bind(socket_path) { Ok(s) => s, diff --git a/crates/derive/keyfork-derive-util/src/request.rs b/crates/derive/keyfork-derive-util/src/request.rs index d6f5830..447b538 100644 --- a/crates/derive/keyfork-derive-util/src/request.rs +++ b/crates/derive/keyfork-derive-util/src/request.rs @@ -209,7 +209,7 @@ impl DerivationRequest { /// # } pub fn derive_with_mnemonic(&self, mnemonic: &Mnemonic) -> Result { // TODO: passphrase support and/or store passphrase within mnemonic - self.derive_with_master_seed(&mnemonic.seed(None)?) + self.derive_with_master_seed(&mnemonic.generate_seed(None)) } /// Derive an [`ExtendedPrivateKey`] using the given seed. diff --git a/crates/util/keyfork-mnemonic-util/src/lib.rs b/crates/util/keyfork-mnemonic-util/src/lib.rs index f5d22cb..90190a5 100644 --- a/crates/util/keyfork-mnemonic-util/src/lib.rs +++ b/crates/util/keyfork-mnemonic-util/src/lib.rs @@ -1,6 +1,11 @@ //! Zero-dependency Mnemonic encoding and decoding. -use std::{error::Error, fmt::Display, str::FromStr, sync::Arc}; +use std::{ + error::Error, + fmt::Display, + str::FromStr, + sync::{Arc, OnceLock}, +}; use hmac::Hmac; use pbkdf2::pbkdf2; @@ -96,6 +101,14 @@ pub struct Mnemonic { wordlist: Arc, } +impl PartialEq for Mnemonic { + fn eq(&self, other: &Self) -> bool { + self.entropy.eq(&other.entropy) + } +} + +impl Eq for Mnemonic {} + impl Display for Mnemonic { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let bit_count = self.entropy.len() * 8; @@ -316,23 +329,34 @@ impl Mnemonic { /// Create a BIP-0032 seed from the provided data and an optional passphrase. /// /// # Errors - /// The method may return an error if the pbkdf2 function returns an invalid length, but this - /// case should not be reached. + /// The method should not return an error. + #[deprecated = "Use generate_seed() instead"] pub fn seed<'a>( &self, passphrase: impl Into>, ) -> Result, MnemonicGenerationError> { + Ok(self.generate_seed(passphrase)) + } + + /// Create a BIP-0032 seed from the provided data and an optional passphrase. + /// + /// # Panics + /// The function may panic if the HmacSha512 function returns an error. The only error the + /// HmacSha512 function should return is an invalid length, which should not be possible. + /// + pub fn generate_seed<'a>(&self, passphrase: impl Into>) -> Vec { let passphrase = passphrase.into(); let mut seed = [0u8; 64]; let mnemonic = self.to_string(); let salt = ["mnemonic", passphrase.unwrap_or("")].join(""); pbkdf2::>(mnemonic.as_bytes(), salt.as_bytes(), 2048, &mut seed) - .map_err(|_| MnemonicGenerationError::InvalidPbkdf2Length)?; - Ok(seed.to_vec()) + .expect("HmacSha512 InvalidLength should be infallible"); + seed.to_vec() } - /// Encode the mnemonic into a list of wordlist indexes. + /// Encode the mnemonic into a list of integers 11 bits in length, matching the length of a + /// BIP-0039 wordlist. pub fn words(self) -> (Vec, Arc) { let bit_count = self.entropy.len() * 8; let mut bits = vec![false; bit_count + bit_count / 32]; @@ -416,13 +440,13 @@ mod tests { let my_mnemonic = super::Mnemonic::from_entropy(&entropy[..256 / 8], wordlist).unwrap(); let their_mnemonic = bip39::Mnemonic::from_entropy(&entropy[..256 / 8]).unwrap(); assert_eq!(my_mnemonic.to_string(), their_mnemonic.to_string()); - assert_eq!(my_mnemonic.seed(None).unwrap(), their_mnemonic.to_seed("")); + assert_eq!(my_mnemonic.generate_seed(None), their_mnemonic.to_seed("")); assert_eq!( - my_mnemonic.seed("testing").unwrap(), + my_mnemonic.generate_seed("testing"), their_mnemonic.to_seed("testing") ); assert_ne!( - my_mnemonic.seed("test1").unwrap(), + my_mnemonic.generate_seed("test1"), their_mnemonic.to_seed("test2") ); }