@@ -25,6 +25,7 @@ use alloc::{
25
25
use derive_getters:: Getters ;
26
26
#[ cfg( any( test, feature = "test-impl" ) ) ]
27
27
use hex:: FromHex ;
28
+ use keys:: PublicKeyPackage ;
28
29
use rand_core:: { CryptoRng , RngCore } ;
29
30
use serialization:: SerializableScalar ;
30
31
use zeroize:: Zeroize ;
@@ -64,11 +65,7 @@ pub use verifying_key::VerifyingKey;
64
65
///
65
66
/// [challenge]: https://datatracker.ietf.org/doc/html/rfc9591#name-signature-challenge-computa
66
67
#[ derive( Copy , Clone ) ]
67
- #[ cfg_attr( feature = "internals" , visibility:: make( pub ) ) ]
68
- #[ cfg_attr( docsrs, doc( cfg( feature = "internals" ) ) ) ]
69
- pub ( crate ) struct Challenge < C : Ciphersuite > (
70
- pub ( crate ) <<C :: Group as Group >:: Field as Field >:: Scalar ,
71
- ) ;
68
+ pub struct Challenge < C : Ciphersuite > ( pub ( crate ) <<C :: Group as Group >:: Field as Field >:: Scalar ) ;
72
69
73
70
impl < C > Challenge < C >
74
71
where
@@ -138,6 +135,8 @@ where
138
135
/// Generates a random nonzero scalar.
139
136
///
140
137
/// It assumes that the Scalar Eq/PartialEq implementation is constant-time.
138
+ #[ cfg_attr( feature = "internals" , visibility:: make( pub ) ) ]
139
+ #[ cfg_attr( docsrs, doc( cfg( feature = "internals" ) ) ) ]
141
140
pub ( crate ) fn random_nonzero < C : Ciphersuite , R : RngCore + CryptoRng > ( rng : & mut R ) -> Scalar < C > {
142
141
loop {
143
142
let scalar = <<C :: Group as Group >:: Field >:: random ( rng) ;
@@ -192,9 +191,7 @@ where
192
191
///
193
192
/// <https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md>
194
193
#[ derive( Clone , PartialEq , Eq ) ]
195
- #[ cfg_attr( feature = "internals" , visibility:: make( pub ) ) ]
196
- #[ cfg_attr( docsrs, doc( cfg( feature = "internals" ) ) ) ]
197
- pub ( crate ) struct BindingFactor < C : Ciphersuite > ( Scalar < C > ) ;
194
+ pub struct BindingFactor < C : Ciphersuite > ( Scalar < C > ) ;
198
195
199
196
impl < C > BindingFactor < C >
200
197
where
@@ -469,9 +466,7 @@ where
469
466
/// The product of all signers' individual commitments, published as part of the
470
467
/// final signature.
471
468
#[ derive( Clone , PartialEq , Eq ) ]
472
- #[ cfg_attr( feature = "internals" , visibility:: make( pub ) ) ]
473
- #[ cfg_attr( docsrs, doc( cfg( feature = "internals" ) ) ) ]
474
- pub ( crate ) struct GroupCommitment < C : Ciphersuite > ( pub ( crate ) Element < C > ) ;
469
+ pub struct GroupCommitment < C : Ciphersuite > ( pub ( crate ) Element < C > ) ;
475
470
476
471
impl < C > GroupCommitment < C >
477
472
where
@@ -483,6 +478,12 @@ where
483
478
pub ( crate ) fn to_element ( self ) -> <C :: Group as Group >:: Element {
484
479
self . 0
485
480
}
481
+
482
+ /// Return the underlying element.
483
+ #[ cfg( feature = "internals" ) ]
484
+ pub fn from_element ( element : Element < C > ) -> Self {
485
+ Self ( element)
486
+ }
486
487
}
487
488
488
489
/// Generates the group commitment which is published as part of the joint
@@ -584,12 +585,15 @@ where
584
585
return Err ( Error :: UnknownIdentifier ) ;
585
586
}
586
587
588
+ let ( signing_package, signature_shares, pubkeys) =
589
+ <C >:: pre_aggregate ( signing_package, signature_shares, pubkeys) ?;
590
+
587
591
// Encodes the signing commitment list produced in round one as part of generating [`BindingFactor`], the
588
592
// binding factor.
589
593
let binding_factor_list: BindingFactorList < C > =
590
- compute_binding_factor_list ( signing_package, & pubkeys. verifying_key , & [ ] ) ?;
594
+ compute_binding_factor_list ( & signing_package, & pubkeys. verifying_key , & [ ] ) ?;
591
595
// Compute the group commitment from signing commitments produced in round one.
592
- let group_commitment = compute_group_commitment ( signing_package, & binding_factor_list) ?;
596
+ let group_commitment = compute_group_commitment ( & signing_package, & binding_factor_list) ?;
593
597
594
598
// The aggregation of the signature shares by summing them up, resulting in
595
599
// a plain Schnorr signature.
@@ -619,10 +623,10 @@ where
619
623
#[ cfg( feature = "cheater-detection" ) ]
620
624
if verification_result. is_err ( ) {
621
625
detect_cheater (
622
- group_commitment,
623
- pubkeys,
624
- signing_package,
625
- signature_shares,
626
+ & group_commitment,
627
+ & pubkeys,
628
+ & signing_package,
629
+ & signature_shares,
626
630
& binding_factor_list,
627
631
) ?;
628
632
}
@@ -637,17 +641,17 @@ where
637
641
/// Each share is verified to find the cheater
638
642
#[ cfg( feature = "cheater-detection" ) ]
639
643
fn detect_cheater < C : Ciphersuite > (
640
- group_commitment : GroupCommitment < C > ,
644
+ group_commitment : & GroupCommitment < C > ,
641
645
pubkeys : & keys:: PublicKeyPackage < C > ,
642
646
signing_package : & SigningPackage < C > ,
643
647
signature_shares : & BTreeMap < Identifier < C > , round2:: SignatureShare < C > > ,
644
648
binding_factor_list : & BindingFactorList < C > ,
645
649
) -> Result < ( ) , Error < C > > {
646
650
// Compute the per-message challenge.
647
- let challenge = crate :: challenge :: < C > (
651
+ let challenge = <C >:: challenge (
648
652
& group_commitment. 0 ,
649
653
& pubkeys. verifying_key ,
650
- signing_package. message ( ) . as_slice ( ) ,
654
+ signing_package. message ( ) ,
651
655
) ?;
652
656
653
657
// Verify the signature shares.
@@ -663,6 +667,7 @@ fn detect_cheater<C: Ciphersuite>(
663
667
* identifier,
664
668
signing_package,
665
669
binding_factor_list,
670
+ group_commitment,
666
671
signature_share,
667
672
verifying_share,
668
673
challenge,
@@ -688,24 +693,44 @@ pub fn verify_signature_share<C: Ciphersuite>(
688
693
signing_package : & SigningPackage < C > ,
689
694
verifying_key : & VerifyingKey < C > ,
690
695
) -> Result < ( ) , Error < C > > {
696
+ // In order to reuse `pre_aggregate()`, we need to create some "dummy" containers
697
+ let signature_shares = BTreeMap :: from ( [ ( identifier, * signature_share) ] ) ;
698
+ let verifying_shares = BTreeMap :: from ( [ ( identifier, * verifying_share) ] ) ;
699
+ let public_key_package = PublicKeyPackage :: new ( verifying_shares, * verifying_key) ;
700
+
701
+ let ( signing_package, signature_shares, pubkeys) =
702
+ <C >:: pre_aggregate ( signing_package, & signature_shares, & public_key_package) ?;
703
+
704
+ // Extract the processed values back from the "dummy" containers
705
+ let verifying_share = pubkeys
706
+ . verifying_shares ( )
707
+ . get ( & identifier)
708
+ . expect ( "pre_aggregate() must keep the identifiers" ) ;
709
+ let verifying_key = pubkeys. verifying_key ( ) ;
710
+ let signature_share = signature_shares
711
+ . get ( & identifier)
712
+ . expect ( "pre_aggregate() must keep the identifiers" ) ;
713
+
691
714
// Encodes the signing commitment list produced in round one as part of generating [`BindingFactor`], the
692
715
// binding factor.
693
716
let binding_factor_list: BindingFactorList < C > =
694
- compute_binding_factor_list ( signing_package, verifying_key, & [ ] ) ?;
717
+ compute_binding_factor_list ( & signing_package, verifying_key, & [ ] ) ?;
718
+
695
719
// Compute the group commitment from signing commitments produced in round one.
696
- let group_commitment = compute_group_commitment ( signing_package, & binding_factor_list) ?;
720
+ let group_commitment = compute_group_commitment ( & signing_package, & binding_factor_list) ?;
697
721
698
722
// Compute the per-message challenge.
699
- let challenge = crate :: challenge :: < C > (
700
- & group_commitment. to_element ( ) ,
723
+ let challenge = <C >:: challenge (
724
+ & group_commitment. clone ( ) . to_element ( ) ,
701
725
verifying_key,
702
726
signing_package. message ( ) . as_slice ( ) ,
703
727
) ?;
704
728
705
729
verify_signature_share_precomputed (
706
730
identifier,
707
- signing_package,
731
+ & signing_package,
708
732
& binding_factor_list,
733
+ & group_commitment,
709
734
signature_share,
710
735
verifying_share,
711
736
challenge,
@@ -720,6 +745,7 @@ fn verify_signature_share_precomputed<C: Ciphersuite>(
720
745
signature_share_identifier : Identifier < C > ,
721
746
signing_package : & SigningPackage < C > ,
722
747
binding_factor_list : & BindingFactorList < C > ,
748
+ group_commitment : & GroupCommitment < C > ,
723
749
signature_share : & round2:: SignatureShare < C > ,
724
750
verifying_share : & keys:: VerifyingShare < C > ,
725
751
challenge : Challenge < C > ,
@@ -735,7 +761,10 @@ fn verify_signature_share_precomputed<C: Ciphersuite>(
735
761
. ok_or ( Error :: UnknownIdentifier ) ?
736
762
. to_group_commitment_share ( binding_factor) ;
737
763
738
- signature_share. verify (
764
+ // Compute relation values to verify this signature share.
765
+ <C >:: verify_share (
766
+ group_commitment,
767
+ signature_share,
739
768
signature_share_identifier,
740
769
& R_share ,
741
770
verifying_share,
0 commit comments