keyfork-mnemonic-util: deprecate from{_raw,}_bytes

This commit is contained in:
Ryan Heywood 2024-02-18 18:14:50 -05:00
parent 31e51f65a5
commit d481c7e164
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
6 changed files with 68 additions and 38 deletions

View File

@ -75,10 +75,10 @@ pub fn remote_decrypt(w: &mut impl Write) -> Result<(), Box<dyn std::error::Erro
iter += 1;
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
let nonce_mnemonic =
unsafe { Mnemonic::from_raw_entropy(nonce.as_slice(), Default::default()) };
unsafe { Mnemonic::from_raw_bytes(nonce.as_slice(), Default::default()) };
let our_key = EphemeralSecret::random();
let key_mnemonic =
Mnemonic::from_entropy(PublicKey::from(&our_key).as_bytes(), Default::default())?;
Mnemonic::from_bytes(PublicKey::from(&our_key).as_bytes(), Default::default())?;
#[cfg(feature = "qrcode")]
{

View File

@ -515,7 +515,7 @@ pub fn decrypt(
let our_key = EphemeralSecret::random();
let our_pubkey_mnemonic =
Mnemonic::from_entropy(PublicKey::from(&our_key).as_bytes(), Default::default())?;
Mnemonic::from_bytes(PublicKey::from(&our_key).as_bytes(), Default::default())?;
let shared_secret = our_key.diffie_hellman(&PublicKey::from(pubkey)).to_bytes();
@ -560,7 +560,7 @@ pub fn decrypt(
}
// safety: size of out_bytes is constant and always % 4 == 0
let payload_mnemonic = unsafe { Mnemonic::from_raw_entropy(&out_bytes, Default::default()) };
let payload_mnemonic = unsafe { Mnemonic::from_raw_bytes(&out_bytes, Default::default()) };
#[cfg(feature = "qrcode")]
{

View File

@ -109,7 +109,7 @@ impl MnemonicSeedSource {
MnemonicSeedSource::Tarot => 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())
}
}

View File

@ -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()

View File

@ -8,7 +8,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
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}");

View File

@ -109,14 +109,14 @@ impl Wordlist {
/// A BIP-0039 mnemonic with reference to a [`Wordlist`].
#[derive(Debug, Clone)]
pub struct Mnemonic {
entropy: Vec<u8>,
data: Vec<u8>,
// words: Vec<usize>,
wordlist: Arc<Wordlist>,
}
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<u8> = bits
let data: Vec<u8> = 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<Wordlist>,
) -> Result<Mnemonic, MnemonicGenerationError> {
@ -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<Wordlist>,
) -> Result<Mnemonic, MnemonicGenerationError> {
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<Wordlist>) -> Mnemonic {
pub unsafe fn from_raw_bytes(bytes: &[u8], wordlist: Arc<Wordlist>) -> 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<Wordlist>) -> 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<u8> {
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<u8> {
self.entropy
self.data
}
/// Clone the existing data.
#[deprecated = "Use as_bytes(), to_bytes(), or into_bytes() instead"]
pub fn entropy(&self) -> Vec<u8> {
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<usize>, Arc<Wordlist>) {
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);
}