diff --git a/key_protocol/Cargo.toml b/key_protocol/Cargo.toml index 39c1028..91bea9b 100644 --- a/key_protocol/Cargo.toml +++ b/key_protocol/Cargo.toml @@ -4,6 +4,8 @@ version = "0.1.0" edition = "2024" [dependencies] +secp256k1 = "0.31.1" + nssa.workspace = true nssa_core.workspace = true common.workspace = true @@ -19,4 +21,4 @@ aes-gcm.workspace = true bip39.workspace = true hmac-sha512.workspace = true thiserror.workspace = true -itertools.workspace = true +itertools.workspace = true \ No newline at end of file diff --git a/key_protocol/src/key_management/key_tree/keys_public.rs b/key_protocol/src/key_management/key_tree/keys_public.rs index d89bc8c..1ef168e 100644 --- a/key_protocol/src/key_management/key_tree/keys_public.rs +++ b/key_protocol/src/key_management/key_tree/keys_public.rs @@ -1,10 +1,8 @@ -use secp256k1::{Scalar, SecretKey}; +use secp256k1::Scalar; use serde::{Deserialize, Serialize}; use crate::key_management::key_tree::traits::KeyNode; -const TWO_POWER_31: u32 = (2u32).pow(31); - #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ChildKeysPublic { pub csk: nssa::PrivateKey, @@ -15,20 +13,25 @@ pub struct ChildKeysPublic { } impl ChildKeysPublic { - fn nth_child_nonharden_hash(&self, cci: u32) -> [u8; 64] { + fn compute_hash_value(self, cci: u32) -> [u8; 64] { let mut hash_input = vec![]; - hash_input.extend_from_slice(self.cpk.value()); - hash_input.extend_from_slice(&cci.to_le_bytes()); - hmac_sha512::HMAC::mac(hash_input, self.ccc) - } + match ((2u32).pow(31)).cmp(&cci) { + // Harden + std::cmp::Ordering::Less => { + hash_input.extend_from_slice(self.csk.value()); + hash_input.extend_from_slice(&(cci).to_le_bytes()); - fn nth_child_harden_hash(&self, cci: u32) -> [u8; 64] { - let mut hash_input = vec![]; - hash_input.extend_from_slice(self.csk.value()); - hash_input.extend_from_slice(&(cci - TWO_POWER_31).to_le_bytes()); + hmac_sha512::HMAC::mac(hash_input, self.ccc) + } + // Non-harden + _ => { + hash_input.extend_from_slice(self.cpk.value()); + hash_input.extend_from_slice(&cci.to_le_bytes()); - hmac_sha512::HMAC::mac(hash_input, self.ccc) + hmac_sha512::HMAC::mac(hash_input, self.ccc) + } + } } } @@ -49,19 +52,9 @@ impl KeyNode for ChildKeysPublic { } fn nth_child(&self, cci: u32) -> Self { - let mut hash_input = vec![]; - hash_input.extend_from_slice(self.cpk.value()); - hash_input.extend_from_slice(&cci.to_le_bytes()); + let hash_value = self.clone().compute_hash_value(cci); - let hash_value = match ((2u32).pow(31)).cmp(&cci) { - // Harden - std::cmp::Ordering::Less => self.nth_child_harden_hash(cci), - // Non-harden - std::cmp::Ordering::Greater => self.nth_child_nonharden_hash(cci), - std::cmp::Ordering::Equal => self.nth_child_nonharden_hash(cci), - }; - - let mut csk = secp256k1::SecretKey::from_byte_array( + let csk = secp256k1::SecretKey::from_byte_array( *hash_value .first_chunk::<32>() .expect("hash_value is 64 bytes, must be safe to get first 32"), @@ -77,7 +70,7 @@ impl KeyNode for ChildKeysPublic { if secp256k1::constants::CURVE_ORDER < *csk.value() { panic!("Secret key cannot exceed curve order"); - } + } let ccc = *hash_value .last_chunk::<32>() @@ -114,8 +107,8 @@ impl<'a> From<&'a ChildKeysPublic> for &'a nssa::PrivateKey { #[cfg(test)] mod tests { - use nssa::{PrivateKey, PublicKey}; use super::*; + use nssa::{PrivateKey, PublicKey}; #[test] fn test_master_keys_generation() { @@ -166,19 +159,19 @@ mod tests { ); let expected_ccc = [ - 84, 37, 139, 254, 228, 162, 42, 156, 65, 175, 48, 210, 234, 18, 153, 90, 203, 87, 194, - 213, 17, 80, 170, 211, 99, 192, 133, 85, 120, 188, 130, 6, + 1, 19, 186, 27, 153, 246, 163, 56, 19, 66, 184, 252, 125, 91, 229, 55, 22, 186, 129, + 78, 67, 38, 102, 167, 88, 237, 142, 162, 165, 105, 67, 250, ]; let expected_csk: PrivateKey = PrivateKey::try_new([ - 210, 196, 140, 88, 194, 249, 219, 180, 242, 207, 206, 205, 41, 160, 89, 179, 221, 155, - 134, 237, 180, 175, 84, 102, 216, 219, 128, 135, 89, 180, 13, 177, + 93, 255, 132, 159, 52, 30, 43, 128, 106, 84, 99, 16, 193, 37, 224, 142, 208, 87, 142, + 156, 175, 116, 90, 204, 157, 219, 136, 109, 230, 223, 76, 70, ]) .unwrap(); let expected_cpk: PublicKey = PublicKey::try_new([ - 130, 250, 109, 211, 83, 152, 36, 53, 47, 197, 199, 161, 150, 96, 126, 20, 39, 43, 36, - 75, 132, 30, 50, 245, 206, 61, 83, 103, 193, 223, 83, 147, + 78, 123, 221, 195, 111, 255, 131, 167, 117, 146, 61, 161, 179, 51, 250, 25, 90, 187, + 190, 163, 30, 145, 212, 87, 88, 127, 86, 5, 45, 236, 184, 223, ]) .unwrap(); @@ -226,13 +219,44 @@ mod tests { assert!(expected_csk == child_keys.csk); assert!(expected_cpk == child_keys.cpk); } + + #[test] + fn test_edge_case_child_keys_generation_2_power_32() { + let seed = [ + 88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173, + 134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87, + 22, 227, 38, 71, 17, 144, 251, 118, 217, 115, 33, 222, 201, 61, 203, 246, 121, 214, 6, + 187, 148, 92, 44, 253, 210, 37, + ]; + let root_keys = ChildKeysPublic::root(seed); + let cci = (2u32).pow(32); //equivant to 0, thus non-harden. + let child_keys = ChildKeysPublic::nth_child(&root_keys, cci); + + print!( + "{} {}", + child_keys.csk.value()[0], + child_keys.csk.value()[1] + ); + + let expected_ccc = [ + 196, 27, 223, 192, 33, 28, 41, 165, 247, 198, 251, 26, 63, 85, 223, 6, 57, 201, 10, 46, + 189, 152, 39, 69, 28, 30, 112, 167, 211, 175, 170, 75, + ]; + + let expected_csk: PrivateKey = PrivateKey::try_new([ + 55, 68, 204, 198, 234, 171, 247, 60, 177, 24, 216, 130, 62, 115, 130, 156, 94, 90, 156, + 8, 160, 126, 14, 33, 214, 184, 79, 127, 88, 87, 95, 217, + ]) + .unwrap(); + + let expected_cpk: PublicKey = PublicKey::try_new([ + 222, 5, 102, 223, 97, 95, 83, 100, 114, 154, 15, 248, 164, 117, 209, 125, 193, 19, 64, + 75, 245, 168, 52, 199, 45, 39, 237, 232, 175, 3, 167, 178, + ]) + .unwrap(); + + assert!(expected_ccc == child_keys.ccc); + assert!(expected_csk == child_keys.csk); + assert!(expected_cpk == child_keys.cpk); + } } - -/* -[2, 14, 243, 116, 96, 0, 81, 219, 86, 228, 188, 116, 201, 71, 176, 107, 84, 4, 196, 176, 100, 140, 111, 57, 126, 38, 84, 91, 40, 154, 53, 12, 54] -Secret child key -[194, 38, 83, 68, 93, 201, 23, 245, 127, 216, 162, 139, 59, 19, 119, 40, 105, 126, 19, 219, 246, 219, 74, 217, 152, 159, 177, 235, 109, 237, 171, 194] -Child chain code -[84, 37, 139, 254, 228, 162, 42, 156, 65, 175, 48, 210, 234, 18, 153, 90, 203, 87, 194, 213, 17, 80, 170, 211, 99, 192, 133, 85, 120, 188, 130, 6] - -*/