Skip to content

Commit bdf1d83

Browse files
authored
feat: add sum for schnorr signature and capk signature (#231)
Adds sum for schnorr signature and capk signature as a features new version
1 parent 494bb73 commit bdf1d83

File tree

4 files changed

+122
-3
lines changed

4 files changed

+122
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ categories = ["cryptography"]
77
homepage = "https://tari.com"
88
readme = "README.md"
99
license = "BSD-3-Clause"
10-
version = "0.20.2"
10+
version = "0.20.3"
1111
edition = "2018"
1212

1313
[dependencies]

changelog.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
# Changelog
22

33
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.
4-
### [0.21.2](https://github.com/tari-project/tari-crypto/compare/v0.21.1...v0.21.2) (2024-06-28)
4+
### [0.20.3](https://github.com/tari-project/tari-crypto/compare/v0.20.1...v0.20.3) (2024-07-02)
5+
6+
7+
### Features
8+
9+
* Include Add CAPK and Schnorr signatures together
10+
11+
### [0.20.2](https://github.com/tari-project/tari-crypto/compare/v0.20.1...v0.20.2) (2024-06-28)
512

613

714
### Features
815

916
* Adds public constructor for DHKE
1017

1118

12-
### [0.21.1](https://github.com/tari-project/tari-crypto/compare/v0.20.0...v0.21.1) (2024-05-09)
19+
### [0.20.1](https://github.com/tari-project/tari-crypto/compare/v0.20.0...v0.20.1) (2024-05-09)
1320

1421

1522
### Features

src/ristretto/ristretto_com_and_pub_sig.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ mod test {
9292
pedersen::{commitment_factory::PedersenCommitmentFactory, PedersenCommitment},
9393
RistrettoComAndPubSig,
9494
RistrettoPublicKey,
95+
RistrettoSchnorr,
9596
RistrettoSecretKey,
9697
},
9798
};
@@ -265,6 +266,62 @@ mod test {
265266
assert!(sig_p_total.verify_challenge(&commitment, &pubkey, &challenge, &factory, &mut rng));
266267
}
267268

269+
/// Create a schnorr and RistrettoComAndPubSig adding them together and testing if they still valid.
270+
#[test]
271+
fn sign_and_verify_combined_schnorr() {
272+
let mut rng = rand::thread_rng();
273+
274+
// Challenge; doesn't use proper Fiat-Shamir, so it's for testing only!
275+
let challenge = Blake2b::<U64>::new().chain_update(b"Small Gods").finalize();
276+
277+
// Witness data
278+
let a_value = RistrettoSecretKey::random(&mut rng);
279+
let x_value = RistrettoSecretKey::random(&mut rng);
280+
let y_value = RistrettoSecretKey::random(&mut rng);
281+
282+
// Statement data
283+
let factory = PedersenCommitmentFactory::default();
284+
let commitment = factory.commit(&x_value, &a_value);
285+
let pubkey = RistrettoPublicKey::from_secret_key(&y_value);
286+
287+
// Nonce data
288+
let r_a = RistrettoSecretKey::random(&mut rng);
289+
let r_x = RistrettoSecretKey::random(&mut rng);
290+
let r_y = RistrettoSecretKey::random(&mut rng);
291+
292+
let sig_capk =
293+
RistrettoComAndPubSig::sign(&a_value, &x_value, &y_value, &r_a, &r_x, &r_y, &challenge, &factory).unwrap();
294+
assert!(sig_capk.verify_challenge(&commitment, &pubkey, &challenge, &factory, &mut rng));
295+
296+
let (k, pub_k) = RistrettoPublicKey::random_keypair(&mut rng);
297+
let r = RistrettoSecretKey::random(&mut rng);
298+
299+
let total_y_value = &y_value + &k;
300+
let total_r_y = &r_y + &r;
301+
302+
let sig = RistrettoSchnorr::sign_raw_uniform(&k, r, &challenge).unwrap();
303+
assert!(sig.verify_raw_uniform(&pub_k, &challenge));
304+
305+
let total_pubkey = RistrettoPublicKey::from_secret_key(&total_y_value);
306+
307+
let total_sig_capk = RistrettoComAndPubSig::sign(
308+
&a_value,
309+
&x_value,
310+
&total_y_value,
311+
&r_a,
312+
&r_x,
313+
&total_r_y,
314+
&challenge,
315+
&factory,
316+
)
317+
.unwrap();
318+
assert!(total_sig_capk.verify_challenge(&commitment, &total_pubkey, &challenge, &factory, &mut rng));
319+
320+
let agg_sig = &sig_capk + &sig;
321+
assert!(agg_sig.verify_challenge(&commitment, &total_pubkey, &challenge, &factory, &mut rng));
322+
assert_eq!(agg_sig, total_sig_capk);
323+
}
324+
268325
/// Test that commitment signatures are linear, as in a multisignature construction
269326
#[test]
270327
fn test_signature_addition() {

src/signatures/commitment_and_public_key_signature.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::{
1616
alloc::borrow::ToOwned,
1717
commitment::{HomomorphicCommitment, HomomorphicCommitmentFactory},
1818
keys::{PublicKey, SecretKey},
19+
signatures::SchnorrSignature,
1920
};
2021

2122
/// An error when creating a commitment signature
@@ -305,6 +306,60 @@ where
305306
}
306307
}
307308

