From 6a99a09089113fb2854f88e731865299b8519bd6 Mon Sep 17 00:00:00 2001 From: ryan Date: Wed, 16 Aug 2023 15:49:37 -0500 Subject: [PATCH] keyfork-mnemonic-generate: fix endianness --- keyfork-mnemonic-generate/src/main.rs | 76 ++++++++++----------------- 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/keyfork-mnemonic-generate/src/main.rs b/keyfork-mnemonic-generate/src/main.rs index edcc446..04766d7 100644 --- a/keyfork-mnemonic-generate/src/main.rs +++ b/keyfork-mnemonic-generate/src/main.rs @@ -76,32 +76,34 @@ fn build_wordlist() -> Vec { .collect() } -#[allow(clippy::trivially_copy_pass_by_ref)] -fn u8_to_bitslice(byte: &u8) -> [bool; 8] { - [ - byte & (1 << 0) != 0, - byte & (1 << 1) != 0, - byte & (1 << 2) != 0, - byte & (1 << 3) != 0, - byte & (1 << 4) != 0, - byte & (1 << 5) != 0, - byte & (1 << 6) != 0, - byte & (1 << 7) != 0, - ] +fn bitslice_to_usize(bitslice: [bool; 11]) -> usize { + let mut index = 0usize; + for i in 0..11 { + index += usize::from(bitslice[10 - i]) << i; + } + index } -fn bitslice_to_usize(bitslice: [bool; 11]) -> usize { - usize::from(bitslice[10]) - + (usize::from(bitslice[9]) << 1) - + (usize::from(bitslice[8]) << 2) - + (usize::from(bitslice[7]) << 3) - + (usize::from(bitslice[6]) << 4) - + (usize::from(bitslice[5]) << 5) - + (usize::from(bitslice[4]) << 6) - + (usize::from(bitslice[3]) << 7) - + (usize::from(bitslice[2]) << 8) - + (usize::from(bitslice[1]) << 9) - + (usize::from(bitslice[0]) << 10) +fn entropy_to_bits(bytes: &[u8]) -> Vec { + let bit_count = bytes.len() * 8; + let hash = generate_slice_hash(bytes); + + assert_eq!(bit_count % 32, 0, "bit count must be in 32 bit increments"); + + 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] = (bytes[byte_index] & (1 << (7 - bit_index))) > 0; + } + } + for check_bit in 0..bit_count / 32 { + bits[bit_count + check_bit] = (hash[check_bit / 8] & (1 << (7 - (check_bit % 8)))) > 0; + } + + assert_eq!(bits.len() % 11, 0, "unstable bit count"); + + bits } fn main() -> Result<(), Box> { @@ -133,18 +135,8 @@ fn main() -> Result<(), Box> { let entropy = &mut [0u8; 256 / 8]; random_handle.read_exact(&mut entropy[..])?; - let hash = generate_slice_hash(entropy); - let checksum = u8_to_bitslice(&hash[1]); + let seed_bits = entropy_to_bits(entropy); - let mut seed_bits = entropy[..bit_size / 8] - .iter() - .flat_map(u8_to_bitslice) - .collect::>(); - seed_bits.extend(if bit_size == 256 { - &checksum[..8] - } else { - &checksum[..4] - }); let words = seed_bits .chunks_exact(11) .map(|chunk| wordlist[bitslice_to_usize(chunk.try_into().expect("11 bit chunks"))].clone()) @@ -179,18 +171,8 @@ mod tests { panic!("bad test: {test}"); }; let hex = hex::decode(hex_.as_str().unwrap()).unwrap(); - let hash = generate_slice_hash(&hex); - let checksum = { - let mut bits = u8_to_bitslice(&hash.iter().next().unwrap()); - bits.reverse(); - bits - }; - let mut seed_bits = hex.iter().flat_map(u8_to_bitslice).collect::>(); - seed_bits.extend(if hex.len() == 256 / 8 { - &checksum[..8] - } else { - &checksum[..4] - }); + + let seed_bits = entropy_to_bits(&hex); let words = seed_bits .chunks_exact(11)