From daa411c800d799d56303a0440f2949ab112bad24 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 15 Sep 2023 17:20:21 +0200 Subject: [PATCH] Sender generates keys with partial secret --- src/sending.rs | 41 ++++++++++++++++------------------------- tests/common/utils.rs | 10 +++------- tests/vector_tests.rs | 18 +++++++----------- 3 files changed, 26 insertions(+), 43 deletions(-) diff --git a/src/sending.rs b/src/sending.rs index 0dca3da..57e1843 100644 --- a/src/sending.rs +++ b/src/sending.rs @@ -9,6 +9,7 @@ use crate::{ Result, }; +#[derive(Copy, Clone, Debug)] struct SilentPaymentAddress { version: u8, scan_pubkey: PublicKey, @@ -103,7 +104,7 @@ impl Into for SilentPaymentAddress { /// # Arguments /// /// * `recipients` - A `Vec` of silent payment addresses to be paid. -/// * `ecdh_shared_secrets` - A HashMap that maps every scan key (representing a recipient) to a shared secret. This shared secret is created using the scan key, along with the private keys of the outputs to spend. This library has no access to these private keys, so we expect the computed shared secret instead. +/// * `partial_secret` - A `SecretKey` that represents the sum of the private keys of eligible inputs of the transaction multiplied by the hash of its outpoints. /// /// # Returns /// @@ -119,26 +120,22 @@ impl Into for SilentPaymentAddress { /// * Edge cases are hit during elliptic curve computation (extremely unlikely). pub fn generate_multiple_recipient_pubkeys( recipients: Vec, - ecdh_shared_secrets: HashMap, + partial_secret: SecretKey, ) -> Result>> { let secp = Secp256k1::new(); let mut silent_payment_groups: HashMap)> = HashMap::new(); - for recipient in recipients { - let recipient: SilentPaymentAddress = recipient.try_into()?; - let B_scan = recipient.scan_pubkey; + for address in recipients { + let address: SilentPaymentAddress = address.try_into()?; + let B_scan = address.scan_pubkey; if let Some((_, payments)) = silent_payment_groups.get_mut(&B_scan) { - payments.push(recipient); + payments.push(address); } else { - let ecdh_shared_secret = ecdh_shared_secrets - .get(&B_scan) - .ok_or(Error::InvalidSharedSecret( - "Shared secret for this B_scan not found".to_owned(), - ))? - .to_owned(); - silent_payment_groups.insert(B_scan, (ecdh_shared_secret, vec![recipient])); + let ecdh_shared_secret: PublicKey = B_scan.mul_tweak(&secp, &partial_secret.into())?; + + silent_payment_groups.insert(B_scan, (ecdh_shared_secret, vec![address])); } } @@ -148,7 +145,7 @@ pub fn generate_multiple_recipient_pubkeys( let (ecdh_shared_secret, recipients) = group; - for recipient in recipients { + for addr in recipients { let mut bytes: Vec = Vec::new(); bytes.extend_from_slice(&ecdh_shared_secret.serialize()); bytes.extend_from_slice(&ser_uint32(n)); @@ -156,10 +153,10 @@ pub fn generate_multiple_recipient_pubkeys( let t_n = sha256(&bytes); let res = SecretKey::from_slice(&t_n)?.public_key(&secp); - let reskey = res.combine(&recipient.m_pubkey)?; + let reskey = res.combine(&addr.m_pubkey)?; let (reskey_xonly, _) = reskey.x_only_public_key(); - let entry = result.entry(recipient.into()).or_insert_with(Vec::new); + let entry = result.entry(addr.into()).or_insert_with(Vec::new); entry.push(reskey_xonly); n += 1; } @@ -175,7 +172,7 @@ pub fn generate_multiple_recipient_pubkeys( /// # Arguments /// /// * `recipient` - A `String` of the bech32m-encoded silent payment address to be paid. -/// * `ecdh_shared_secret` - A `PublicKey` representing the shared secret. This shared secret is created using the scan key, along with the private keys of the outputs to spend. This library has no access to these private keys, so we expect the computed shared secret instead. +/// * `partial_secret` - A `SecretKey` representing the private keys of the outputs to spend multiplied by the hash of its outpoints. /// /// # Returns /// @@ -189,15 +186,9 @@ pub fn generate_multiple_recipient_pubkeys( /// * Edge cases are hit during elliptic curve computation (extremely unlikely). pub fn generate_recipient_pubkey( recipient: String, - ecdh_shared_secret: PublicKey, + partial_secret: SecretKey, ) -> Result { - let scan_pubkey = decode_scan_pubkey(&recipient)?; - - // re-use generate_recipient_pubkeys function logic - let recipients = vec![recipient]; - let mut ecdh_shared_secrets = HashMap::new(); - ecdh_shared_secrets.insert(scan_pubkey, ecdh_shared_secret); - let res = generate_multiple_recipient_pubkeys(recipients, ecdh_shared_secrets)?; + let res = generate_multiple_recipient_pubkeys(vec![recipient], partial_secret)?; let output = res .into_values() diff --git a/tests/common/utils.rs b/tests/common/utils.rs index 554e1da..19ea061 100644 --- a/tests/common/utils.rs +++ b/tests/common/utils.rs @@ -110,15 +110,11 @@ pub fn calculate_tweak_data_for_recipient( A_sum.mul_tweak(&secp, &outpoints_hash).unwrap() } -pub fn sender_calculate_shared_secret( +pub fn sender_calculate_partial_secret( a_sum: SecretKey, - B_scan: PublicKey, outpoints_hash: Scalar, -) -> PublicKey { - let secp = secp256k1::Secp256k1::new(); - - let diffie_hellman = B_scan.mul_tweak(&secp, &a_sum.into()).unwrap(); - diffie_hellman.mul_tweak(&secp, &outpoints_hash).unwrap() +) -> SecretKey{ + a_sum.mul_tweak(&outpoints_hash).unwrap() } pub fn receiver_calculate_shared_secret( diff --git a/tests/vector_tests.rs b/tests/vector_tests.rs index 922006a..8c24dd6 100644 --- a/tests/vector_tests.rs +++ b/tests/vector_tests.rs @@ -8,20 +8,20 @@ mod tests { str::FromStr, }; - use secp256k1::{PublicKey, Secp256k1, SecretKey, Scalar}; + use secp256k1::{Secp256k1, SecretKey, Scalar}; #[cfg(feature = "receiving")] use silentpayments::receiving::Receiver; #[cfg(feature = "sending")] - use silentpayments::sending::{decode_scan_pubkey, generate_multiple_recipient_pubkeys}; + use silentpayments::sending::generate_multiple_recipient_pubkeys; use crate::common::{ structs::TestData, utils::{ self, calculate_tweak_data_for_recipient, decode_input_pub_keys, decode_outpoints, decode_outputs_to_check, decode_priv_keys, decode_recipients, get_a_sum_secret_keys, - hash_outpoints, sender_calculate_shared_secret, verify_and_calculate_signatures, receiver_calculate_shared_secret + hash_outpoints, sender_calculate_partial_secret, verify_and_calculate_signatures, receiver_calculate_shared_secret }, }; @@ -59,15 +59,11 @@ mod tests { let a_sum = get_a_sum_secret_keys(&input_priv_keys); - let mut ecdh_shared_secrets: HashMap = HashMap::new(); - for addr in &silent_addresses { - let B_scan = decode_scan_pubkey(&addr).unwrap(); - let ecdh_shared_secret = - sender_calculate_shared_secret(a_sum, B_scan, outpoints_hash); - ecdh_shared_secrets.insert(B_scan, ecdh_shared_secret); - } + let partial_secret = + sender_calculate_partial_secret(a_sum, outpoints_hash); + let outputs = - generate_multiple_recipient_pubkeys(silent_addresses, ecdh_shared_secrets).unwrap(); + generate_multiple_recipient_pubkeys(silent_addresses, partial_secret).unwrap(); for output_pubkeys in &outputs { for pubkey in output_pubkeys.1 {