309+
impl<'a, 'b, P, K> Add<&'b SchnorrSignature<P, K>> for &'a CommitmentAndPublicKeySignature<P, K>
310+
where
311+
P: PublicKey<K = K>,
312+
&'a HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
313+
&'a P: Add<&'b P, Output = P>,
314+
K: SecretKey,
315+
&'a K: Add<&'b K, Output = K>,
316+
{
317+
type Output = CommitmentAndPublicKeySignature<P, K>;
318+
319+
fn add(self, rhs: &'b SchnorrSignature<P, K>) -> CommitmentAndPublicKeySignature<P, K> {
320+
let ephemeral_commitment_sum = self.ephemeral_commitment().clone();
321+
let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.get_public_nonce();
322+
let u_a_sum = self.u_a().clone();
323+
let u_x_sum = self.u_x().clone();
324+
let u_y_sum = self.u_y() + rhs.get_signature();
325+
326+
CommitmentAndPublicKeySignature::new(
327+
ephemeral_commitment_sum,
328+
ephemeral_pubkey_sum_sum,
329+
u_a_sum,
330+
u_x_sum,
331+
u_y_sum,
332+
)
333+
}
334+
}
335+
336+
impl<'a, P, K> Add<SchnorrSignature<P, K>> for &'a CommitmentAndPublicKeySignature<P, K>
337+
where
338+
P: PublicKey<K = K>,
339+
for<'b> &'a HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
340+
for<'b> &'a P: Add<&'b P, Output = P>,
341+
K: SecretKey,
342+
for<'b> &'a K: Add<&'b K, Output = K>,
343+
{
344+
type Output = CommitmentAndPublicKeySignature<P, K>;
345+
346+
fn add(self, rhs: SchnorrSignature<P, K>) -> CommitmentAndPublicKeySignature<P, K> {
347+
let ephemeral_commitment_sum = self.ephemeral_commitment().clone();
348+
let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.get_public_nonce();
349+
let u_a_sum = self.u_a().clone();
350+
let u_x_sum = self.u_x().clone();
351+
let u_y_sum = self.u_y() + rhs.get_signature();
352+
353+
CommitmentAndPublicKeySignature::new(
354+
ephemeral_commitment_sum,
355+
ephemeral_pubkey_sum_sum,
356+
u_a_sum,
357+
u_x_sum,
358+
u_y_sum,
359+
)
360+
}
361+
}
362+
308363
impl<P, K> Default for CommitmentAndPublicKeySignature<P, K>
309364
where
310365
P: PublicKey<K = K>,

0 commit comments

Comments
 (0)