@@ -156,35 +156,60 @@ impl Deref for Signature {
156
156
}
157
157
}
158
158
159
- impl PublicKey {
160
- /// Verifies that the signature `signature` is valid for the message
161
- /// `message`.
162
- pub fn verify ( & self , message : impl AsRef < [ u8 ] > , signature : & Signature ) -> Result < ( ) , Error > {
159
+ /// The state of a streaming verification operation.
160
+ pub struct VerifyingState {
161
+ hasher : sha512:: Hash ,
162
+ signature : Signature ,
163
+ a : GeP3 ,
164
+ }
165
+
166
+ impl Drop for VerifyingState {
167
+ fn drop ( & mut self ) {
168
+ Mem :: wipe ( self . signature . 0 ) ;
169
+ }
170
+ }
171
+
172
+ impl VerifyingState {
173
+ fn new ( pk : & PublicKey , signature : & Signature ) -> Result < Self , Error > {
163
174
let r = & signature[ 0 ..32 ] ;
164
175
let s = & signature[ 32 ..64 ] ;
165
176
sc_reject_noncanonical ( s) ?;
166
- if is_identity ( self ) || self . iter ( ) . fold ( 0 , |acc, x| acc | x) == 0 {
177
+ if is_identity ( pk ) || pk . iter ( ) . fold ( 0 , |acc, x| acc | x) == 0 {
167
178
return Err ( Error :: WeakPublicKey ) ;
168
179
}
169
- let a = match GeP3 :: from_bytes_negate_vartime ( self ) {
180
+ let a = match GeP3 :: from_bytes_negate_vartime ( pk ) {
170
181
Some ( g) => g,
171
182
None => {
172
183
return Err ( Error :: InvalidPublicKey ) ;
173
184
}
174
185
} ;
175
-
176
186
let mut hasher = sha512:: Hash :: new ( ) ;
177
187
hasher. update ( r) ;
178
- hasher. update ( & self [ ..] ) ;
179
- hasher. update ( message) ;
180
- let mut hash = hasher. finalize ( ) ;
188
+ hasher. update ( & pk[ ..] ) ;
189
+ Ok ( VerifyingState {
190
+ hasher,
191
+ signature : * signature,
192
+ a,
193
+ } )
194
+ }
195
+
196
+ /// Appends data to the message being verified.
197
+ pub fn absorb ( & mut self , chunk : impl AsRef < [ u8 ] > ) {
198
+ self . hasher . update ( chunk)
199
+ }
200
+
201
+ /// Verifies the signature and return it.
202
+ pub fn verify ( & self ) -> Result < ( ) , Error > {
203
+ let s = & self . signature [ 32 ..64 ] ;
204
+
205
+ let mut hash = self . hasher . finalize ( ) ;
181
206
sc_reduce ( & mut hash) ;
182
207
183
- let r = GeP2 :: double_scalarmult_vartime ( hash. as_ref ( ) , a, s) ;
208
+ let r = GeP2 :: double_scalarmult_vartime ( hash. as_ref ( ) , self . a , s) ;
184
209
if r. to_bytes ( )
185
210
. as_ref ( )
186
211
. iter ( )
187
- . zip ( signature. iter ( ) )
212
+ . zip ( self . signature . iter ( ) )
188
213
. fold ( 0 , |acc, ( x, y) | acc | ( x ^ y) )
189
214
!= 0
190
215
{
@@ -195,7 +220,99 @@ impl PublicKey {
195
220
}
196
221
}
197
222
223
+ impl PublicKey {
224
+ /// Verify the signature of a multi-part message (streaming).
225
+ pub fn verify_incremental ( & self , signature : & Signature ) -> Result < VerifyingState , Error > {
226
+ VerifyingState :: new ( self , signature)
227
+ }
228
+
229
+ /// Verifies that the signature `signature` is valid for the message
230
+ /// `message`.
231
+ pub fn verify ( & self , message : impl AsRef < [ u8 ] > , signature : & Signature ) -> Result < ( ) , Error > {
232
+ let mut st = VerifyingState :: new ( self , signature) ?;
233
+ st. absorb ( message) ;
234
+ st. verify ( )
235
+ }
236
+ }
237
+
238
+ /// The state of a streaming signature operation.
239
+ pub struct SigningState {
240
+ hasher : sha512:: Hash ,
241
+ az : [ u8 ; 64 ] ,
242
+ nonce : [ u8 ; 64 ] ,
243
+ }
244
+
245
+ impl Drop for SigningState {
246
+ fn drop ( & mut self ) {
247
+ Mem :: wipe ( self . az ) ;
248
+ Mem :: wipe ( self . nonce ) ;
249
+ }
250
+ }
251
+
252
+ impl SigningState {
253
+ fn new ( nonce : [ u8 ; 64 ] , az : [ u8 ; 64 ] , pk_ : & [ u8 ] ) -> Self {
254
+ let mut prefix: [ u8 ; 64 ] = [ 0 ; 64 ] ;
255
+ let r = ge_scalarmult_base ( & nonce[ 0 ..32 ] ) ;
256
+ prefix[ 0 ..32 ] . copy_from_slice ( & r. to_bytes ( ) [ ..] ) ;
257
+ prefix[ 32 ..64 ] . copy_from_slice ( pk_) ;
258
+
259
+ let mut st = sha512:: Hash :: new ( ) ;
260
+ st. update ( prefix) ;
261
+
262
+ SigningState {
263
+ hasher : st,
264
+ nonce,
265
+ az,
266
+ }
267
+ }
268
+
269
+ /// Appends data to the message being signed.
270
+ pub fn absorb ( & mut self , chunk : impl AsRef < [ u8 ] > ) {
271
+ self . hasher . update ( chunk)
272
+ }
273
+
274
+ /// Computes the signature and return it.
275
+ pub fn sign ( self ) -> Signature {
276
+ let mut signature: [ u8 ; 64 ] = [ 0 ; 64 ] ;
277
+ let r = ge_scalarmult_base ( & self . nonce [ 0 ..32 ] ) ;
278
+ signature[ 0 ..32 ] . copy_from_slice ( & r. to_bytes ( ) [ ..] ) ;
279
+ let mut hram = self . hasher . finalize ( ) ;
280
+ sc_reduce ( & mut hram) ;
281
+ sc_muladd (
282
+ & mut signature[ 32 ..64 ] ,
283
+ & hram[ 0 ..32 ] ,
284
+ & self . az [ 0 ..32 ] ,
285
+ & self . nonce [ 0 ..32 ] ,
286
+ ) ;
287
+ Signature ( signature)
288
+ }
289
+ }
290
+
198
291
impl SecretKey {
292
+ /// Sign a multi-part message (streaming API).
293
+ /// It is critical for `noise` to never repeat.
294
+ pub fn sign_incremental ( & self , noise : Noise ) -> SigningState {
295
+ let seed = & self [ 0 ..32 ] ;
296
+ let pk = & self [ 32 ..64 ] ;
297
+ let az: [ u8 ; 64 ] = {
298
+ let mut hash_output = sha512:: Hash :: hash ( seed) ;
299
+ hash_output[ 0 ] &= 248 ;
300
+ hash_output[ 31 ] &= 63 ;
301
+ hash_output[ 31 ] |= 64 ;
302
+ hash_output
303
+ } ;
304
+ let mut st = sha512:: Hash :: new ( ) ;
305
+ #[ cfg( feature = "random" ) ]
306
+ {
307
+ let additional_noise = Noise :: generate ( ) ;
308
+ st. update ( additional_noise. as_ref ( ) ) ;
309
+ }
310
+ st. update ( noise. as_ref ( ) ) ;
311
+ st. update ( seed) ;
312
+ let nonce = st. finalize ( ) ;
313
+ SigningState :: new ( nonce, az, pk)
314
+ }
315
+
199
316
/// Computes a signature for the message `message` using the secret key.
200
317
/// The noise parameter is optional, but recommended in order to mitigate
201
318
/// fault attacks.
@@ -222,22 +339,9 @@ impl SecretKey {
222
339
sc_reduce ( & mut hash_output[ 0 ..64 ] ) ;
223
340
hash_output
224
341
} ;
225
- let mut signature: [ u8 ; 64 ] = [ 0 ; 64 ] ;
226
- let r = ge_scalarmult_base ( & nonce[ 0 ..32 ] ) ;
227
- signature[ 0 ..32 ] . copy_from_slice ( & r. to_bytes ( ) [ ..] ) ;
228
- signature[ 32 ..64 ] . copy_from_slice ( pk) ;
229
- let mut hasher = sha512:: Hash :: new ( ) ;
230
- hasher. update ( signature. as_ref ( ) ) ;
231
- hasher. update ( & message) ;
232
- let mut hram = hasher. finalize ( ) ;
233
- sc_reduce ( & mut hram) ;
234
- sc_muladd (
235
- & mut signature[ 32 ..64 ] ,
236
- & hram[ 0 ..32 ] ,
237
- & az[ 0 ..32 ] ,
238
- & nonce[ 0 ..32 ] ,
239
- ) ;
240
- let signature = Signature ( signature) ;
342
+ let mut st = SigningState :: new ( nonce, az, pk) ;
343
+ st. absorb ( & message) ;
344
+ let signature = st. sign ( ) ;
241
345
242
346
#[ cfg( feature = "self-verify" ) ]
243
347
{
@@ -246,6 +350,7 @@ impl SecretKey {
246
350
. verify ( message, & signature)
247
351
. expect ( "Newly created signature cannot be verified" ) ;
248
352
}
353
+
249
354
signature
250
355
}
251
356
}
@@ -751,3 +856,22 @@ fn test_blind_ed25519() {
751
856
assert_eq ! ( Hex :: decode_to_vec( "947bacfabc63448f8955dc20630e069e58f37b72bb433ae17f2fa904ea860b44deb761705a3cc2168a6673ee0b41ff7765c7a4896941eec6833c1689315acb0b" ,
752
857
None ) . unwrap( ) , signature. as_ref( ) ) ;
753
858
}
859
+
860
+ #[ test]
861
+ fn test_streaming ( ) {
862
+ let kp = KeyPair :: generate ( ) ;
863
+
864
+ let msg1 = "mes" ;
865
+ let msg2 = "sage" ;
866
+ let mut st = kp. sk . sign_incremental ( Noise :: default ( ) ) ;
867
+ st. absorb ( msg1) ;
868
+ st. absorb ( msg2) ;
869
+ let signature = st. sign ( ) ;
870
+
871
+ let msg1 = "mess" ;
872
+ let msg2 = "age" ;
873
+ let mut st = kp. pk . verify_incremental ( & signature) . unwrap ( ) ;
874
+ st. absorb ( msg1) ;
875
+ st. absorb ( msg2) ;
876
+ assert ! ( st. verify( ) . is_ok( ) ) ;
877
+ }
0 commit comments