@@ -53,7 +53,7 @@ use secp256kfun::{
5353/// certifying the aggregated keygen input in certpedpop.
5454pub trait CertificationScheme {
5555 /// The signature type produced by this scheme
56- type Signature : Clone + core:: fmt:: Debug + PartialEq ;
56+ type Signature : Clone + core:: fmt:: Debug ;
5757
5858 /// Sign the AggKeygenInput with the given keypair
5959 fn certify ( & self , keypair : & KeyPair , agg_input : & encpedpop:: AggKeygenInput ) -> Self :: Signature ;
@@ -91,6 +91,115 @@ impl<H: Hash32, NG: NonceGen> CertificationScheme for Schnorr<H, NG> {
9191 }
9292}
9393
94+ /// VRF-based implementation of CertificationScheme
95+ #[ cfg( feature = "vrf_cert_keygen" ) ]
96+ pub mod vrf_cert {
97+ use super :: * ;
98+ use vrf_fun:: VrfProof ;
99+
100+ /// A wrapper type for using VRF as a certification scheme
101+ pub struct VrfCertifier < V > {
102+ /// The underlying VRF instance
103+ pub vrf : V ,
104+ }
105+
106+ /// Create a VRF certification scheme with the RFC 9381 SSWU suite using SHA256
107+ pub fn sswu_vrf_sha256 ( ) -> VrfCertifier < vrf_fun:: Rfc9381SswuVrf < sha2:: Sha256 > > {
108+ VrfCertifier {
109+ vrf : vrf_fun:: Rfc9381SswuVrf :: default ( ) ,
110+ }
111+ }
112+
113+ /// Create a VRF certification scheme with the RFC 9381 TAI suite using SHA256
114+ pub fn tai_vrf_sha256 ( ) -> VrfCertifier < vrf_fun:: Rfc9381TaiVrf < sha2:: Sha256 > > {
115+ VrfCertifier {
116+ vrf : vrf_fun:: Rfc9381TaiVrf :: default ( ) ,
117+ }
118+ }
119+
120+ /// Implement CertificationScheme for VrfCertifier wrapping the SSWU VRF
121+ impl CertificationScheme for VrfCertifier < vrf_fun:: Rfc9381SswuVrf < sha2:: Sha256 > > {
122+ type Signature = VrfProof ;
123+
124+ fn certify (
125+ & self ,
126+ keypair : & KeyPair ,
127+ agg_input : & encpedpop:: AggKeygenInput ,
128+ ) -> Self :: Signature {
129+ // Use the certification bytes as the VRF input
130+ let cert_bytes = agg_input. cert_bytes ( ) ;
131+ vrf_fun:: rfc9381:: sswu:: prove :: < sha2:: Sha256 > ( keypair, & cert_bytes)
132+ }
133+
134+ fn verify_cert (
135+ & self ,
136+ cert_key : Point ,
137+ agg_input : & encpedpop:: AggKeygenInput ,
138+ signature : & Self :: Signature ,
139+ ) -> bool {
140+ // Use the certification bytes as the VRF input
141+ let cert_bytes = agg_input. cert_bytes ( ) ;
142+ vrf_fun:: rfc9381:: sswu:: verify :: < sha2:: Sha256 > ( cert_key, & cert_bytes, signature)
143+ . is_some ( )
144+ }
145+ }
146+
147+ /// Implement CertificationScheme for VrfCertifier wrapping the TAI VRF
148+ impl CertificationScheme for VrfCertifier < vrf_fun:: Rfc9381TaiVrf < sha2:: Sha256 > > {
149+ type Signature = VrfProof ;
150+
151+ fn certify (
152+ & self ,
153+ keypair : & KeyPair ,
154+ agg_input : & encpedpop:: AggKeygenInput ,
155+ ) -> Self :: Signature {
156+ // Use the certification bytes as the VRF input
157+ let cert_bytes = agg_input. cert_bytes ( ) ;
158+ vrf_fun:: rfc9381:: tai:: prove :: < sha2:: Sha256 > ( keypair, & cert_bytes)
159+ }
160+
161+ fn verify_cert (
162+ & self ,
163+ cert_key : Point ,
164+ agg_input : & encpedpop:: AggKeygenInput ,
165+ signature : & Self :: Signature ,
166+ ) -> bool {
167+ // Use the certification bytes as the VRF input
168+ let cert_bytes = agg_input. cert_bytes ( ) ;
169+ vrf_fun:: rfc9381:: tai:: verify :: < sha2:: Sha256 > ( cert_key, & cert_bytes, signature)
170+ . is_some ( )
171+ }
172+ }
173+
174+ /// Compute a randomness beacon from a set of VRF outputs
175+ ///
176+ /// This function takes all the VRF outputs (gamma points) from the certificate
177+ /// and hashes them together to produce unpredictable randomness that no single
178+ /// party could have controlled (as long as at least one party is honest).
179+ pub fn compute_randomness_beacon < S > ( certificate : & certpedpop:: Certificate < S > ) -> [ u8 ; 32 ]
180+ where
181+ S : CertificationScheme ,
182+ S :: Signature : AsRef < VrfProof > ,
183+ {
184+ use sha2:: { Digest , Sha256 } ;
185+
186+ let mut hasher = Sha256 :: new ( ) ;
187+
188+ // Sort by public key to ensure deterministic ordering
189+ let mut sorted_entries: Vec < _ > = certificate. iter ( ) . collect ( ) ;
190+ sorted_entries. sort_by_key ( |( pk, _) | pk. to_bytes ( ) ) ;
191+
192+ // Hash all the VRF gamma points
193+ for ( _, vrf_proof) in sorted_entries {
194+ let gamma = vrf_proof. as_ref ( ) . gamma ;
195+ hasher. update ( gamma. to_bytes ( ) ) ;
196+ }
197+
198+ // Get the hash output
199+ hasher. finalize ( ) . into ( )
200+ }
201+ }
202+
94203/// SimplePedPop is a bare bones secure distributed key generation algorithm that leaves a lot left
95204/// up to the application.
96205///
@@ -1103,7 +1212,7 @@ pub mod certpedpop {
11031212 }
11041213
11051214 /// A key generation session that has been certified by each certifying party (contributors and share receivers).
1106- #[ derive( Clone , Debug , PartialEq ) ]
1215+ #[ derive( Clone , Debug ) ]
11071216 pub struct CertifiedKeygen < S : CertificationScheme > {
11081217 input : AggKeygenInput ,
11091218 certificate : Certificate < S > ,
0 commit comments