8
8
// - Deirdre Connolly <[email protected] >
9
9
// - Henry de Valence <[email protected] >
10
10
11
- //! Performs batch RedJubjub signature verification.
11
+ //! Performs batch RedDSA signature verification.
12
12
//!
13
13
//! Batch verification asks whether *all* signatures in some set are valid,
14
14
//! rather than asking whether *each* of them is valid. This allows sharing
20
20
21
21
use std:: convert:: TryFrom ;
22
22
23
- use jubjub:: * ;
23
+ use group:: {
24
+ cofactor:: CofactorGroup ,
25
+ ff:: { Field , PrimeField } ,
26
+ GroupEncoding ,
27
+ } ;
24
28
use rand_core:: { CryptoRng , RngCore } ;
25
29
26
- use crate :: { private:: Sealed , scalar_mul:: VartimeMultiscalarMul , * } ;
30
+ use crate :: { private:: SealedScalar , scalar_mul:: VartimeMultiscalarMul , * } ;
27
31
28
32
// Shim to generate a random 128bit value in a [u64; 4], without
29
33
// importing `rand`.
@@ -35,16 +39,16 @@ fn gen_128_bits<R: RngCore + CryptoRng>(mut rng: R) -> [u64; 4] {
35
39
}
36
40
37
41
#[ derive( Clone , Debug ) ]
38
- enum Inner {
42
+ enum Inner < S : SpendAuth , B : Binding < Scalar = S :: Scalar , Point = S :: Point > > {
39
43
SpendAuth {
40
- vk_bytes : VerificationKeyBytes < SpendAuth > ,
41
- sig : Signature < SpendAuth > ,
42
- c : Scalar ,
44
+ vk_bytes : VerificationKeyBytes < S > ,
45
+ sig : Signature < S > ,
46
+ c : S :: Scalar ,
43
47
} ,
44
48
Binding {
45
- vk_bytes : VerificationKeyBytes < Binding > ,
46
- sig : Signature < Binding > ,
47
- c : Scalar ,
49
+ vk_bytes : VerificationKeyBytes < B > ,
50
+ sig : Signature < B > ,
51
+ c : B :: Scalar ,
48
52
} ,
49
53
}
50
54
@@ -54,26 +58,19 @@ enum Inner {
54
58
/// lifetime of the message. This is useful when using the batch verification API
55
59
/// in an async context.
56
60
#[ derive( Clone , Debug ) ]
57
- pub struct Item {
58
- inner : Inner ,
61
+ pub struct Item < S : SpendAuth , B : Binding < Scalar = S :: Scalar , Point = S :: Point > > {
62
+ inner : Inner < S , B > ,
59
63
}
60
64
61
- impl < ' msg , M : AsRef < [ u8 ] > >
62
- From < (
63
- VerificationKeyBytes < SpendAuth > ,
64
- Signature < SpendAuth > ,
65
- & ' msg M ,
66
- ) > for Item
67
- {
68
- fn from (
69
- ( vk_bytes, sig, msg) : (
70
- VerificationKeyBytes < SpendAuth > ,
71
- Signature < SpendAuth > ,
72
- & ' msg M ,
73
- ) ,
65
+ impl < S : SpendAuth , B : Binding < Scalar = S :: Scalar , Point = S :: Point > > Item < S , B > {
66
+ /// Create a batch item from a `SpendAuth` signature.
67
+ pub fn from_spendauth < ' msg , M : AsRef < [ u8 ] > > (
68
+ vk_bytes : VerificationKeyBytes < S > ,
69
+ sig : Signature < S > ,
70
+ msg : & ' msg M ,
74
71
) -> Self {
75
72
// Compute c now to avoid dependency on the msg lifetime.
76
- let c = HStar :: default ( )
73
+ let c = HStar :: < S > :: default ( )
77
74
. update ( & sig. r_bytes [ ..] )
78
75
. update ( & vk_bytes. bytes [ ..] )
79
76
. update ( msg)
@@ -82,16 +79,15 @@ impl<'msg, M: AsRef<[u8]>>
82
79
inner : Inner :: SpendAuth { vk_bytes, sig, c } ,
83
80
}
84
81
}
85
- }
86
82
87
- impl < ' msg , M : AsRef < [ u8 ] > > From < ( VerificationKeyBytes < Binding > , Signature < Binding > , & ' msg M ) >
88
- for Item
89
- {
90
- fn from (
91
- ( vk_bytes , sig , msg) : ( VerificationKeyBytes < Binding > , Signature < Binding > , & ' msg M ) ,
83
+ /// Create a batch item from a `Binding` signature.
84
+ pub fn from_binding < ' msg , M : AsRef < [ u8 ] > > (
85
+ vk_bytes : VerificationKeyBytes < B > ,
86
+ sig : Signature < B > ,
87
+ msg : & ' msg M ,
92
88
) -> Self {
93
89
// Compute c now to avoid dependency on the msg lifetime.
94
- let c = HStar :: default ( )
90
+ let c = HStar :: < B > :: default ( )
95
91
. update ( & sig. r_bytes [ ..] )
96
92
. update ( & vk_bytes. bytes [ ..] )
97
93
. update ( msg)
@@ -100,9 +96,7 @@ impl<'msg, M: AsRef<[u8]>> From<(VerificationKeyBytes<Binding>, Signature<Bindin
100
96
inner : Inner :: Binding { vk_bytes, sig, c } ,
101
97
}
102
98
}
103
- }
104
99
105
- impl Item {
106
100
/// Perform non-batched verification of this `Item`.
107
101
///
108
102
/// This is useful (in combination with `Item::clone`) for implementing fallback
@@ -113,31 +107,36 @@ impl Item {
113
107
#[ allow( non_snake_case) ]
114
108
pub fn verify_single ( self ) -> Result < ( ) , Error > {
115
109
match self . inner {
116
- Inner :: Binding { vk_bytes, sig, c } => VerificationKey :: < Binding > :: try_from ( vk_bytes)
117
- . and_then ( |vk| vk. verify_prehashed ( & sig, c) ) ,
110
+ Inner :: Binding { vk_bytes, sig, c } => {
111
+ VerificationKey :: < B > :: try_from ( vk_bytes) . and_then ( |vk| vk. verify_prehashed ( & sig, c) )
112
+ }
118
113
Inner :: SpendAuth { vk_bytes, sig, c } => {
119
- VerificationKey :: < SpendAuth > :: try_from ( vk_bytes)
120
- . and_then ( |vk| vk. verify_prehashed ( & sig, c) )
114
+ VerificationKey :: < S > :: try_from ( vk_bytes) . and_then ( |vk| vk. verify_prehashed ( & sig, c) )
121
115
}
122
116
}
123
117
}
124
118
}
125
119
126
- #[ derive( Default ) ]
127
120
/// A batch verification context.
128
- pub struct Verifier {
121
+ pub struct Verifier < S : SpendAuth , B : Binding < Scalar = S :: Scalar , Point = S :: Point > > {
129
122
/// Signature data queued for verification.
130
- signatures : Vec < Item > ,
123
+ signatures : Vec < Item < S , B > > ,
124
+ }
125
+
126
+ impl < S : SpendAuth , B : Binding < Scalar = S :: Scalar , Point = S :: Point > > Default for Verifier < S , B > {
127
+ fn default ( ) -> Self {
128
+ Verifier { signatures : vec ! [ ] }
129
+ }
131
130
}
132
131
133
- impl Verifier {
132
+ impl < S : SpendAuth , B : Binding < Scalar = S :: Scalar , Point = S :: Point > > Verifier < S , B > {
134
133
/// Construct a new batch verifier.
135
- pub fn new ( ) -> Verifier {
134
+ pub fn new ( ) -> Verifier < S , B > {
136
135
Verifier :: default ( )
137
136
}
138
137
139
138
/// Queue an Item for verification.
140
- pub fn queue < I : Into < Item > > ( & mut self , item : I ) {
139
+ pub fn queue < I : Into < Item < S , B > > > ( & mut self , item : I ) {
141
140
self . signatures . push ( item. into ( ) ) ;
142
141
}
143
142
@@ -163,7 +162,7 @@ impl Verifier {
163
162
/// - h_G is the cofactor of the group;
164
163
/// - P_G is the generator of the subgroup;
165
164
///
166
- /// Since RedJubjub uses different subgroups for different types
165
+ /// Since RedDSA uses different subgroups for different types
167
166
/// of signatures, SpendAuth's and Binding's, we need to have yet
168
167
/// another point and associated scalar accumulator for all the
169
168
/// signatures of each type in our batch, but we can still
@@ -185,8 +184,8 @@ impl Verifier {
185
184
let mut VKs = Vec :: with_capacity ( n) ;
186
185
let mut R_coeffs = Vec :: with_capacity ( self . signatures . len ( ) ) ;
187
186
let mut Rs = Vec :: with_capacity ( self . signatures . len ( ) ) ;
188
- let mut P_spendauth_coeff = Scalar :: zero ( ) ;
189
- let mut P_binding_coeff = Scalar :: zero ( ) ;
187
+ let mut P_spendauth_coeff = S :: Scalar :: zero ( ) ;
188
+ let mut P_binding_coeff = B :: Scalar :: zero ( ) ;
190
189
191
190
for item in self . signatures . iter ( ) {
192
191
let ( s_bytes, r_bytes, c) = match item. inner {
@@ -196,7 +195,9 @@ impl Verifier {
196
195
197
196
let s = {
198
197
// XXX-jubjub: should not use CtOption here
199
- let maybe_scalar = Scalar :: from_bytes ( & s_bytes) ;
198
+ let mut repr = <S :: Scalar as PrimeField >:: Repr :: default ( ) ;
199
+ repr. as_mut ( ) . copy_from_slice ( & s_bytes) ;
200
+ let maybe_scalar = S :: Scalar :: from_repr ( repr) ;
200
201
if maybe_scalar. is_some ( ) . into ( ) {
201
202
maybe_scalar. unwrap ( )
202
203
} else {
@@ -207,24 +208,26 @@ impl Verifier {
207
208
let R = {
208
209
// XXX-jubjub: should not use CtOption here
209
210
// XXX-jubjub: inconsistent ownership in from_bytes
210
- let maybe_point = AffinePoint :: from_bytes ( r_bytes) ;
211
+ let mut repr = <S :: Point as GroupEncoding >:: Repr :: default ( ) ;
212
+ repr. as_mut ( ) . copy_from_slice ( & r_bytes) ;
213
+ let maybe_point = S :: Point :: from_bytes ( & repr) ;
211
214
if maybe_point. is_some ( ) . into ( ) {
212
- jubjub :: ExtendedPoint :: from ( maybe_point. unwrap ( ) )
215
+ maybe_point. unwrap ( )
213
216
} else {
214
217
return Err ( Error :: InvalidSignature ) ;
215
218
}
216
219
} ;
217
220
218
221
let VK = match item. inner {
219
222
Inner :: SpendAuth { vk_bytes, .. } => {
220
- VerificationKey :: < SpendAuth > :: try_from ( vk_bytes. bytes ) ?. point
223
+ VerificationKey :: < S > :: try_from ( vk_bytes. bytes ) ?. point
221
224
}
222
225
Inner :: Binding { vk_bytes, .. } => {
223
- VerificationKey :: < Binding > :: try_from ( vk_bytes. bytes ) ?. point
226
+ VerificationKey :: < B > :: try_from ( vk_bytes. bytes ) ?. point
224
227
}
225
228
} ;
226
229
227
- let z = Scalar :: from_raw ( gen_128_bits ( & mut rng) ) ;
230
+ let z = S :: Scalar :: from_raw ( gen_128_bits ( & mut rng) ) ;
228
231
229
232
let P_coeff = z * s;
230
233
match item. inner {
@@ -239,7 +242,7 @@ impl Verifier {
239
242
R_coeffs . push ( z) ;
240
243
Rs . push ( R ) ;
241
244
242
- VK_coeffs . push ( Scalar :: zero ( ) + ( z * c) ) ;
245
+ VK_coeffs . push ( S :: Scalar :: zero ( ) + ( z * c) ) ;
243
246
VKs . push ( VK ) ;
244
247
}
245
248
@@ -250,10 +253,10 @@ impl Verifier {
250
253
. chain ( VK_coeffs . iter ( ) )
251
254
. chain ( R_coeffs . iter ( ) ) ;
252
255
253
- let basepoints = [ SpendAuth :: basepoint ( ) , Binding :: basepoint ( ) ] ;
256
+ let basepoints = [ S :: basepoint ( ) , B :: basepoint ( ) ] ;
254
257
let points = basepoints. iter ( ) . chain ( VKs . iter ( ) ) . chain ( Rs . iter ( ) ) ;
255
258
256
- let check = ExtendedPoint :: vartime_multiscalar_mul ( scalars, points) ;
259
+ let check = S :: Point :: vartime_multiscalar_mul ( scalars, points) ;
257
260
258
261
if check. is_small_order ( ) . into ( ) {
259
262
Ok ( ( ) )
0 commit comments