From ff45f829b41ff3784500b3922f96169fb0031e08 Mon Sep 17 00:00:00 2001 From: redshiftzero Date: Fri, 8 Sep 2023 17:52:28 -0400 Subject: [PATCH] test: add BIP39 seed vectors --- crates/core/keys/src/keys/bip44.rs | 4 +-- crates/core/keys/src/keys/seed_phrase.rs | 42 +++++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/crates/core/keys/src/keys/bip44.rs b/crates/core/keys/src/keys/bip44.rs index f3f4036cb0..0fa595804c 100644 --- a/crates/core/keys/src/keys/bip44.rs +++ b/crates/core/keys/src/keys/bip44.rs @@ -38,12 +38,12 @@ impl Bip44Path { /// Per BIP44, coin type is a constant set for each currency. pub fn coin_type(&self) -> u32 { - self.coin_type + self.coin_type | 0x80000000 } /// Per BIP44, account splits the key space into independent user identities. pub fn account(&self) -> u32 { - self.account + self.account | 0x80000000 } /// Change is set to 1 to denote change addresses. diff --git a/crates/core/keys/src/keys/seed_phrase.rs b/crates/core/keys/src/keys/seed_phrase.rs index 2dfe9bbfbd..2fcfb1ac0b 100644 --- a/crates/core/keys/src/keys/seed_phrase.rs +++ b/crates/core/keys/src/keys/seed_phrase.rs @@ -217,6 +217,8 @@ fn convert_bits_to_usize(bits: &[bool]) -> usize { #[cfg(test)] mod tests { + use hmac::Hmac; + use pbkdf2::pbkdf2; use std::str::FromStr; use super::*; @@ -224,7 +226,7 @@ mod tests { #[test] fn bip39_mnemonic_derivation() { // These test vectors are taken from: https://github.com/trezor/python-mnemonic/blob/master/vectors.json - let randomness_arr: [&str; 16] = [ + let randomness_arr = [ "00000000000000000000000000000000", "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", "80808080808080808080808080808080", @@ -242,7 +244,7 @@ mod tests { "066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad", "f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f", ]; - let expected_phrase_arr: [&str; 16] = [ + let expected_phrase_arr = [ "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", "legal winner thank year wave sausage worth useful legal winner thank yellow", "letter advice cage absurd amount doctor acoustic avoid letter advice cage above", @@ -260,9 +262,29 @@ mod tests { "all hour make first leader extend hole alien behind guard gospel lava path output census museum junior mass reopen famous sing advance salt reform", "void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold", ]; + let seed_result_arr = [ + "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", + "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607", + "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8", + "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a13332572917f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069", + "274ddc525802f7c828d8ef7ddbcdc5304e87ac3535913611fbbfa986d0c9e5476c91689f9c8a54fd55bd38606aa6a8595ad213d4c9c9f9aca3fb217069a41028", + "ea725895aaae8d4c1cf682c1bfd2d358d52ed9f0f0591131b559e2724bb234fca05aa9c02c57407e04ee9dc3b454aa63fbff483a8b11de949624b9f1831a9612", + "deb5f45449e615feff5640f2e49f933ff51895de3b4381832b3139941c57b59205a42480c52175b6efcffaa58a2503887c1e8b363a707256bdd2b587b46541f5", + "2aaa9242daafcee6aa9d7269f17d4efe271e1b9a529178d7dc139cd18747090bf9d60295d0ce74309a78852a9caadf0af48aae1c6253839624076224374bc63f", + "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8", + "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87", + "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f", + "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad", + "64c87cde7e12ecf6704ab95bb1408bef047c22db4cc7491c4271d170a1b213d20b385bc1588d9c7b38f1b39d415665b8a9030c9ec653d75e65f847d8fc1fc440", + "72be8e052fc4919d2adf28d5306b5474b0069df35b02303de8c1729c9538dbb6fc2d731d5f832193cd9fb6aeecbc469594a70e3dd50811b5067f3b88b28c3e8d", + "26e975ec644423f4a4c4f4215ef09b4bd7ef924e85d1d17c4cf3f136c2863cf6df0a475045652c57eb5fb41513ca2a2d67722b77e954b4b3fc11f7590449191d", + "01f5bced59dec48e362f2c45b5de68b9fd6c92c6634f44d6d40aab69056506f0e35524a518034ddc1192e1dacd32c1ed3eaa3c3b131c88ed8e7e54c49a5d0998", + ]; - for (hex_randomness, expected_phrase) in - randomness_arr.iter().zip(expected_phrase_arr.iter()) + for (i, (hex_randomness, expected_phrase)) in randomness_arr + .iter() + .zip(expected_phrase_arr.iter()) + .enumerate() { let randomness = hex::decode(hex_randomness).expect("can decode test vector"); let actual_phrase = SeedPhrase::from_randomness(&randomness[..]); @@ -270,6 +292,18 @@ mod tests { actual_phrase .verify_checksum() .expect("checksum should validate"); + + let password = format!("{actual_phrase}"); + let mut seed_bytes = [0u8; 64]; + pbkdf2::>( + password.as_bytes(), + "mnemonicTREZOR".as_bytes(), + NUM_PBKDF2_ROUNDS, + &mut seed_bytes, + ) + .expect("seed phrase hash always succeeds"); + let seed_result = hex::encode(seed_bytes); + assert_eq!(seed_result, seed_result_arr[i]); } }