keyfork-mnemonic-generate: begin work on tests
This commit is contained in:
parent
0d768a6eef
commit
7467a30c40
|
@ -56,10 +56,24 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "keyfork-mnemonic-generate"
|
name = "keyfork-mnemonic-generate"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hex",
|
||||||
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -69,6 +83,29 @@ version = "0.2.147"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.183"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.105"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.7"
|
version = "0.10.7"
|
||||||
|
|
|
@ -7,3 +7,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sha2 = "0.10.7"
|
sha2 = "0.10.7"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
hex = "0.4.3"
|
||||||
|
serde_json = "1.0.105"
|
||||||
|
|
|
@ -61,6 +61,12 @@ fn ensure_offline() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_slice_hash(data: &[u8]) -> Vec<u8> {
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(data);
|
||||||
|
hasher.finalize().to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
fn build_wordlist() -> Vec<String> {
|
fn build_wordlist() -> Vec<String> {
|
||||||
let wordlist_file = include_str!("wordlist.txt");
|
let wordlist_file = include_str!("wordlist.txt");
|
||||||
wordlist_file
|
wordlist_file
|
||||||
|
@ -85,17 +91,17 @@ fn u8_to_bitslice(byte: &u8) -> [bool; 8] {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bitslice_to_usize(bitslice: [bool; 11]) -> usize {
|
fn bitslice_to_usize(bitslice: [bool; 11]) -> usize {
|
||||||
usize::from(bitslice[0])
|
usize::from(bitslice[10])
|
||||||
+ (usize::from(bitslice[1]) << 1)
|
+ (usize::from(bitslice[9]) << 1)
|
||||||
+ (usize::from(bitslice[2]) << 2)
|
+ (usize::from(bitslice[8]) << 2)
|
||||||
+ (usize::from(bitslice[3]) << 3)
|
+ (usize::from(bitslice[7]) << 3)
|
||||||
+ (usize::from(bitslice[4]) << 4)
|
+ (usize::from(bitslice[6]) << 4)
|
||||||
+ (usize::from(bitslice[5]) << 5)
|
+ (usize::from(bitslice[5]) << 5)
|
||||||
+ (usize::from(bitslice[6]) << 6)
|
+ (usize::from(bitslice[4]) << 6)
|
||||||
+ (usize::from(bitslice[7]) << 7)
|
+ (usize::from(bitslice[3]) << 7)
|
||||||
+ (usize::from(bitslice[8]) << 8)
|
+ (usize::from(bitslice[2]) << 8)
|
||||||
+ (usize::from(bitslice[9]) << 9)
|
+ (usize::from(bitslice[1]) << 9)
|
||||||
+ (usize::from(bitslice[10]) << 10)
|
+ (usize::from(bitslice[0]) << 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
@ -127,9 +133,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let entropy = &mut [0u8; 256 / 8];
|
let entropy = &mut [0u8; 256 / 8];
|
||||||
random_handle.read_exact(&mut entropy[..])?;
|
random_handle.read_exact(&mut entropy[..])?;
|
||||||
|
|
||||||
let mut hasher = Sha256::new();
|
let hash = generate_slice_hash(entropy);
|
||||||
hasher.update(&entropy);
|
|
||||||
let hash = hasher.finalize();
|
|
||||||
let checksum = u8_to_bitslice(&hash[1]);
|
let checksum = u8_to_bitslice(&hash[1]);
|
||||||
|
|
||||||
let mut seed_bits = entropy[..bit_size / 8]
|
let mut seed_bits = entropy[..bit_size / 8]
|
||||||
|
@ -149,3 +153,49 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn has_good_wordlist() {
|
||||||
|
let wordlist = build_wordlist();
|
||||||
|
assert_eq!(
|
||||||
|
wordlist.len(),
|
||||||
|
2usize.pow(11),
|
||||||
|
"Wordlist did not include correct word count"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn loads_mnemonics() -> Result<(), Box<dyn super::Error>> {
|
||||||
|
let content = include_str!("test/vectors.json");
|
||||||
|
let jsonobj: serde_json::Value = serde_json::from_str(content)?;
|
||||||
|
let wordlist = build_wordlist();
|
||||||
|
|
||||||
|
for test in jsonobj["english"].as_array().unwrap() {
|
||||||
|
let [ref hex_, ref seed, ..] = test.as_array().unwrap()[..] else {
|
||||||
|
panic!("bad test: {test}");
|
||||||
|
};
|
||||||
|
let hex = hex::decode(hex_.as_str().unwrap()).unwrap();
|
||||||
|
let hash = generate_slice_hash(&hex);
|
||||||
|
let checksum = u8_to_bitslice(&hash.iter().next().unwrap());
|
||||||
|
let mut seed_bits = hex.iter().flat_map(u8_to_bitslice).collect::<Vec<_>>();
|
||||||
|
seed_bits.extend(if hex.len() == 256 / 8 {
|
||||||
|
&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()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
panic!("{}", words.join(" "));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue