@@ -21,7 +21,7 @@ use secp256kfun::{KeyPair, hash::Hash32, nonce::NonceGen, prelude::*, rand_core}
2121/// certifying the aggregated keygen input in certpedpop.
2222pub trait CertificationScheme {
2323 /// The signature type produced by this scheme
24- type Signature : Clone + core:: fmt:: Debug ;
24+ type Signature : Clone + core:: fmt:: Debug + PartialEq ;
2525
2626 /// The output produced by successful verification
2727 type Output : Clone + core:: fmt:: Debug ;
@@ -74,10 +74,11 @@ pub mod vrf_cert {
7474 use vrf_fun:: VrfProof ;
7575
7676 /// VRF certification scheme using SSWU VRF
77+ #[ derive( Clone , Debug , PartialEq ) ]
7778 pub struct VrfCertifier ;
7879
7980 /// The output from VRF verification containing the gamma point
80- #[ derive( Clone , Debug ) ]
81+ #[ derive( Clone , Debug , PartialEq ) ]
8182 pub struct VrfOutput {
8283 /// The VRF output point (gamma)
8384 pub gamma : Point ,
@@ -118,6 +119,7 @@ pub mod vrf_cert {
118119/// A party that generates secret input to the key generation. You need at least one of these
119120/// and if at least one of these parties is honest then the final secret key will not be known by an
120121/// attacker (unless they obtain `t` shares!).
122+ #[ derive( Clone , Debug , PartialEq ) ]
121123pub struct Contributor {
122124 inner : encpedpop:: Contributor ,
123125}
@@ -128,7 +130,13 @@ pub type KeygenInput = encpedpop::KeygenInput;
128130/// Key generation inputs after being aggregated by the coordinator
129131pub type AggKeygenInput = encpedpop:: AggKeygenInput ;
130132/// A certificate containing signatures or proofs from certifying parties
131- #[ derive( Clone , Debug ) ]
133+ #[ derive( Clone , Debug , PartialEq ) ]
134+ #[ cfg_attr( feature = "bincode" , derive( bincode:: Encode , bincode:: Decode ) ) ]
135+ #[ cfg_attr(
136+ feature = "serde" ,
137+ derive( crate :: fun:: serde:: Deserialize , crate :: fun:: serde:: Serialize ) ,
138+ serde( crate = "crate::fun::serde" )
139+ ) ]
132140pub struct Certificate < Sig > ( BTreeMap < Point , Sig > ) ;
133141
134142/// A certificate containing signatures or proofs from certifying parties
@@ -138,14 +146,17 @@ impl<Sig> Default for Certificate<Sig> {
138146 }
139147}
140148
141- impl < Sig > Certificate < Sig > {
149+ impl < Sig : PartialEq + core :: fmt :: Debug > Certificate < Sig > {
142150 /// Create a new empty certificate
143151 pub fn new ( ) -> Self {
144152 Self :: default ( )
145153 }
146154
147155 /// Insert a signature/proof for a public key
148156 pub fn insert ( & mut self , key : Point , sig : Sig ) {
157+ if let Some ( existing) = self . 0 . get ( & key) {
158+ assert_eq ! ( existing, & sig, "certification should not change" ) ;
159+ }
149160 self . 0 . insert ( key, sig) ;
150161 }
151162
@@ -158,6 +169,17 @@ impl<Sig> Certificate<Sig> {
158169 pub fn iter ( & self ) -> impl Iterator < Item = ( & Point , & Sig ) > {
159170 self . 0 . iter ( )
160171 }
172+
173+ /// The number of certificates stored
174+ pub fn len ( & self ) -> usize {
175+ self . 0 . len ( )
176+ }
177+
178+ /// Have any certificates been collected
179+ pub fn is_empty ( & self ) -> bool {
180+ // clippy::len_without_is_empty wanted this method
181+ self . 0 . is_empty ( )
182+ }
161183}
162184
163185impl Contributor {
@@ -203,12 +225,14 @@ impl Contributor {
203225}
204226
205227/// A key generation session that has been certified by each certifying party (contributors and share receivers).
206- #[ derive( Clone , Debug ) ]
228+ #[ derive( Clone , Debug , PartialEq ) ]
207229pub struct CertifiedKeygen < S : CertificationScheme > {
208- input : AggKeygenInput ,
209- certificate : Certificate < S :: Signature > ,
230+ /// The aggregated inputs to keygen
231+ pub input : AggKeygenInput ,
232+ /// The collected certificates from each party
233+ pub certificate : Certificate < S :: Signature > ,
210234 /// The outputs from successful verification, indexed by certifying party's public key
211- outputs : BTreeMap < Point , S :: Output > ,
235+ pub outputs : BTreeMap < Point , S :: Output > ,
212236}
213237
214238impl < S : CertificationScheme > CertifiedKeygen < S > {
@@ -296,6 +320,7 @@ pub use encpedpop::Coordinator;
296320
297321/// Stores the state of share recipient who first receives their share and then waits to get
298322/// signatures from all the certifying parties on the keygeneration before accepting it.
323+ #[ derive( Debug , Clone , PartialEq ) ]
299324pub struct SecretShareReceiver {
300325 paired_secret_share : PairedSecretShare < Normal , Zero > ,
301326 agg_input : AggKeygenInput ,
@@ -344,7 +369,9 @@ impl SecretShareReceiver {
344369 . agg_input
345370 . encryption_keys ( )
346371 . map ( |( _, encryption_key) | encryption_key)
347- . chain ( contributor_keys. iter ( ) . cloned ( ) ) ;
372+ . chain ( contributor_keys. iter ( ) . cloned ( ) )
373+ . collect :: < BTreeSet < _ > > ( ) ; // dedupe as some contributers may have also be receivers
374+
348375 for cert_key in cert_keys {
349376 match certificate. get ( & cert_key) {
350377 Some ( sig) => match cert_scheme. verify_cert ( cert_key, & self . agg_input , sig) {
@@ -378,38 +405,47 @@ pub fn simulate_keygen<H: Hash32, NG: NonceGen, S: CertificationScheme>(
378405 cert_scheme : & S ,
379406 threshold : u32 ,
380407 n_receivers : u32 ,
381- n_generators : u32 ,
408+ n_extra_generators : u32 ,
382409 fingerprint : Fingerprint ,
383410 rng : & mut impl rand_core:: RngCore ,
384411) -> (
385412 CertifiedKeygen < S > ,
386413 Vec < ( PairedSecretShare < Normal > , KeyPair ) > ,
387414) {
388- let share_receivers = ( 1 ..=n_receivers)
389- . map ( |i| Scalar :: from ( i) . non_zero ( ) . unwrap ( ) )
390- . collect :: < BTreeSet < _ > > ( ) ;
391-
392- let mut receiver_enckeys = share_receivers
393- . iter ( )
394- . cloned ( )
395- . map ( |party_index| ( party_index, KeyPair :: new ( Scalar :: random ( rng) ) ) )
415+ let mut receiver_enckeys = ( 1 ..=n_receivers)
416+ . map ( |i| {
417+ let party_index = Scalar :: from ( i) . non_zero ( ) . unwrap ( ) ;
418+ ( party_index, KeyPair :: new ( Scalar :: random ( rng) ) )
419+ } )
396420 . collect :: < BTreeMap < _ , _ > > ( ) ;
397421
398422 let public_receiver_enckeys = receiver_enckeys
399423 . iter ( )
400424 . map ( |( party_index, enckeypair) | ( * party_index, enckeypair. public_key ( ) ) )
401425 . collect :: < BTreeMap < ShareIndex , Point > > ( ) ;
402426
427+ // Total number of generators is receivers + extra generators
428+ let n_generators = n_receivers + n_extra_generators;
429+
430+ // Generate keypairs for contributors - receivers will use their existing keypairs
431+ let contributor_keys: Vec < _ > = ( 1 ..=n_receivers)
432+ . map ( |i| {
433+ let party_index = Scalar :: from ( i) . non_zero ( ) . unwrap ( ) ;
434+ receiver_enckeys[ & party_index]
435+ } )
436+ . chain ( core:: iter:: repeat_n (
437+ KeyPair :: new ( Scalar :: random ( rng) ) ,
438+ n_extra_generators as _ ,
439+ ) )
440+ . collect ( ) ;
441+
403442 let ( contributors, to_coordinator_messages) : ( Vec < Contributor > , Vec < KeygenInput > ) = ( 0
404443 ..n_generators)
405444 . map ( |i| {
406445 Contributor :: gen_keygen_input ( schnorr, threshold, & public_receiver_enckeys, i, rng)
407446 } )
408447 . unzip ( ) ;
409448
410- let contributor_keys = ( 0 ..n_generators)
411- . map ( |_| KeyPair :: new ( Scalar :: random ( rng) ) )
412- . collect :: < Vec < _ > > ( ) ;
413449 let contributor_public_keys = contributor_keys
414450 . iter ( )
415451 . map ( |kp| kp. public_key ( ) )
@@ -526,7 +562,7 @@ mod test {
526562 #[ test]
527563 fn certified_run_simulate_keygen(
528564 ( n_receivers, threshold) in ( 1u32 ..=4 ) . prop_flat_map( |n| ( Just ( n) , 1u32 ..=n) ) ,
529- n_generators in 1u32 .. 5 ,
565+ n_extra_generators in 0u32 ..= 3 ,
530566 ) {
531567 let schnorr = crate :: new_with_deterministic_nonces:: <sha2:: Sha256 >( ) ;
532568 let mut rng = TestRng :: deterministic_rng( RngAlgorithm :: ChaCha ) ;
@@ -536,7 +572,7 @@ mod test {
536572 & schnorr,
537573 threshold,
538574 n_receivers,
539- n_generators ,
575+ n_extra_generators ,
540576 Fingerprint :: none( ) ,
541577 & mut rng
542578 ) ;
@@ -559,14 +595,14 @@ mod test {
559595
560596 let threshold = 2 ;
561597 let n_receivers = 3 ;
562- let n_generators = 2 ;
598+ let n_extra_generators = 0 ; // All receivers are also generators
563599
564600 let ( certified_keygen, _) = certpedpop:: simulate_keygen (
565601 & schnorr,
566602 & vrf_certifier,
567603 threshold,
568604 n_receivers,
569- n_generators ,
605+ n_extra_generators ,
570606 Fingerprint :: none ( ) ,
571607 & mut rng,
572608 ) ;
@@ -581,7 +617,7 @@ mod test {
581617 // Verify we have the expected number of VRF outputs
582618 assert_eq ! (
583619 certified_keygen. outputs( ) . len( ) ,
584- ( n_receivers + n_generators ) as usize
620+ ( n_receivers + n_extra_generators ) as usize
585621 ) ;
586622 }
587623}
0 commit comments