diff --git a/indexer/service/configs/indexer_config.json b/indexer/service/configs/indexer_config.json index e4dd8f93..30ae0e64 100644 --- a/indexer/service/configs/indexer_config.json +++ b/indexer/service/configs/indexer_config.json @@ -11,11 +11,11 @@ "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", "initial_accounts": [ { - "account_id": "CbgR6tj5kWx5oziiFptM7jMvrQeYY3Mzaao6ciuhSr2r", + "account_id": "jZvdpERLqEkzk6CAz6vDuDJ1wx5aoyFpDa1VFmRvuPX", "balance": 10000 }, { - "account_id": "2RHZhw9h534Zr3eq2RGhQete2Hh667foECzXPmSkGni2", + "account_id": "3jQfsyRyvVpBfdkZegf8QpjfcDq1M5RAXB4H4eJ4kTtf", "balance": 20000 } ], 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 73ed7bee..d7c4f7cd 100644 --- a/key_protocol/src/key_management/key_tree/keys_public.rs +++ b/key_protocol/src/key_management/key_tree/keys_public.rs @@ -5,6 +5,7 @@ use crate::key_management::key_tree::traits::KeyNode; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ChildKeysPublic { + pub cssk: nssa::PrivateKey, pub csk: nssa::PrivateKey, pub cpk: nssa::PublicKey, pub ccc: [u8; 32], @@ -21,14 +22,14 @@ impl ChildKeysPublic { // Non-harden. // BIP-032 compatibility requires 1-byte header from the public_key; // Not stored in `self.cpk.value()`. - let sk = secp256k1::SecretKey::from_byte_array(*self.csk.value()) + let sk = secp256k1::SecretKey::from_byte_array(*self.cssk.value()) .expect("32 bytes, within curve order"); let pk = secp256k1::PublicKey::from_secret_key(&secp256k1::Secp256k1::new(), &sk); hash_input.extend_from_slice(&secp256k1::PublicKey::serialize(&pk)); } else { // Harden. hash_input.extend_from_slice(&[0_u8]); - hash_input.extend_from_slice(self.csk.value()); + hash_input.extend_from_slice(self.cssk.value()); } hash_input.extend_from_slice(&cci.to_be_bytes()); @@ -41,11 +42,13 @@ impl KeyNode for ChildKeysPublic { fn root(seed: [u8; 64]) -> Self { let hash_value = hmac_sha512::HMAC::mac(seed, "LEE_master_pub"); - let csk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap(); + let cssk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap(); + let csk = nssa::PrivateKey::tweak(cssk.value()).unwrap(); let ccc = *hash_value.last_chunk::<32>().unwrap(); let cpk = nssa::PublicKey::new_from_private_key(&csk); Self { + cssk, csk, cpk, ccc, @@ -56,22 +59,22 @@ impl KeyNode for ChildKeysPublic { fn nth_child(&self, cci: u32) -> Self { let hash_value = self.compute_hash_value(cci); - let csk = secp256k1::SecretKey::from_byte_array( + let cssk = secp256k1::SecretKey::from_byte_array( *hash_value .first_chunk::<32>() .expect("hash_value is 64 bytes, must be safe to get first 32"), ) .unwrap(); - let csk = nssa::PrivateKey::try_new({ - let scalar = Scalar::from_be_bytes(*self.csk.value()).unwrap(); - - csk.add_tweak(&scalar) + let cssk = nssa::PrivateKey::try_new({ + cssk.add_tweak(&Scalar::from_be_bytes(*self.cssk.value()).unwrap()) .expect("Expect a valid Scalar") .secret_bytes() }) .unwrap(); + let csk = nssa::PrivateKey::tweak(cssk.value()).unwrap(); + assert!( secp256k1::constants::CURVE_ORDER >= *csk.value(), "Secret key cannot exceed curve order" @@ -84,6 +87,7 @@ impl KeyNode for ChildKeysPublic { let cpk = nssa::PublicKey::new_from_private_key(&csk); Self { + cssk, csk, cpk, ccc, @@ -135,19 +139,26 @@ mod tests { 13, 146, 126, 232, 239, 113, 9, 194, 219, 190, 48, 187, 155, ]; - let expected_csk: PrivateKey = PrivateKey::try_new([ + let expected_cssk: PrivateKey = PrivateKey::try_new([ 40, 35, 239, 19, 53, 178, 250, 55, 115, 12, 34, 3, 153, 153, 72, 170, 190, 36, 172, 36, 202, 148, 181, 228, 35, 222, 58, 84, 156, 24, 146, 86, ]) .unwrap(); + let expected_csk: PrivateKey = PrivateKey::try_new([ + 207, 4, 246, 223, 104, 72, 19, 85, 14, 122, 194, 82, 32, 163, 60, 57, 8, 25, 209, 91, + 254, 107, 76, 238, 31, 68, 236, 192, 154, 78, 105, 118, + ]) + .unwrap(); + let expected_cpk: PublicKey = PublicKey::try_new([ - 219, 141, 130, 105, 11, 203, 187, 124, 112, 75, 223, 22, 11, 164, 153, 127, 59, 247, - 244, 166, 75, 66, 242, 224, 35, 156, 161, 75, 41, 51, 76, 245, + 188, 163, 203, 45, 151, 154, 230, 254, 123, 114, 158, 130, 19, 182, 164, 143, 150, 131, + 176, 7, 27, 58, 204, 116, 5, 247, 0, 255, 111, 160, 52, 201, ]) .unwrap(); assert!(expected_ccc == keys.ccc); + assert!(expected_cssk == keys.cssk); assert!(expected_csk == keys.csk); assert!(expected_cpk == keys.cpk); } @@ -169,19 +180,26 @@ mod tests { 130, 126, 123, 20, 90, 34, 173, 209, 101, 248, 155, 36, ]; - let expected_csk: PrivateKey = PrivateKey::try_new([ + let expected_cssk: PrivateKey = PrivateKey::try_new([ 9, 65, 33, 228, 25, 82, 219, 117, 91, 217, 11, 223, 144, 85, 246, 26, 123, 216, 107, 213, 33, 52, 188, 22, 198, 246, 71, 46, 245, 174, 16, 47, ]) .unwrap(); + let expected_csk: PrivateKey = PrivateKey::try_new([ + 100, 37, 212, 81, 40, 233, 72, 156, 177, 139, 50, 114, 136, 157, 202, 132, 203, 246, + 252, 242, 13, 81, 42, 100, 159, 240, 187, 252, 202, 108, 25, 105, + ]) + .unwrap(); + let expected_cpk: PublicKey = PublicKey::try_new([ - 142, 143, 238, 159, 105, 165, 224, 252, 108, 62, 53, 209, 176, 219, 249, 38, 90, 241, - 201, 81, 194, 146, 236, 5, 83, 152, 238, 243, 138, 16, 229, 15, + 210, 59, 119, 137, 21, 153, 82, 22, 195, 82, 12, 16, 80, 156, 125, 199, 19, 173, 46, + 224, 213, 144, 165, 126, 70, 129, 171, 141, 77, 212, 108, 233, ]) .unwrap(); assert!(expected_ccc == child_keys.ccc); + assert!(expected_cssk == child_keys.cssk); assert!(expected_csk == child_keys.csk); assert!(expected_cpk == child_keys.cpk); } @@ -203,19 +221,26 @@ mod tests { 16, 28, 79, 80, 232, 216, 101, 145, 19, 101, 220, 217, 141, ]; - let expected_csk: PrivateKey = PrivateKey::try_new([ + let expected_cssk: PrivateKey = PrivateKey::try_new([ 185, 147, 32, 242, 145, 91, 123, 77, 42, 33, 134, 84, 12, 165, 117, 70, 158, 201, 95, 153, 14, 12, 92, 235, 128, 156, 194, 169, 68, 35, 165, 127, ]) .unwrap(); + let expected_csk: PrivateKey = PrivateKey::try_new([ + 215, 157, 181, 165, 200, 92, 8, 103, 239, 104, 39, 41, 150, 199, 17, 205, 77, 179, 188, + 27, 168, 216, 198, 12, 94, 11, 72, 131, 148, 44, 166, 128, + ]) + .unwrap(); + let expected_cpk: PublicKey = PublicKey::try_new([ - 119, 16, 145, 121, 97, 244, 186, 35, 136, 34, 140, 171, 206, 139, 11, 208, 207, 121, - 158, 45, 28, 22, 140, 98, 161, 179, 212, 173, 238, 220, 2, 34, + 210, 66, 25, 100, 233, 50, 82, 94, 139, 83, 39, 52, 196, 241, 123, 248, 177, 10, 249, + 206, 71, 167, 198, 5, 202, 184, 178, 148, 106, 231, 214, 235, ]) .unwrap(); assert!(expected_ccc == child_keys.ccc); + assert!(expected_cssk == child_keys.cssk); assert!(expected_csk == child_keys.csk); assert!(expected_cpk == child_keys.cpk); } @@ -237,19 +262,26 @@ mod tests { 58, 215, 40, 246, 111, 166, 113, 183, 145, 173, 11, 27, 182, ]; - let expected_csk: PrivateKey = PrivateKey::try_new([ + let expected_cssk: PrivateKey = PrivateKey::try_new([ 223, 29, 87, 189, 126, 24, 117, 225, 190, 57, 0, 143, 207, 168, 231, 139, 170, 192, 81, 254, 126, 10, 115, 42, 141, 157, 70, 171, 199, 231, 198, 132, ]) .unwrap(); + let expected_csk: PrivateKey = PrivateKey::try_new([ + 35, 70, 190, 115, 134, 106, 151, 84, 164, 16, 139, 204, 100, 203, 36, 219, 91, 200, 6, + 52, 120, 67, 35, 82, 14, 197, 163, 27, 248, 162, 129, 159, + ]) + .unwrap(); + let expected_cpk: PublicKey = PublicKey::try_new([ - 96, 123, 245, 51, 214, 216, 215, 205, 70, 145, 105, 221, 166, 169, 122, 27, 94, 112, - 228, 110, 249, 177, 85, 173, 180, 248, 185, 199, 112, 246, 83, 33, + 61, 182, 68, 167, 177, 158, 173, 101, 79, 212, 191, 179, 169, 131, 220, 232, 123, 203, + 235, 244, 72, 251, 159, 98, 215, 85, 103, 49, 124, 137, 98, 39, ]) .unwrap(); assert!(expected_ccc == child_keys.ccc); + assert!(expected_cssk == child_keys.cssk); assert!(expected_csk == child_keys.csk); assert!(expected_cpk == child_keys.cpk); } diff --git a/key_protocol/src/key_management/key_tree/mod.rs b/key_protocol/src/key_management/key_tree/mod.rs index 08a576e5..f6168f02 100644 --- a/key_protocol/src/key_management/key_tree/mod.rs +++ b/key_protocol/src/key_management/key_tree/mod.rs @@ -283,8 +283,8 @@ mod tests { assert!(tree.key_map.contains_key(&ChainIndex::root())); assert!(tree.account_id_map.contains_key(&AccountId::new([ - 172, 82, 222, 249, 164, 16, 148, 184, 219, 56, 92, 145, 203, 220, 251, 89, 214, 178, - 38, 30, 108, 202, 251, 241, 148, 200, 125, 185, 93, 227, 189, 247 + 10, 231, 159, 65, 236, 46, 205, 5, 172, 89, 250, 29, 123, 195, 212, 137, 155, 111, 40, + 120, 53, 28, 124, 54, 224, 170, 119, 208, 2, 72, 75, 50 ]))); } diff --git a/nssa/src/signature/private_key.rs b/nssa/src/signature/private_key.rs index e73e0e4f..72c392db 100644 --- a/nssa/src/signature/private_key.rs +++ b/nssa/src/signature/private_key.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use rand::{Rng as _, rngs::OsRng}; +use risc0_zkvm::sha::{Impl, Sha256 as _}; use serde_with::{DeserializeFromStr, SerializeDisplay}; use crate::error::NssaError; @@ -60,6 +61,28 @@ impl PrivateKey { pub const fn value(&self) -> &[u8; 32] { &self.0 } + + pub fn tweak(value: &[u8; 32]) -> Result { + assert!(Self::is_valid_key(*value)); + + let sk = secp256k1::SecretKey::from_byte_array(*value).expect("Expect a valid secret key"); + + let mut bytes = vec![]; + let pk = secp256k1::PublicKey::from_secret_key(&secp256k1::Secp256k1::new(), &sk); + bytes.extend_from_slice(&secp256k1::PublicKey::serialize(&pk)); + let hashed: [u8; 32] = Impl::hash_bytes(&bytes) + .as_bytes() + .try_into() + .expect("Sha256 outputs a 32-byte array"); + + Self::try_new( + sk.add_tweak( + &secp256k1::Scalar::from_be_bytes(hashed).expect("Expect a valid secp256k1 Scalar"), + ) + .expect("Expect a valid Scalar") + .secret_bytes(), + ) + } } #[cfg(test)] diff --git a/sequencer/service/configs/debug/sequencer_config.json b/sequencer/service/configs/debug/sequencer_config.json index 4088fc4a..d11cb789 100644 --- a/sequencer/service/configs/debug/sequencer_config.json +++ b/sequencer/service/configs/debug/sequencer_config.json @@ -18,11 +18,11 @@ "indexer_rpc_url": "ws://localhost:8779", "initial_accounts": [ { - "account_id": "CbgR6tj5kWx5oziiFptM7jMvrQeYY3Mzaao6ciuhSr2r", + "account_id": "jZvdpERLqEkzk6CAz6vDuDJ1wx5aoyFpDa1VFmRvuPX", "balance": 10000 }, { - "account_id": "2RHZhw9h534Zr3eq2RGhQete2Hh667foECzXPmSkGni2", + "account_id": "3jQfsyRyvVpBfdkZegf8QpjfcDq1M5RAXB4H4eJ4kTtf", "balance": 20000 } ], diff --git a/sequencer/service/configs/docker/sequencer_config.json b/sequencer/service/configs/docker/sequencer_config.json index f5a243d5..b41711f7 100644 --- a/sequencer/service/configs/docker/sequencer_config.json +++ b/sequencer/service/configs/docker/sequencer_config.json @@ -18,11 +18,11 @@ "indexer_rpc_url": "ws://localhost:8779", "initial_accounts": [ { - "account_id": "CbgR6tj5kWx5oziiFptM7jMvrQeYY3Mzaao6ciuhSr2r", + "account_id": "jZvdpERLqEkzk6CAz6vDuDJ1wx5aoyFpDa1VFmRvuPX", "balance": 10000 }, { - "account_id": "2RHZhw9h534Zr3eq2RGhQete2Hh667foECzXPmSkGni2", + "account_id": "3jQfsyRyvVpBfdkZegf8QpjfcDq1M5RAXB4H4eJ4kTtf", "balance": 20000 } ], diff --git a/wallet/configs/debug/wallet_config.json b/wallet/configs/debug/wallet_config.json index 6604f65b..021cc10a 100644 --- a/wallet/configs/debug/wallet_config.json +++ b/wallet/configs/debug/wallet_config.json @@ -7,14 +7,80 @@ "initial_accounts": [ { "Public": { - "account_id": "CbgR6tj5kWx5oziiFptM7jMvrQeYY3Mzaao6ciuhSr2r", - "pub_sign_key": "7f273098f25b71e6c005a9519f2678da8d1c7f01f6a27778e2d9948abdf901fb" + "account_id": "jZvdpERLqEkzk6CAz6vDuDJ1wx5aoyFpDa1VFmRvuPX", + "pub_sign_key": [ + 157, + 102, + 173, + 116, + 76, + 167, + 130, + 165, + 77, + 104, + 14, + 233, + 114, + 43, + 180, + 98, + 59, + 187, + 165, + 28, + 80, + 130, + 126, + 164, + 224, + 181, + 203, + 53, + 31, + 168, + 169, + 23 + ] } }, { "Public": { - "account_id": "2RHZhw9h534Zr3eq2RGhQete2Hh667foECzXPmSkGni2", - "pub_sign_key": "f434f8741720014586ae43356d2aec6257da086222f604ddb75d69733b86fc4c" + "account_id": "3jQfsyRyvVpBfdkZegf8QpjfcDq1M5RAXB4H4eJ4kTtf", + "pub_sign_key": [ + 230, + 17, + 4, + 52, + 87, + 162, + 72, + 137, + 119, + 205, + 163, + 211, + 118, + 157, + 15, + 164, + 67, + 12, + 124, + 50, + 159, + 23, + 184, + 6, + 109, + 154, + 2, + 219, + 147, + 239, + 125, + 20 + ] } }, {