@@ -174,7 +174,7 @@ impl<Z> PointPoly<Z> {
174
174
#[ derive( Clone , Debug ) ]
175
175
pub struct KeyGen {
176
176
point_polys : Vec < PointPoly > ,
177
- keygen_id : Point < EvenY > ,
177
+ keygen_id : Scalar ,
178
178
frost_key : FrostKey ,
179
179
}
180
180
@@ -310,7 +310,7 @@ impl FrostKey {
310
310
}
311
311
}
312
312
313
- impl < H : Digest < OutputSize = U32 > + Clone , NG : AddTag > Frost < H , NG > {
313
+ impl < H : Digest < OutputSize = U32 > + Clone , NG : AddTag + NonceGen > Frost < H , NG > {
314
314
/// Create secret shares and our proof-of-possession to be shared with other participants.
315
315
///
316
316
/// Secret shares are created for every other participant by evaluating our secret polynomial
@@ -322,31 +322,23 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
322
322
///
323
323
/// ## Return value
324
324
///
325
- /// Returns a vector of secret shares and a proof of possession, as a tupple.
325
+ /// Returns a vector of secret shares and a proof of possession Signature
326
326
/// The secret shares at index 0 is destined for participant 1.
327
327
pub fn create_shares (
328
328
& self ,
329
329
KeyGen : & KeyGen ,
330
330
scalar_poly : ScalarPoly ,
331
- rng : & mut ( impl RngCore + CryptoRng ) ,
332
- ) -> ( Vec < Scalar < Secret , Zero > > , ( Point , Scalar < Secret , Zero > ) ) {
333
- // Create proof of possession
334
- let pop_r = Scalar :: random ( rng) ;
335
- let pop_R = g ! ( pop_r * G ) . normalize ( ) ;
336
- let pop_c = Scalar :: from_hash (
337
- self . keygen_id_hash
338
- . clone ( )
339
- . add ( g ! ( { scalar_poly. 0 [ 0 ] . clone( ) } * G ) . normalize ( ) )
340
- . add ( KeyGen . keygen_id )
341
- . add ( pop_R) ,
342
- ) ;
343
- let pop_z = s ! ( pop_c + pop_r) ;
331
+ ) -> ( Vec < Scalar < Secret , Zero > > , Signature ) {
332
+ let key_pair = self . schnorr . new_keypair ( scalar_poly. 0 [ 0 ] . clone ( ) ) ;
333
+ let pop = self
334
+ . schnorr
335
+ . sign ( & key_pair, Message :: < Public > :: plain ( "frost-pop" , b"" ) ) ;
344
336
345
337
let shares = ( 1 ..=KeyGen . point_polys . len ( ) )
346
338
. map ( |i| scalar_poly. eval ( i as u32 ) )
347
339
. collect ( ) ;
348
340
349
- ( shares, ( pop_R , pop_z ) )
341
+ ( shares, pop )
350
342
}
351
343
}
352
344
@@ -356,22 +348,14 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
356
348
/// ## Return value
357
349
///
358
350
/// Returns `bool` true if the proof of possession matches this point poly,
359
- fn verify_pop (
360
- & self ,
361
- keygen_id : Point < secp256kfun:: marker:: EvenY > ,
362
- point_poly : & PointPoly ,
363
- pop : ( Point , Scalar < Secret , Zero > ) ,
364
- ) -> bool {
365
- let first_point = point_poly. 0 [ 0 ] ;
366
- let ( pop_R, pop_z) = pop;
367
- let pop_c = Scalar :: from_hash (
368
- self . keygen_id_hash
369
- . clone ( )
370
- . add ( first_point)
371
- . add ( keygen_id)
372
- . add ( pop_R) ,
373
- ) ;
374
- !g ! ( pop_R + pop_c * first_point - pop_z * G ) . is_zero ( )
351
+ fn verify_pop ( & self , point_poly : & PointPoly , pop : Signature ) -> bool {
352
+ let ( even_poly_point, _) = point_poly. 0 [ 0 ] . into_point_with_even_y ( ) ;
353
+
354
+ self . schnorr . verify (
355
+ & even_poly_point,
356
+ Message :: < Public > :: plain ( "frost-pop" , b"" ) ,
357
+ & pop,
358
+ )
375
359
}
376
360
}
377
361
@@ -411,7 +395,7 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
411
395
. into_point_with_even_y ( ) ;
412
396
413
397
// TODO set keygen id
414
- let keygen_id = joint_public_key;
398
+ let keygen_id = Scalar :: from_hash ( self . keygen_id_hash . clone ( ) . add ( joint_public_key) ) ;
415
399
416
400
let verification_shares = ( 1 ..=point_polys. len ( ) )
417
401
. map ( |i| joint_poly. eval ( i as u32 ) . normalize ( ) . mark :: < NonZero > ( ) )
@@ -447,20 +431,21 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: AddTag> Frost<H, NG> {
447
431
KeyGen : KeyGen ,
448
432
my_index : u32 ,
449
433
secret_shares : Vec < Scalar < Secret , Zero > > ,
450
- proofs_of_possession : Vec < ( Point , Scalar < Secret , Zero > ) > ,
434
+ proofs_of_possession : Vec < Signature > ,
451
435
) -> Result < ( Scalar , FrostKey ) , FinishKeyGenError > {
452
436
assert_eq ! (
453
437
secret_shares. len( ) ,
454
438
KeyGen . frost_key. verification_shares. len( )
455
439
) ;
440
+ assert_eq ! ( secret_shares. len( ) , proofs_of_possession. len( ) ) ;
456
441
457
442
for ( i, ( poly, pop) ) in KeyGen
458
443
. point_polys
459
444
. iter ( )
460
445
. zip ( proofs_of_possession)
461
446
. enumerate ( )
462
447
{
463
- if !self . verify_pop ( KeyGen . keygen_id , poly, pop) {
448
+ if !self . verify_pop ( poly, pop) {
464
449
return Err ( FinishKeyGenError :: InvalidProofOfPossession ( i) ) ;
465
450
}
466
451
}
@@ -711,30 +696,11 @@ impl<H: Digest<OutputSize = U32> + Clone, NG: NonceGen + AddTag> Frost<H, NG> {
711
696
}
712
697
}
713
698
714
- /// Allows getting the FrostKey
715
- // TODO seal this trait
716
- pub trait GetFrostKey {
717
- /// Get Frost key
718
- fn get_frost_key ( & self ) -> & FrostKey ;
719
- }
720
-
721
- impl GetFrostKey for KeyGen {
722
- fn get_frost_key ( & self ) -> & FrostKey {
723
- & self . frost_key
724
- }
725
- }
726
-
727
- impl GetFrostKey for FrostKey {
728
- fn get_frost_key ( & self ) -> & FrostKey {
729
- & self
730
- }
731
- }
732
-
733
699
#[ cfg( test) ]
734
700
mod test {
701
+ use core:: num:: NonZeroU32 ;
702
+
735
703
use super :: * ;
736
- use rand:: { prelude:: IteratorRandom , Rng } ;
737
- // proptest::prelude::*};
738
704
use secp256kfun:: {
739
705
nonce:: Deterministic ,
740
706
proptest:: { arbitrary:: any, proptest} ,
@@ -743,95 +709,124 @@ mod test {
743
709
744
710
proptest ! {
745
711
#[ test]
746
- fn frost_prop_test( n_parties in 3u32 ..8 , something in any:: <u32 >( ) ) {
747
- let mut rng = rand:: thread_rng( ) ;
748
- let threshold = rng. gen_range( 2 ..=n_parties) ;
712
+ fn frost_prop_test( n_parties in 3u32 ..8 , threshold in 3u32 ..8 , signers_mask_seed in any:: <u32 >( ) , tweak1 in any:: <Scalar <Public , Zero >>( ) , tweak2 in any:: <Scalar <Public , Zero >>( ) , use_tweak2 in any:: <bool >( ) ) {
713
+ // Two tweaks
749
714
let frost = Frost :: new( Schnorr :: <Sha256 , Deterministic <Sha256 >>:: new(
750
715
Deterministic :: <Sha256 >:: default ( ) ,
751
716
) ) ;
752
717
dbg!( threshold, n_parties) ;
753
-
754
- let scalar_polys: Vec <ScalarPoly > = ( 0 ..n_parties) . map( |_| ScalarPoly :: random( threshold, & mut rng) ) . collect( ) ;
755
- let point_polys: Vec <PointPoly > = scalar_polys. iter( ) . map( |sp| sp. to_point_poly( ) ) . collect( ) ;
756
-
757
- let KeyGen = frost. new_keygen( point_polys) . unwrap( ) ;
758
-
759
- let mut proofs_of_possession= vec![ ] ;
760
- let mut shares_vec = vec![ ] ;
761
- for sp in scalar_polys {
762
- let ( shares, pop) = frost. create_shares( & KeyGen , sp, & mut rng) ;
763
- proofs_of_possession. push( pop) ;
764
- shares_vec. push( shares) ;
765
- }
766
-
767
- // let recieved_shares = signer_indexes.iter().zip(signer_indexes).map(|(i, j)| (i,j)).collect();
768
- let mut recieved_shares: Vec <Vec <_>> = vec![ ] ;
769
- for party_index in 0 ..n_parties {
770
- recieved_shares. push( vec![ ] ) ;
771
- for share_index in 0 ..n_parties {
772
- recieved_shares[ party_index as usize ] . push( shares_vec[ share_index as usize ] [ party_index as usize ] . clone( ) ) ;
718
+ if n_parties < threshold {
719
+ dbg!( "too few parties for this threshold" ) ;
720
+ } else {
721
+ // create some scalar poly for each party
722
+ let mut scalar_polys = vec![ ] ;
723
+ for i in 1 ..=n_parties {
724
+ let scalar_poly = ( 1 ..=threshold) . map( |j| Scalar :: from_non_zero_u32( NonZeroU32 :: new( i* j) . expect( "starts from 1" ) ) ) . collect( ) ;
725
+ scalar_polys. push( ScalarPoly :: new( scalar_poly) ) ;
773
726
}
774
- }
727
+ let point_polys : Vec < PointPoly > = scalar_polys . iter ( ) . map ( |sp| sp . to_point_poly ( ) ) . collect ( ) ;
775
728
776
- let ( secret_shares, frost_keys) : ( Vec <Scalar >, Vec <FrostKey >) = ( 0 ..n_parties) . map( |i| {
777
- let ( secret_share, frost) = frost. finish_keygen(
778
- KeyGen . clone( ) ,
779
- i,
780
- recieved_shares[ i as usize ] . clone( ) ,
781
- proofs_of_possession. clone( ) ,
782
- )
783
- . unwrap( ) ;
784
- ( secret_share, frost)
785
- } ) . unzip( ) ;
786
-
787
-
788
- // Signing coalition of t to n parties
789
- let n_signers = if threshold == n_parties {
790
- threshold
791
- } else {
792
- rng. gen_range( threshold..=n_parties)
793
- } ;
794
- let signer_indexes = ( 0 ..n_parties) . choose_multiple( & mut rng, n_signers as usize ) ;
729
+ let KeyGen = frost. new_keygen( point_polys) . unwrap( ) ;
795
730
796
- let sid = frost_keys[ 0 ] . joint_public_key. to_bytes( ) ;
731
+ let mut proofs_of_possession= vec![ ] ;
732
+ let mut shares_vec = vec![ ] ;
733
+ for sp in scalar_polys {
734
+ let ( shares, pop) = frost. create_shares( & KeyGen , sp) ;
735
+ proofs_of_possession. push( pop) ;
736
+ shares_vec. push( shares) ;
737
+ }
797
738
798
- let nonces: Vec <NonceKeyPair > = signer_indexes. iter( ) . map( |i| frost. gen_nonce( & secret_shares[ * i as usize ] , & sid) ) . collect( ) ;
739
+ // collect the recieved shares for each party
740
+ let mut recieved_shares: Vec <Vec <_>> = vec![ ] ;
741
+ for party_index in 0 ..n_parties {
742
+ recieved_shares. push( vec![ ] ) ;
743
+ for share_index in 0 ..n_parties {
744
+ recieved_shares[ party_index as usize ] . push( shares_vec[ share_index as usize ] [ party_index as usize ] . clone( ) ) ;
745
+ }
746
+ }
799
747
800
- let mut recieved_nonces: Vec <_> = vec![ ] ;
801
- for ( i, nonce) in signer_indexes. iter( ) . zip( nonces. clone( ) ) {
802
- recieved_nonces. push( ( * i, nonce. public( ) ) ) ;
803
- }
748
+ // finish keygen for each party
749
+ let ( secret_shares, frost_keys) : ( Vec <Scalar >, Vec <FrostKey >) = ( 0 ..n_parties) . map( |i| {
750
+ let ( secret_share, mut frost_key) = frost. finish_keygen(
751
+ KeyGen . clone( ) ,
752
+ i,
753
+ recieved_shares[ i as usize ] . clone( ) ,
754
+ proofs_of_possession. clone( ) ,
755
+ )
756
+ . unwrap( ) ;
757
+ frost_key = frost_key. tweak( tweak1. clone( ) ) . expect( "applying tweak1" ) ;
758
+ frost_key = if use_tweak2 {
759
+ frost_key. tweak( tweak2. clone( ) ) . expect( "applying tweak2" )
760
+ } else {
761
+ frost_key
762
+ } ;
763
+ ( secret_share, frost_key)
764
+ } ) . unzip( ) ;
765
+
766
+ // create a mask of signers
767
+ // use bytes from random u32 to determine whether a party is a signer or not
768
+ let mut signers_mask = vec![ true ] ;
769
+ while signers_mask. len( ) < n_parties as usize {
770
+ for v in signers_mask_seed. to_be_bytes( ) {
771
+ if v > 128 {
772
+ signers_mask. push( true ) ;
773
+ } else {
774
+ signers_mask. push( false ) ;
775
+ }
776
+ if signers_mask. len( ) >= n_parties as usize {
777
+ break
778
+ }
779
+ }
780
+ }
781
+ let mut signer_indexes = vec![ ] ;
782
+ for ( index, included) in signers_mask. iter( ) . enumerate( ) {
783
+ if * included {
784
+ signer_indexes. push( index) ;
785
+ }
786
+ }
787
+ dbg!( & signer_indexes) ;
788
+
789
+ if signer_indexes. len( ) < threshold as usize {
790
+ dbg!( "less signers than threshold.. skipping" ) ;
791
+ } else {
792
+ let sid = frost_keys[ 0 ] . joint_public_key. to_bytes( ) ;
793
+ let nonces: Vec <NonceKeyPair > = signer_indexes. iter( ) . map( |i| frost. gen_nonce( & secret_shares[ * i as usize ] , & sid) ) . collect( ) ;
794
+ // dbg!(&nonces);
795
+
796
+ let mut recieved_nonces: Vec <_> = vec![ ] ;
797
+ for ( i, nonce) in signer_indexes. iter( ) . zip( nonces. clone( ) ) {
798
+ recieved_nonces. push( ( * i as u32 , nonce. public( ) ) ) ;
799
+ }
800
+
801
+ // Create Frost signing session
802
+ let mut signatures = vec![ ] ;
803
+ for i in 0 ..signer_indexes. len( ) {
804
+ let signer_index = signer_indexes[ i] as usize ;
805
+ let session = frost. start_sign_session( & frost_keys[ signer_index] , recieved_nonces. clone( ) , Message :: plain( "test" , b"test" ) ) ;
806
+ dbg!( nonces[ i] . clone( ) ) ;
807
+ let sig = frost. sign( & frost_keys[ signer_index] , & session, signer_index as u32 , & secret_shares[ signer_index] , nonces[ i] . clone( ) ) ;
808
+ assert!( frost. verify_signature_share( & frost_keys[ signer_index] , & session, signer_index as u32 , sig) ) ;
809
+ signatures. push( sig) ;
810
+ }
811
+
812
+ // TODO get this session from loop above
813
+ // assert same and use one
814
+ let session = frost. start_sign_session( & frost_keys[ signer_indexes[ 0 ] as usize ] , recieved_nonces. clone( ) , Message :: plain( "test" , b"test" ) ) ;
815
+ let combined_sig = frost. combine_signature_shares( & frost_keys[ signer_indexes[ 0 ] as usize ] , & session, signatures) ;
816
+
817
+ assert!( frost. schnorr. verify(
818
+ & frost_keys[ signer_indexes[ 0 ] as usize ] . joint_public_key,
819
+ Message :: <Public >:: plain( "test" , b"test" ) ,
820
+ & combined_sig
821
+ ) ) ;
804
822
805
- dbg!( recieved_nonces. clone( ) ) ;
806
-
807
- // Create Frost signing session
808
- let mut signatures = vec![ ] ;
809
- for i in 0 ..signer_indexes. len( ) {
810
- let signer_index = signer_indexes[ i] as usize ;
811
- let session = frost. start_sign_session( & frost_keys[ signer_index] , recieved_nonces. clone( ) , Message :: plain( "test" , b"test" ) ) ;
812
- dbg!( nonces[ i] . clone( ) ) ;
813
- let sig = frost. sign( & frost_keys[ signer_index] , & session, signer_index as u32 , & secret_shares[ signer_index] , nonces[ i] . clone( ) ) ;
814
- assert!( frost. verify_signature_share( & frost_keys[ signer_index] , & session, signer_index as u32 , sig) ) ;
815
- signatures. push( sig) ;
823
+ }
816
824
}
817
-
818
- // TODO get this session from loop above
819
- let session = frost. start_sign_session( & frost_keys[ signer_indexes[ 0 ] as usize ] , recieved_nonces. clone( ) , Message :: plain( "test" , b"test" ) ) ;
820
- let combined_sig = frost. combine_signature_shares( & frost_keys[ signer_indexes[ 0 ] as usize ] , & session, signatures) ;
821
-
822
- assert!( frost. schnorr. verify(
823
- & frost_keys[ signer_indexes[ 0 ] as usize ] . joint_public_key,
824
- Message :: <Public >:: plain( "test" , b"test" ) ,
825
- & combined_sig
826
- ) ) ;
827
-
828
-
829
825
}
830
826
}
831
827
832
828
#[ test]
833
829
fn frost_test_end_to_end ( ) {
834
- let mut rng = rand:: thread_rng ( ) ;
835
830
// Create a secret polynomial for each participant
836
831
let sp1 = ScalarPoly :: new ( vec ! [ s!( 3 ) , s!( 7 ) ] ) ;
837
832
let sp2 = ScalarPoly :: new ( vec ! [ s!( 11 ) , s!( 13 ) ] ) ;
@@ -847,9 +842,9 @@ mod test {
847
842
] ;
848
843
849
844
let KeyGen = frost. new_keygen ( point_polys) . unwrap ( ) ;
850
- let ( shares1, pop1) = frost. create_shares ( & KeyGen , sp1, & mut rng ) ;
851
- let ( shares2, pop2) = frost. create_shares ( & KeyGen , sp2, & mut rng ) ;
852
- let ( shares3, pop3) = frost. create_shares ( & KeyGen , sp3, & mut rng ) ;
845
+ let ( shares1, pop1) = frost. create_shares ( & KeyGen , sp1) ;
846
+ let ( shares2, pop2) = frost. create_shares ( & KeyGen , sp2) ;
847
+ let ( shares3, pop3) = frost. create_shares ( & KeyGen , sp3) ;
853
848
let proofs_of_possession = vec ! [ pop1, pop2, pop3] ;
854
849
855
850
let ( secret_share1, mut frost_key) = frost
@@ -881,18 +876,20 @@ mod test {
881
876
assert_eq ! ( frost_key, jk3) ;
882
877
883
878
let use_tweak = true ;
884
- if use_tweak {
885
- let tweak = Scalar :: from_bytes ( [
879
+ let tweak = if use_tweak {
880
+ Scalar :: from_bytes ( [
886
881
0xE8 , 0xF7 , 0x91 , 0xFF , 0x92 , 0x25 , 0xA2 , 0xAF , 0x01 , 0x02 , 0xAF , 0xFF , 0x4A , 0x9A ,
887
882
0x72 , 0x3D , 0x96 , 0x12 , 0xA6 , 0x82 , 0xA2 , 0x5E , 0xBE , 0x79 , 0x80 , 0x2B , 0x26 , 0x3C ,
888
883
0xDF , 0xCD , 0x83 , 0xBB ,
889
884
] )
890
- . unwrap ( ) ;
891
- // let tweak = Scalar::zero();
892
- frost_key = frost_key. tweak ( tweak. clone ( ) ) . expect ( "tweak worked" ) ;
893
- jk2 = jk2. tweak ( tweak. clone ( ) ) . expect ( "tweak worked" ) ;
894
- jk3 = jk3. tweak ( tweak) . expect ( "tweak worked" ) ;
895
- }
885
+ . unwrap ( )
886
+ } else {
887
+ Scalar :: zero ( )
888
+ } ;
889
+
890
+ frost_key = frost_key. tweak ( tweak. clone ( ) ) . expect ( "tweak worked" ) ;
891
+ jk2 = jk2. tweak ( tweak. clone ( ) ) . expect ( "tweak worked" ) ;
892
+ jk3 = jk3. tweak ( tweak) . expect ( "tweak worked" ) ;
896
893
897
894
// TODO USE PROPER SID
898
895
// public => [ b"r2-frost", my_index.to_be_bytes(), frost_key.joint_public_key, &frost_key.verification_shares[..], sid]
0 commit comments