@@ -26,7 +26,7 @@ use std::{error, fmt};
26
26
27
27
use curve25519_dalek:: constants:: ED25519_BASEPOINT_POINT ;
28
28
use curve25519_dalek:: edwards:: { CompressedEdwardsY , EdwardsPoint } ;
29
- use curve25519_dalek:: scalar:: Scalar as ed25519_Scalar;
29
+ use curve25519_dalek:: scalar:: { clamp_integer , Scalar as ed25519_Scalar} ;
30
30
use rand;
31
31
use sha2:: { Digest , Sha512 } ;
32
32
@@ -181,6 +181,7 @@ impl VRFPublicKey {
181
181
pub enum Error {
182
182
InvalidPublicKey ,
183
183
InvalidDataError ,
184
+ InvalidHashPoints ,
184
185
OSRNGError ( rand:: Error ) ,
185
186
}
186
187
@@ -189,6 +190,7 @@ impl fmt::Display for Error {
189
190
match * self {
190
191
Error :: InvalidPublicKey => write ! ( f, "Invalid public key" ) ,
191
192
Error :: InvalidDataError => write ! ( f, "No data could be found" ) ,
193
+ Error :: InvalidHashPoints => write ! ( f, "VRF hash points did not yield a valid scalar" ) ,
192
194
Error :: OSRNGError ( ref e) => fmt:: Display :: fmt ( e, f) ,
193
195
}
194
196
}
@@ -199,6 +201,7 @@ impl error::Error for Error {
199
201
match * self {
200
202
Error :: InvalidPublicKey => None ,
201
203
Error :: InvalidDataError => None ,
204
+ Error :: InvalidHashPoints => None ,
202
205
Error :: OSRNGError ( ref e) => Some ( e) ,
203
206
}
204
207
}
@@ -246,7 +249,7 @@ impl VRFProof {
246
249
247
250
#[ allow( clippy:: needless_range_loop) ]
248
251
pub fn check_c ( c : & ed25519_Scalar ) -> bool {
249
- let c_bytes = c. reduce ( ) . to_bytes ( ) ;
252
+ let c_bytes = c. to_bytes ( ) ;
250
253
251
254
// upper 16 bytes of c must be 0's
252
255
for c_byte in c_bytes[ 16 ..32 ] . iter ( ) {
@@ -281,7 +284,9 @@ impl VRFProof {
281
284
// 0 32 48 80
282
285
// |----------------------------|----------|---------------------------|
283
286
// Gamma point c scalar s scalar
284
- let gamma_opt = CompressedEdwardsY :: from_slice ( & bytes[ 0 ..32 ] ) . decompress ( ) ;
287
+ let gamma_opt = CompressedEdwardsY :: from_slice ( & bytes[ 0 ..32 ] )
288
+ . ok ( )
289
+ . and_then ( |y| y. decompress ( ) ) ;
285
290
if gamma_opt. is_none ( ) {
286
291
test_debug ! ( "Invalid Gamma" ) ;
287
292
return None ;
@@ -297,10 +302,14 @@ impl VRFProof {
297
302
298
303
c_buf[ ..16 ] . copy_from_slice ( & bytes[ 32 ..( 16 + 32 ) ] ) ;
299
304
s_buf[ ..32 ] . copy_from_slice ( & bytes[ 48 ..( 32 + 48 ) ] ) ;
300
- let c = ed25519_Scalar:: from_canonical_bytes ( c_buf) ?;
301
- let s = ed25519_Scalar:: from_canonical_bytes ( s_buf) ?;
302
-
303
- Some ( VRFProof { Gamma : gamma, c, s } )
305
+ let c: Option < ed25519_Scalar > = ed25519_Scalar:: from_canonical_bytes ( c_buf) . into ( ) ;
306
+ let s: Option < ed25519_Scalar > = ed25519_Scalar:: from_canonical_bytes ( s_buf) . into ( ) ;
307
+
308
+ Some ( VRFProof {
309
+ Gamma : gamma,
310
+ c : c?,
311
+ s : s?,
312
+ } )
304
313
}
305
314
_ => None ,
306
315
}
@@ -324,7 +333,7 @@ impl VRFProof {
324
333
"FATAL ERROR: somehow constructed an invalid ECVRF proof"
325
334
) ;
326
335
327
- let c_bytes = self . c . reduce ( ) . to_bytes ( ) ;
336
+ let c_bytes = self . c . to_bytes ( ) ;
328
337
c_bytes_16[ 0 ..16 ] . copy_from_slice ( & c_bytes[ 0 ..16 ] ) ;
329
338
330
339
let gamma_bytes = self . Gamma . compress ( ) . to_bytes ( ) ;
@@ -386,7 +395,7 @@ impl VRF {
386
395
}
387
396
388
397
let y = CompressedEdwardsY :: from_slice ( & hasher. finalize ( ) [ 0 ..32 ] ) ;
389
- if let Some ( h) = y. decompress ( ) {
398
+ if let Some ( h) = y. ok ( ) . and_then ( |y| y . decompress ( ) ) {
390
399
break h;
391
400
}
392
401
@@ -445,8 +454,7 @@ impl VRF {
445
454
let mut h_32 = [ 0u8 ; 32 ] ;
446
455
h_32. copy_from_slice ( & h[ 0 ..32 ] ) ;
447
456
448
- let x_scalar_raw = ed25519_Scalar:: from_bits ( h_32) ;
449
- let x_scalar = x_scalar_raw. reduce ( ) ; // use the canonical scalar for the private key
457
+ let x_scalar = ed25519_Scalar:: from_bytes_mod_order ( clamp_integer ( h_32) ) ;
450
458
451
459
trunc_hash. copy_from_slice ( & h[ 32 ..64 ] ) ;
452
460
@@ -469,17 +477,17 @@ impl VRF {
469
477
470
478
/// Convert a 16-byte string into a scalar.
471
479
/// The upper 16 bytes in the resulting scalar MUST BE 0's
472
- fn ed25519_scalar_from_hash128 ( hash128 : & [ u8 ; 16 ] ) -> ed25519_Scalar {
480
+ fn ed25519_scalar_from_hash128 ( hash128 : & [ u8 ; 16 ] ) -> Option < ed25519_Scalar > {
473
481
let mut scalar_buf = [ 0u8 ; 32 ] ;
474
482
scalar_buf[ 0 ..16 ] . copy_from_slice ( hash128) ;
475
483
476
- ed25519_Scalar:: from_bits ( scalar_buf)
484
+ ed25519_Scalar:: from_canonical_bytes ( scalar_buf) . into ( )
477
485
}
478
486
479
487
/// ECVRF proof routine
480
488
/// https://tools.ietf.org/id/draft-irtf-cfrg-vrf-02.html#rfc.section.5.1
481
489
#[ allow( clippy:: op_ref) ]
482
- pub fn prove ( secret : & VRFPrivateKey , alpha : & [ u8 ] ) -> VRFProof {
490
+ pub fn prove ( secret : & VRFPrivateKey , alpha : & [ u8 ] ) -> Option < VRFProof > {
483
491
let ( Y_point , x_scalar, trunc_hash) = VRF :: expand_privkey ( secret) ;
484
492
let H_point = VRF :: hash_to_curve ( & Y_point , alpha) ;
485
493
@@ -490,15 +498,15 @@ impl VRF {
490
498
let kH_point = & k_scalar * & H_point ;
491
499
492
500
let c_hashbuf = VRF :: hash_points ( & H_point , & Gamma_point , & kB_point, & kH_point) ;
493
- let c_scalar = VRF :: ed25519_scalar_from_hash128 ( & c_hashbuf) ;
501
+ let c_scalar = VRF :: ed25519_scalar_from_hash128 ( & c_hashbuf) ? ;
494
502
495
- let s_full_scalar = & k_scalar + & c_scalar * & x_scalar;
496
- let s_scalar = s_full_scalar. reduce ( ) ;
503
+ let s_scalar = & k_scalar + & c_scalar * & x_scalar;
497
504
498
505
// NOTE: expect() won't panic because c_scalar is guaranteed to have
499
506
// its upper 16 bytes as 0
500
507
VRFProof :: new ( Gamma_point , c_scalar, s_scalar)
501
- . expect ( "FATAL ERROR: upper-16 bytes of proof's C scalar are NOT 0" )
508
+ . inspect_err ( |e| error ! ( "FATAL: upper-16 bytes of proof's C scalar are NOT 0: {e}" ) )
509
+ . ok ( )
502
510
}
503
511
504
512
/// Given a public key, verify that the private key owner that generate the ECVRF proof did so on the given message.
@@ -509,19 +517,21 @@ impl VRF {
509
517
#[ allow( clippy:: op_ref) ]
510
518
pub fn verify ( Y_point : & VRFPublicKey , proof : & VRFProof , alpha : & [ u8 ] ) -> Result < bool , Error > {
511
519
let H_point = VRF :: hash_to_curve ( Y_point , alpha) ;
512
- let s_reduced = proof. s ( ) . reduce ( ) ;
520
+ let s_reduced = proof. s ( ) ;
513
521
let Y_point_ed = CompressedEdwardsY ( Y_point . to_bytes ( ) )
514
522
. decompress ( )
515
523
. ok_or ( Error :: InvalidPublicKey ) ?;
516
524
if proof. Gamma ( ) . is_small_order ( ) {
517
525
return Err ( Error :: InvalidPublicKey ) ;
518
526
}
519
527
520
- let U_point = & s_reduced * & ED25519_BASEPOINT_POINT - proof. c ( ) * Y_point_ed ;
521
- let V_point = & s_reduced * & H_point - proof. c ( ) * proof. Gamma ( ) ;
528
+ let U_point = s_reduced * & ED25519_BASEPOINT_POINT - proof. c ( ) * Y_point_ed ;
529
+ let V_point = s_reduced * & H_point - proof. c ( ) * proof. Gamma ( ) ;
522
530
523
531
let c_prime_hashbuf = VRF :: hash_points ( & H_point , proof. Gamma ( ) , & U_point , & V_point ) ;
524
- let c_prime = VRF :: ed25519_scalar_from_hash128 ( & c_prime_hashbuf) ;
532
+ let Some ( c_prime) = VRF :: ed25519_scalar_from_hash128 ( & c_prime_hashbuf) else {
533
+ return Err ( Error :: InvalidHashPoints ) ;
534
+ } ;
525
535
526
536
// NOTE: this leverages constant-time comparison inherited from the Scalar impl
527
537
Ok ( c_prime == * ( proof. c ( ) ) )
@@ -583,7 +593,7 @@ mod tests {
583
593
let privk = VRFPrivateKey :: from_bytes ( & proof_fixture. privkey [ ..] ) . unwrap ( ) ;
584
594
let expected_proof_bytes = & proof_fixture. proof [ ..] ;
585
595
586
- let proof = VRF :: prove ( & privk, & alpha. to_vec ( ) ) ;
596
+ let proof = VRF :: prove ( & privk, & alpha. to_vec ( ) ) . unwrap ( ) ;
587
597
let proof_bytes = proof. to_bytes ( ) ;
588
598
589
599
assert_eq ! ( proof_bytes. to_vec( ) , expected_proof_bytes. to_vec( ) ) ;
@@ -605,7 +615,7 @@ mod tests {
605
615
let mut msg = [ 0u8 ; 1024 ] ;
606
616
rng. fill_bytes ( & mut msg) ;
607
617
608
- let proof = VRF :: prove ( & secret_key, & msg) ;
618
+ let proof = VRF :: prove ( & secret_key, & msg) . unwrap ( ) ;
609
619
let res = VRF :: verify ( & public_key, & proof, & msg) . unwrap ( ) ;
610
620
611
621
assert ! ( res) ;
0 commit comments