From d481c7e1648dfb2873f2085b92467c794b369407 Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 18 Feb 2024 18:14:50 -0500 Subject: [PATCH] keyfork-mnemonic-util: deprecate from{_raw,}_bytes --- crates/keyfork-shard/src/lib.rs | 4 +- crates/keyfork-shard/src/openpgp.rs | 4 +- crates/keyfork/src/cli/mnemonic.rs | 2 +- crates/keyfork/src/cli/recover.rs | 2 +- .../src/bin/keyfork-mnemonic-from-seed.rs | 2 +- crates/util/keyfork-mnemonic-util/src/lib.rs | 92 ++++++++++++------- 6 files changed, 68 insertions(+), 38 deletions(-) diff --git a/crates/keyfork-shard/src/lib.rs b/crates/keyfork-shard/src/lib.rs index 496d00c..2e4e63f 100644 --- a/crates/keyfork-shard/src/lib.rs +++ b/crates/keyfork-shard/src/lib.rs @@ -75,10 +75,10 @@ pub fn remote_decrypt(w: &mut impl Write) -> Result<(), Box todo!(), MnemonicSeedSource::Dice => todo!(), }; - let mnemonic = keyfork_mnemonic_util::Mnemonic::from_entropy(&seed, Default::default())?; + let mnemonic = keyfork_mnemonic_util::Mnemonic::from_bytes(&seed, Default::default())?; Ok(mnemonic.to_string()) } } diff --git a/crates/keyfork/src/cli/recover.rs b/crates/keyfork/src/cli/recover.rs index 8a6aa4d..e884b2f 100644 --- a/crates/keyfork/src/cli/recover.rs +++ b/crates/keyfork/src/cli/recover.rs @@ -90,7 +90,7 @@ pub struct Recover { impl Recover { pub fn handle(&self, _k: &Keyfork) -> Result<()> { let seed = self.command.handle()?; - let mnemonic = Mnemonic::from_entropy(&seed, Default::default())?; + let mnemonic = Mnemonic::from_bytes(&seed, Default::default())?; tokio::runtime::Builder::new_multi_thread() .enable_all() .build() diff --git a/crates/util/keyfork-mnemonic-util/src/bin/keyfork-mnemonic-from-seed.rs b/crates/util/keyfork-mnemonic-util/src/bin/keyfork-mnemonic-from-seed.rs index 863a395..ddb85cb 100644 --- a/crates/util/keyfork-mnemonic-util/src/bin/keyfork-mnemonic-from-seed.rs +++ b/crates/util/keyfork-mnemonic-util/src/bin/keyfork-mnemonic-from-seed.rs @@ -8,7 +8,7 @@ fn main() -> Result<(), Box> { input.read_line(&mut line)?; let decoded = smex::decode(line.trim())?; - let mnemonic = unsafe { Mnemonic::from_raw_entropy(&decoded, Default::default()) }; + let mnemonic = unsafe { Mnemonic::from_raw_bytes(&decoded, Default::default()) }; println!("{mnemonic}"); diff --git a/crates/util/keyfork-mnemonic-util/src/lib.rs b/crates/util/keyfork-mnemonic-util/src/lib.rs index 4480443..f66db96 100644 --- a/crates/util/keyfork-mnemonic-util/src/lib.rs +++ b/crates/util/keyfork-mnemonic-util/src/lib.rs @@ -109,14 +109,14 @@ impl Wordlist { /// A BIP-0039 mnemonic with reference to a [`Wordlist`]. #[derive(Debug, Clone)] pub struct Mnemonic { - entropy: Vec, + data: Vec, // words: Vec, wordlist: Arc, } impl PartialEq for Mnemonic { fn eq(&self, other: &Self) -> bool { - self.entropy.eq(&other.entropy) + self.data.eq(&other.data) } } @@ -124,18 +124,18 @@ 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; + let bit_count = self.data.len() * 8; let mut bits = vec![false; bit_count + bit_count / 32]; for byte_index in 0..bit_count / 8 { for bit_index in 0..8 { bits[byte_index * 8 + bit_index] = - (self.entropy[byte_index] & (1 << (7 - bit_index))) > 0; + (self.data[byte_index] & (1 << (7 - bit_index))) > 0; } } let mut hasher = Sha256::new(); - hasher.update(&self.entropy); + hasher.update(&self.data); let hash = hasher.finalize().to_vec(); for check_bit in 0..bit_count / 32 { bits[bit_count + check_bit] = (hash[check_bit / 8] & (1 << (7 - (check_bit % 8)))) > 0; @@ -223,7 +223,7 @@ impl FromStr for Mnemonic { bits.truncate(bits.len() * 32 / 33); // bits.truncate(bits.len() - bits.len() % 32); - let entropy: Vec = bits + let data: Vec = bits .chunks_exact(8) .map(|chunk| { let mut num = 0u8; @@ -235,7 +235,7 @@ impl FromStr for Mnemonic { .collect(); let mut hasher = Sha256::new(); - hasher.update(&entropy); + hasher.update(&data); let hash = hasher.finalize().to_vec(); for (i, bit) in checksum_bits.iter().enumerate() { @@ -245,7 +245,7 @@ impl FromStr for Mnemonic { } Ok(Mnemonic { - entropy, + data, // words: usize_words, wordlist, }) @@ -253,18 +253,19 @@ impl FromStr for Mnemonic { } impl Mnemonic { - /// Generate a [`Mnemonic`] from the provided entropy and [`Wordlist`]. + /// Generate a [`Mnemonic`] from the provided data and [`Wordlist`]. The data is expected to be + /// of 128, 192, or 256 bits, as per BIP-0039. /// /// # Errors - /// An error may be returned if the entropy is not within the acceptable lengths. + /// An error may be returned if the data is not within the expected lengths. /// /// # Examples /// ```rust /// use keyfork_mnemonic_util::Mnemonic; /// let data = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - /// let mnemonic = Mnemonic::from_entropy(data.as_slice(), Default::default()).unwrap(); + /// let mnemonic = Mnemonic::from_bytes(data.as_slice(), Default::default()).unwrap(); /// ``` - pub fn from_entropy( + pub fn from_bytes( bytes: &[u8], wordlist: Arc, ) -> Result { @@ -278,11 +279,24 @@ impl Mnemonic { return Err(MnemonicGenerationError::InvalidByteLength(bit_count)); } - Ok(unsafe { Self::from_raw_entropy(bytes, wordlist) }) + Ok(unsafe { Self::from_raw_bytes(bytes, wordlist) }) } - /// Create a Mnemonic using an arbitrary length of given entropy. The length does not need to - /// conform to BIP-0039 standards. + /// Generate a [`Mnemonic`] from the provided data and [`Wordlist`]. The data is expected to be + /// of 128, 192, or 256 bits, as per BIP-0039. + /// + /// # Errors + /// An error may be returned if the data is not within the expected lengths. + #[deprecated = "use Mnemonic::from_bytes"] + pub fn from_entropy( + bytes: &[u8], + wordlist: Arc, + ) -> Result { + Mnemonic::from_bytes(bytes, wordlist) + } + + /// Create a Mnemonic using an arbitrary length of given data. The length does not need to + /// conform to BIP-0039 standards, but should be a multiple of 32 bits or 4 bytes. /// /// # Safety /// @@ -294,7 +308,7 @@ impl Mnemonic { /// ```rust /// use keyfork_mnemonic_util::Mnemonic; /// let data = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - /// let mnemonic = unsafe { Mnemonic::from_raw_entropy(data.as_slice(), Default::default()) }; + /// let mnemonic = unsafe { Mnemonic::from_raw_bytes(data.as_slice(), Default::default()) }; /// let mnemonic_text = mnemonic.to_string(); /// ``` /// @@ -306,37 +320,53 @@ impl Mnemonic { /// /// // NOTE: Data is of invalid length, 31 /// let data = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - /// let mnemonic = unsafe { Mnemonic::from_raw_entropy(data.as_slice(), Default::default()) }; + /// let mnemonic = unsafe { Mnemonic::from_raw_bytes(data.as_slice(), Default::default()) }; /// let mnemonic_text = mnemonic.to_string(); /// // NOTE: panic happens here /// let new_mnemonic = Mnemonic::from_str(&mnemonic_text).unwrap(); /// ``` - pub unsafe fn from_raw_entropy(bytes: &[u8], wordlist: Arc) -> Mnemonic { + pub unsafe fn from_raw_bytes(bytes: &[u8], wordlist: Arc) -> Mnemonic { Mnemonic { - entropy: bytes.to_vec(), + data: bytes.to_vec(), + wordlist, + } + } + + /// Create a Mnemonic using an arbitrary length of given data. The length does not need to + /// conform to BIP-0039 standards, but should be a multiple of 32 bits or 4 bytes. + /// + /// # Safety + /// + /// This function can potentially produce mnemonics that are not BIP-0039 compliant or can't + /// properly be encoded as a mnemonic. It is assumed the caller asserts the byte count is `% 4 + /// == 0`. If the assumption is incorrect, code may panic. + #[deprecated = "use Mnemonic::from_raw_bytes"] + pub unsafe fn from_raw_entropy(bytes: &[u8], wordlist: Arc) -> Mnemonic{ + Mnemonic { + data: bytes.to_vec(), wordlist, } } /// A view to internal representation of the decoded data. pub fn as_bytes(&self) -> &[u8] { - &self.entropy + &self.data } /// A clone of the internal representation of the decoded data. pub fn to_bytes(&self) -> Vec { - self.entropy.to_vec() + self.data.to_vec() } /// Conver the Mnemonic into the internal representation of the decoded data. pub fn into_bytes(self) -> Vec { - self.entropy + self.data } /// Clone the existing data. #[deprecated = "Use as_bytes(), to_bytes(), or into_bytes() instead"] pub fn entropy(&self) -> Vec { - self.entropy.clone() + self.data.clone() } /// Create a BIP-0032 seed from the provided data and an optional passphrase. @@ -371,18 +401,18 @@ impl Mnemonic { /// 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 bit_count = self.data.len() * 8; let mut bits = vec![false; bit_count + bit_count / 32]; for byte_index in 0..bit_count / 8 { for bit_index in 0..8 { bits[byte_index * 8 + bit_index] = - (self.entropy[byte_index] & (1 << (7 - bit_index))) > 0; + (self.data[byte_index] & (1 << (7 - bit_index))) > 0; } } let mut hasher = Sha256::new(); - hasher.update(&self.entropy); + hasher.update(&self.data); let hash = hasher.finalize().to_vec(); for check_bit in 0..bit_count / 32 { bits[bit_count + check_bit] = (hash[check_bit / 8] & (1 << (7 - (check_bit % 8)))) > 0; @@ -421,7 +451,7 @@ mod tests { let entropy = &mut [0u8; 256 / 8]; random_handle.read_exact(&mut entropy[..]).unwrap(); let wordlist = Wordlist::default().arc(); - let mnemonic = super::Mnemonic::from_entropy(&entropy[..256 / 8], wordlist).unwrap(); + let mnemonic = super::Mnemonic::from_bytes(&entropy[..256 / 8], wordlist).unwrap(); let new_entropy = mnemonic.as_bytes(); assert_eq!(new_entropy, entropy); } @@ -438,7 +468,7 @@ mod tests { }; let hex = hex::decode(hex_.as_str().unwrap()).unwrap(); - let mnemonic = Mnemonic::from_entropy(&hex, wordlist.clone()).unwrap(); + let mnemonic = Mnemonic::from_bytes(&hex, wordlist.clone()).unwrap(); assert_eq!(mnemonic.to_string(), seed.as_str().unwrap()); } @@ -450,7 +480,7 @@ mod tests { let entropy = &mut [0u8; 256 / 8]; random_handle.read_exact(&mut entropy[..]).unwrap(); let wordlist = Wordlist::default().arc(); - let my_mnemonic = super::Mnemonic::from_entropy(&entropy[..256 / 8], wordlist).unwrap(); + let my_mnemonic = super::Mnemonic::from_bytes(&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.generate_seed(None), their_mnemonic.to_seed("")); @@ -475,7 +505,7 @@ mod tests { for _ in 0..tests { random.read_exact(&mut entropy[..]).unwrap(); - let mnemonic = Mnemonic::from_entropy(&entropy[..256 / 8], wordlist.clone()).unwrap(); + let mnemonic = Mnemonic::from_bytes(&entropy[..256 / 8], wordlist.clone()).unwrap(); let (words, _) = mnemonic.words(); hs.clear(); hs.extend(words); @@ -507,7 +537,7 @@ mod tests { let wordlist = Wordlist::default().arc(); let mut random = std::fs::File::open("/dev/urandom").unwrap(); random.read_exact(&mut entropy[..]).unwrap(); - let mnemonic = unsafe { Mnemonic::from_raw_entropy(&entropy[..], wordlist.clone()) }; + let mnemonic = unsafe { Mnemonic::from_raw_bytes(&entropy[..], wordlist.clone()) }; let (words, _) = mnemonic.words(); assert!(words.len() == 96); }