From e3764e1911aea3b8dedb73ac1c2292d10f72149e Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Thu, 5 Mar 2026 12:35:18 +0200 Subject: [PATCH] fix: shared secret receiver fix --- .../key_management/key_tree/chain_index.rs | 4 + key_protocol/src/key_management/mod.rs | 7 +- nssa/core/src/encryption/mod.rs | 13 +- wallet/src/lib.rs | 249 ++++++++++++++++-- 4 files changed, 254 insertions(+), 19 deletions(-) diff --git a/key_protocol/src/key_management/key_tree/chain_index.rs b/key_protocol/src/key_management/key_tree/chain_index.rs index 6dbaf9a9..d5fbf401 100644 --- a/key_protocol/src/key_management/key_tree/chain_index.rs +++ b/key_protocol/src/key_management/key_tree/chain_index.rs @@ -68,6 +68,10 @@ impl ChainIndex { &self.0 } + pub fn index(&self) -> Option { + self.chain().last().copied() + } + pub fn next_in_line(&self) -> ChainIndex { let mut chain = self.0.clone(); // ToDo: Add overflow check diff --git a/key_protocol/src/key_management/mod.rs b/key_protocol/src/key_management/mod.rs index d46dcf35..31848f4c 100644 --- a/key_protocol/src/key_management/mod.rs +++ b/key_protocol/src/key_management/mod.rs @@ -62,9 +62,10 @@ impl KeyChain { pub fn calculate_shared_secret_receiver( &self, ephemeral_public_key_sender: EphemeralPublicKey, + index: Option, ) -> SharedSecretKey { SharedSecretKey::new( - &self.secret_spending_key.generate_viewing_secret_key(None), + &self.secret_spending_key.generate_viewing_secret_key(index), &ephemeral_public_key_sender, ) } @@ -101,8 +102,8 @@ mod tests { let ephemeral_public_key_sender = EphemeralPublicKey::from_scalar(scalar); // Calculate shared secret - let _shared_secret = - account_id_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + let _shared_secret = account_id_key_holder + .calculate_shared_secret_receiver(ephemeral_public_key_sender, None); } #[test] diff --git a/nssa/core/src/encryption/mod.rs b/nssa/core/src/encryption/mod.rs index 9ccbf2c8..4817d3c8 100644 --- a/nssa/core/src/encryption/mod.rs +++ b/nssa/core/src/encryption/mod.rs @@ -75,6 +75,17 @@ impl EncryptionScheme { Self::symmetric_transform(&mut buffer, shared_secret, commitment, output_index); let mut cursor = Cursor::new(buffer.as_slice()); - Account::from_cursor(&mut cursor).ok() + Account::from_cursor(&mut cursor) + .inspect_err(|err| { + println!( + "Failed to decode {ciphertext:?} \n + with secret {:?} ,\n + commitment {commitment:?} ,\n + and output_index {output_index} ,\n + with error {err:?}", + shared_secret.0 + ) + }) + .ok() } } diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 0162dcb1..f3755b0b 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -363,11 +363,24 @@ impl WalletCore { ); let tx = PrivacyPreservingTransaction::new(message, witness_set); - let shared_secrets = private_account_keys + let shared_secrets: Vec<_> = private_account_keys .into_iter() .map(|keys| keys.ssk) .collect(); + // ["dbfa57c178c287057c94f2fa8caaf78649d1dcac8d4eec0759264a22ebc788b4", + // "e3aa7298c9cc409f001e425caf139d0f5d627201fa60c0868d68f200c9044825"] + // ["dbfa57c178c287057c94f2fa8caaf78649d1dcac8d4eec0759264a22ebc788b4", + // "17a5070917903d5213db9ce9442ba472d8682af318fb5369e5c784c3980cacc9"] + + info!( + "shared secrets is {:?}", + shared_secrets + .iter() + .map(|secret| hex::encode(secret.0)) + .collect::>() + ); + Ok(( self.sequencer_client.send_tx_private(tx).await?, shared_secrets, @@ -419,18 +432,19 @@ impl WalletCore { .user_data .default_user_private_accounts .iter() - .map(|(acc_account_id, (key_chain, _))| (*acc_account_id, key_chain)) - .chain( - self.storage - .user_data - .private_key_tree - .key_map - .values() - .map(|keys_node| (keys_node.account_id(), &keys_node.value.0)), - ); + .map(|(acc_account_id, (key_chain, _))| (*acc_account_id, key_chain, None)) + .chain(self.storage.user_data.private_key_tree.key_map.iter().map( + |(chain_index, keys_node)| { + ( + keys_node.account_id(), + &keys_node.value.0, + chain_index.index(), + ) + }, + )); let affected_accounts = private_account_key_chains - .flat_map(|(acc_account_id, key_chain)| { + .flat_map(|(acc_account_id, key_chain, index)| { let view_tag = EncryptedAccountData::compute_view_tag( key_chain.nullifer_public_key.clone(), key_chain.viewing_public_key.clone(), @@ -444,17 +458,20 @@ impl WalletCore { .filter_map(|(ciph_id, encrypted_data)| { let ciphertext = &encrypted_data.ciphertext; let commitment = &tx.message.new_commitments[ciph_id]; - let shared_secret = - key_chain.calculate_shared_secret_receiver(encrypted_data.epk.clone()); + let shared_secret = key_chain + .calculate_shared_secret_receiver(encrypted_data.epk.clone(), index); - nssa_core::EncryptionScheme::decrypt( + let res = nssa_core::EncryptionScheme::decrypt( ciphertext, &shared_secret, commitment, ciph_id as u32, - ) + ); + + res }) .map(move |res_acc| (acc_account_id, res_acc)) + .collect::>() }) .collect::>(); @@ -479,3 +496,205 @@ impl WalletCore { &self.config_overrides } } + +#[cfg(test)] +mod tests { + use key_protocol::key_management::{KeyChain, ephemeral_key_holder::EphemeralKeyHolder}; + + fn account_for_tests() -> KeyChain { + let key_chain_raw = r#" + { + "secret_spending_key": [ + 208, + 155, + 82, + 128, + 101, + 206, + 20, + 95, + 241, + 147, + 159, + 231, + 207, + 78, + 152, + 28, + 114, + 111, + 61, + 69, + 254, + 51, + 242, + 28, + 28, + 195, + 170, + 242, + 160, + 24, + 47, + 189 + ], + "private_key_holder": { + "nullifier_secret_key": [ + 142, + 76, + 154, + 157, + 42, + 40, + 174, + 199, + 151, + 63, + 2, + 216, + 52, + 103, + 81, + 42, + 200, + 177, + 189, + 49, + 81, + 39, + 166, + 139, + 203, + 154, + 156, + 166, + 88, + 159, + 11, + 151 + ], + "viewing_secret_key": [ + 122, + 94, + 159, + 21, + 28, + 49, + 169, + 79, + 12, + 156, + 171, + 90, + 41, + 216, + 203, + 75, + 251, + 192, + 204, + 217, + 18, + 49, + 28, + 219, + 213, + 147, + 244, + 194, + 205, + 237, + 134, + 36 + ] + }, + "nullifer_public_key": [ + 235, + 24, + 62, + 99, + 243, + 236, + 137, + 35, + 153, + 149, + 6, + 10, + 118, + 239, + 117, + 188, + 64, + 8, + 33, + 52, + 220, + 231, + 11, + 39, + 180, + 117, + 1, + 22, + 62, + 199, + 164, + 169 + ], + "viewing_public_key": [ + 2, + 253, + 204, + 5, + 212, + 86, + 249, + 156, + 132, + 143, + 1, + 172, + 80, + 61, + 18, + 185, + 233, + 36, + 221, + 58, + 64, + 110, + 89, + 242, + 202, + 230, + 154, + 66, + 45, + 252, + 138, + 174, + 37 + ] + } + "#; + + serde_json::from_str(key_chain_raw).unwrap() + } + + #[test] + fn test_1() { + let keys = account_for_tests(); + + let eph_key_holder = EphemeralKeyHolder::new(&keys.nullifer_public_key); + + let key_sender = eph_key_holder.calculate_shared_secret_sender(&keys.viewing_public_key); + let key_receiver = keys.calculate_shared_secret_receiver( + eph_key_holder.generate_ephemeral_public_key(), + Some(2), + ); + + assert_eq!(key_sender.0, key_receiver.0); + } +}