diff --git a/Cargo.toml b/Cargo.toml index 401c4e24..90a5618b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ categories = ["cryptography"] homepage = "https://tari.com" readme = "README.md" license = "BSD-3-Clause" -version = "0.20.2" +version = "0.20.3" edition = "2018" [dependencies] diff --git a/changelog.md b/changelog.md index d59676da..25ee0f5a 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,14 @@ # Changelog All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. -### [0.21.2](https://github.com/tari-project/tari-crypto/compare/v0.21.1...v0.21.2) (2024-06-28) +### [0.20.3](https://github.com/tari-project/tari-crypto/compare/v0.20.1...v0.20.3) (2024-07-02) + + +### Features + +* Include Add CAPK and Schnorr signatures together + +### [0.20.2](https://github.com/tari-project/tari-crypto/compare/v0.20.1...v0.20.2) (2024-06-28) ### Features @@ -9,7 +16,7 @@ All notable changes to this project will be documented in this file. See [standa * Adds public constructor for DHKE -### [0.21.1](https://github.com/tari-project/tari-crypto/compare/v0.20.0...v0.21.1) (2024-05-09) +### [0.20.1](https://github.com/tari-project/tari-crypto/compare/v0.20.0...v0.20.1) (2024-05-09) ### Features diff --git a/src/ristretto/ristretto_com_and_pub_sig.rs b/src/ristretto/ristretto_com_and_pub_sig.rs index 8d328e69..cc4a79d8 100644 --- a/src/ristretto/ristretto_com_and_pub_sig.rs +++ b/src/ristretto/ristretto_com_and_pub_sig.rs @@ -92,6 +92,7 @@ mod test { pedersen::{commitment_factory::PedersenCommitmentFactory, PedersenCommitment}, RistrettoComAndPubSig, RistrettoPublicKey, + RistrettoSchnorr, RistrettoSecretKey, }, }; @@ -265,6 +266,62 @@ mod test { assert!(sig_p_total.verify_challenge(&commitment, &pubkey, &challenge, &factory, &mut rng)); } + /// Create a schnorr and RistrettoComAndPubSig adding them together and testing if they still valid. + #[test] + fn sign_and_verify_combined_schnorr() { + let mut rng = rand::thread_rng(); + + // Challenge; doesn't use proper Fiat-Shamir, so it's for testing only! + let challenge = Blake2b::::new().chain_update(b"Small Gods").finalize(); + + // Witness data + let a_value = RistrettoSecretKey::random(&mut rng); + let x_value = RistrettoSecretKey::random(&mut rng); + let y_value = RistrettoSecretKey::random(&mut rng); + + // Statement data + let factory = PedersenCommitmentFactory::default(); + let commitment = factory.commit(&x_value, &a_value); + let pubkey = RistrettoPublicKey::from_secret_key(&y_value); + + // Nonce data + let r_a = RistrettoSecretKey::random(&mut rng); + let r_x = RistrettoSecretKey::random(&mut rng); + let r_y = RistrettoSecretKey::random(&mut rng); + + let sig_capk = + RistrettoComAndPubSig::sign(&a_value, &x_value, &y_value, &r_a, &r_x, &r_y, &challenge, &factory).unwrap(); + assert!(sig_capk.verify_challenge(&commitment, &pubkey, &challenge, &factory, &mut rng)); + + let (k, pub_k) = RistrettoPublicKey::random_keypair(&mut rng); + let r = RistrettoSecretKey::random(&mut rng); + + let total_y_value = &y_value + &k; + let total_r_y = &r_y + &r; + + let sig = RistrettoSchnorr::sign_raw_uniform(&k, r, &challenge).unwrap(); + assert!(sig.verify_raw_uniform(&pub_k, &challenge)); + + let total_pubkey = RistrettoPublicKey::from_secret_key(&total_y_value); + + let total_sig_capk = RistrettoComAndPubSig::sign( + &a_value, + &x_value, + &total_y_value, + &r_a, + &r_x, + &total_r_y, + &challenge, + &factory, + ) + .unwrap(); + assert!(total_sig_capk.verify_challenge(&commitment, &total_pubkey, &challenge, &factory, &mut rng)); + + let agg_sig = &sig_capk + &sig; + assert!(agg_sig.verify_challenge(&commitment, &total_pubkey, &challenge, &factory, &mut rng)); + assert_eq!(agg_sig, total_sig_capk); + } + /// Test that commitment signatures are linear, as in a multisignature construction #[test] fn test_signature_addition() { diff --git a/src/signatures/commitment_and_public_key_signature.rs b/src/signatures/commitment_and_public_key_signature.rs index f46e48a6..bac5d18e 100644 --- a/src/signatures/commitment_and_public_key_signature.rs +++ b/src/signatures/commitment_and_public_key_signature.rs @@ -16,6 +16,7 @@ use crate::{ alloc::borrow::ToOwned, commitment::{HomomorphicCommitment, HomomorphicCommitmentFactory}, keys::{PublicKey, SecretKey}, + signatures::SchnorrSignature, }; /// An error when creating a commitment signature @@ -305,6 +306,60 @@ where } } +impl<'a, 'b, P, K> Add<&'b SchnorrSignature> for &'a CommitmentAndPublicKeySignature +where + P: PublicKey, + &'a HomomorphicCommitment

: Add<&'b HomomorphicCommitment

, Output = HomomorphicCommitment

>, + &'a P: Add<&'b P, Output = P>, + K: SecretKey, + &'a K: Add<&'b K, Output = K>, +{ + type Output = CommitmentAndPublicKeySignature; + + fn add(self, rhs: &'b SchnorrSignature) -> CommitmentAndPublicKeySignature { + let ephemeral_commitment_sum = self.ephemeral_commitment().clone(); + let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.get_public_nonce(); + let u_a_sum = self.u_a().clone(); + let u_x_sum = self.u_x().clone(); + let u_y_sum = self.u_y() + rhs.get_signature(); + + CommitmentAndPublicKeySignature::new( + ephemeral_commitment_sum, + ephemeral_pubkey_sum_sum, + u_a_sum, + u_x_sum, + u_y_sum, + ) + } +} + +impl<'a, P, K> Add> for &'a CommitmentAndPublicKeySignature +where + P: PublicKey, + for<'b> &'a HomomorphicCommitment

: Add<&'b HomomorphicCommitment

, Output = HomomorphicCommitment

>, + for<'b> &'a P: Add<&'b P, Output = P>, + K: SecretKey, + for<'b> &'a K: Add<&'b K, Output = K>, +{ + type Output = CommitmentAndPublicKeySignature; + + fn add(self, rhs: SchnorrSignature) -> CommitmentAndPublicKeySignature { + let ephemeral_commitment_sum = self.ephemeral_commitment().clone(); + let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.get_public_nonce(); + let u_a_sum = self.u_a().clone(); + let u_x_sum = self.u_x().clone(); + let u_y_sum = self.u_y() + rhs.get_signature(); + + CommitmentAndPublicKeySignature::new( + ephemeral_commitment_sum, + ephemeral_pubkey_sum_sum, + u_a_sum, + u_x_sum, + u_y_sum, + ) + } +} + impl Default for CommitmentAndPublicKeySignature where P: PublicKey,