@@ -10,7 +10,7 @@ use self::super_ffi::CPtr;
10
10
use super :: ffi as super_ffi;
11
11
use crate :: ecdsa:: Signature ;
12
12
use crate :: ffi:: recovery as ffi;
13
- use crate :: { key, Error , Message , Secp256k1 , Signing , Verification } ;
13
+ use crate :: { key, Error , Message } ;
14
14
15
15
/// A tag used for recovering the public key from a compact signature.
16
16
#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
@@ -157,7 +157,7 @@ impl RecoverableSignature {
157
157
#[ inline]
158
158
#[ cfg( feature = "global-context" ) ]
159
159
pub fn recover ( & self , msg : impl Into < Message > ) -> Result < key:: PublicKey , Error > {
160
- crate :: SECP256K1 . recover_ecdsa ( msg, self )
160
+ self . recover_ecdsa ( msg)
161
161
}
162
162
}
163
163
@@ -174,42 +174,49 @@ impl From<ffi::RecoverableSignature> for RecoverableSignature {
174
174
fn from ( sig : ffi:: RecoverableSignature ) -> RecoverableSignature { RecoverableSignature ( sig) }
175
175
}
176
176
177
- impl < C : Signing > Secp256k1 < C > {
177
+ impl RecoverableSignature {
178
178
fn sign_ecdsa_recoverable_with_noncedata_pointer (
179
- & self ,
180
179
msg : impl Into < Message > ,
181
180
sk : & key:: SecretKey ,
182
181
noncedata_ptr : * const super_ffi:: types:: c_void ,
183
- ) -> RecoverableSignature {
182
+ ) -> Self {
184
183
let msg = msg. into ( ) ;
185
184
let mut ret = ffi:: RecoverableSignature :: new ( ) ;
186
- unsafe {
187
- // We can assume the return value because it's not possible to construct
188
- // an invalid signature from a valid `Message` and `SecretKey`
189
- assert_eq ! (
190
- ffi:: secp256k1_ecdsa_sign_recoverable(
191
- self . ctx. as_ptr( ) ,
192
- & mut ret,
193
- msg. as_c_ptr( ) ,
194
- sk. as_c_ptr( ) ,
195
- super_ffi:: secp256k1_nonce_function_rfc6979,
196
- noncedata_ptr
197
- ) ,
198
- 1
199
- ) ;
185
+ // xor the secret key and message together to get a rerandomization seed
186
+ // for timing analysis defense-in-depth
187
+ let mut rerandomize = sk. secret_bytes ( ) ;
188
+ for ( rera, byte) in rerandomize. iter_mut ( ) . zip ( msg[ ..] . iter ( ) ) {
189
+ * rera ^= * byte;
200
190
}
191
+ crate :: with_raw_global_context (
192
+ |ctx| unsafe {
193
+ // We can assume the return value because it's not possible to construct
194
+ // an invalid signature from a valid `Message` and `SecretKey`
195
+ assert_eq ! (
196
+ ffi:: secp256k1_ecdsa_sign_recoverable(
197
+ ctx. as_ptr( ) ,
198
+ & mut ret,
199
+ msg. as_c_ptr( ) ,
200
+ sk. as_c_ptr( ) ,
201
+ super_ffi:: secp256k1_nonce_function_rfc6979,
202
+ noncedata_ptr
203
+ ) ,
204
+ 1
205
+ ) ;
206
+ } ,
207
+ Some ( & rerandomize) ,
208
+ ) ;
201
209
202
210
RecoverableSignature :: from ( ret)
203
211
}
204
212
205
213
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
206
214
/// Requires a signing-capable context.
207
215
pub fn sign_ecdsa_recoverable (
208
- & self ,
209
216
msg : impl Into < Message > ,
210
217
sk : & key:: SecretKey ,
211
218
) -> RecoverableSignature {
212
- self . sign_ecdsa_recoverable_with_noncedata_pointer ( msg, sk, ptr:: null ( ) )
219
+ Self :: sign_ecdsa_recoverable_with_noncedata_pointer ( msg, sk, ptr:: null ( ) )
213
220
}
214
221
215
222
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
@@ -218,38 +225,34 @@ impl<C: Signing> Secp256k1<C> {
218
225
/// signatures are needed for the same Message and SecretKey while still using RFC6979.
219
226
/// Requires a signing-capable context.
220
227
pub fn sign_ecdsa_recoverable_with_noncedata (
221
- & self ,
222
228
msg : impl Into < Message > ,
223
229
sk : & key:: SecretKey ,
224
230
noncedata : & [ u8 ; 32 ] ,
225
231
) -> RecoverableSignature {
226
232
let noncedata_ptr = noncedata. as_ptr ( ) as * const super_ffi:: types:: c_void ;
227
- self . sign_ecdsa_recoverable_with_noncedata_pointer ( msg, sk, noncedata_ptr)
233
+ Self :: sign_ecdsa_recoverable_with_noncedata_pointer ( msg, sk, noncedata_ptr)
228
234
}
229
- }
230
235
231
- impl < C : Verification > Secp256k1 < C > {
232
236
/// Determines the public key for which `sig` is a valid signature for
233
237
/// `msg`. Requires a verify-capable context.
234
- pub fn recover_ecdsa (
235
- & self ,
236
- msg : impl Into < Message > ,
237
- sig : & RecoverableSignature ,
238
- ) -> Result < key:: PublicKey , Error > {
238
+ pub fn recover_ecdsa ( & self , msg : impl Into < Message > ) -> Result < key:: PublicKey , Error > {
239
239
let msg = msg. into ( ) ;
240
- unsafe {
241
- let mut pk = super_ffi:: PublicKey :: new ( ) ;
242
- if ffi:: secp256k1_ecdsa_recover (
243
- self . ctx . as_ptr ( ) ,
244
- & mut pk,
245
- sig. as_c_ptr ( ) ,
246
- msg. as_c_ptr ( ) ,
247
- ) != 1
248
- {
249
- return Err ( Error :: InvalidSignature ) ;
250
- }
251
- Ok ( key:: PublicKey :: from ( pk) )
252
- }
240
+ crate :: with_raw_global_context (
241
+ |ctx| unsafe {
242
+ let mut pk = super_ffi:: PublicKey :: new ( ) ;
243
+ if ffi:: secp256k1_ecdsa_recover (
244
+ ctx. as_ptr ( ) ,
245
+ & mut pk,
246
+ self . as_c_ptr ( ) ,
247
+ msg. as_c_ptr ( ) ,
248
+ ) != 1
249
+ {
250
+ return Err ( Error :: InvalidSignature ) ;
251
+ }
252
+ Ok ( key:: PublicKey :: from ( pk) )
253
+ } ,
254
+ None ,
255
+ )
253
256
}
254
257
}
255
258
@@ -264,28 +267,13 @@ mod tests {
264
267
use crate :: { Error , Message , Secp256k1 , SecretKey } ;
265
268
266
269
#[ test]
267
- #[ cfg( feature = "std" ) ]
268
270
fn capabilities ( ) {
269
- let sign = Secp256k1 :: signing_only ( ) ;
270
- let vrfy = Secp256k1 :: verification_only ( ) ;
271
- let full = Secp256k1 :: new ( ) ;
272
-
273
271
let msg = crate :: test_random_32_bytes ( ) ;
274
272
let msg = Message :: from_digest_slice ( & msg) . unwrap ( ) ;
275
273
276
- // Try key generation
277
274
let ( sk, pk) = crate :: test_random_keypair ( ) ;
278
-
279
- // Try signing
280
- assert_eq ! ( sign. sign_ecdsa_recoverable( msg, & sk) , full. sign_ecdsa_recoverable( msg, & sk) ) ;
281
- let sigr = full. sign_ecdsa_recoverable ( msg, & sk) ;
282
-
283
- // Try pk recovery
284
- assert ! ( vrfy. recover_ecdsa( msg, & sigr) . is_ok( ) ) ;
285
- assert ! ( full. recover_ecdsa( msg, & sigr) . is_ok( ) ) ;
286
-
287
- assert_eq ! ( vrfy. recover_ecdsa( msg, & sigr) , full. recover_ecdsa( msg, & sigr) ) ;
288
- assert_eq ! ( full. recover_ecdsa( msg, & sigr) , Ok ( pk) ) ;
275
+ let sigr = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
276
+ assert_eq ! ( sigr. recover_ecdsa( msg) , Ok ( pk) ) ;
289
277
}
290
278
291
279
#[ test]
@@ -296,15 +284,12 @@ mod tests {
296
284
297
285
#[ test]
298
286
#[ cfg( not( secp256k1_fuzz) ) ] // fixed sig vectors can't work with fuzz-sigs
299
- #[ cfg( feature = "std" ) ]
300
287
#[ rustfmt:: skip]
301
288
fn sign ( ) {
302
- let s = Secp256k1 :: new ( ) ;
303
-
304
289
let sk = SecretKey :: from_slice ( & ONE ) . unwrap ( ) ;
305
290
let msg = Message :: from_digest_slice ( & ONE ) . unwrap ( ) ;
306
291
307
- let sig = s . sign_ecdsa_recoverable ( msg, & sk) ;
292
+ let sig = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
308
293
309
294
assert_eq ! ( Ok ( sig) , RecoverableSignature :: from_compact( & [
310
295
0x66 , 0x73 , 0xff , 0xad , 0x21 , 0x47 , 0x74 , 0x1f ,
@@ -320,16 +305,13 @@ mod tests {
320
305
321
306
#[ test]
322
307
#[ cfg( not( secp256k1_fuzz) ) ] // fixed sig vectors can't work with fuzz-sigs
323
- #[ cfg( feature = "std" ) ]
324
308
#[ rustfmt:: skip]
325
309
fn sign_with_noncedata ( ) {
326
- let s = Secp256k1 :: new ( ) ;
327
-
328
310
let sk = SecretKey :: from_slice ( & ONE ) . unwrap ( ) ;
329
311
let msg = Message :: from_digest_slice ( & ONE ) . unwrap ( ) ;
330
312
let noncedata = [ 42u8 ; 32 ] ;
331
313
332
- let sig = s . sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
314
+ let sig = RecoverableSignature :: sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
333
315
334
316
assert_eq ! ( Ok ( sig) , RecoverableSignature :: from_compact( & [
335
317
0xb5 , 0x0b , 0xb6 , 0x79 , 0x5f , 0x31 , 0x74 , 0x8a ,
@@ -351,57 +333,48 @@ mod tests {
351
333
let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
352
334
let ( sk, pk) = crate :: test_random_keypair ( ) ;
353
335
354
- let sigr = s . sign_ecdsa_recoverable ( msg, & sk) ;
336
+ let sigr = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
355
337
let sig = sigr. to_standard ( ) ;
356
338
357
339
let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
358
340
assert_eq ! ( s. verify_ecdsa( & sig, msg, & pk) , Err ( Error :: IncorrectSignature ) ) ;
359
341
360
- let recovered_key = s . recover_ecdsa ( msg, & sigr ) . unwrap ( ) ;
342
+ let recovered_key = sigr . recover_ecdsa ( msg) . unwrap ( ) ;
361
343
assert ! ( recovered_key != pk) ;
362
344
}
363
345
364
346
#[ test]
365
- #[ cfg( feature = "std" ) ]
366
347
fn sign_with_recovery ( ) {
367
- let s = Secp256k1 :: new ( ) ;
368
-
369
348
let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
370
349
let ( sk, pk) = crate :: test_random_keypair ( ) ;
371
350
372
- let sig = s . sign_ecdsa_recoverable ( msg, & sk) ;
351
+ let sig = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
373
352
374
- assert_eq ! ( s . recover_ecdsa( msg, & sig ) , Ok ( pk) ) ;
353
+ assert_eq ! ( sig . recover_ecdsa( msg) , Ok ( pk) ) ;
375
354
}
376
355
377
356
#[ test]
378
- #[ cfg( feature = "std" ) ]
379
357
fn sign_with_recovery_and_noncedata ( ) {
380
- let s = Secp256k1 :: new ( ) ;
381
-
382
358
let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
383
359
let noncedata = crate :: test_random_32_bytes ( ) ;
384
360
385
361
let ( sk, pk) = crate :: test_random_keypair ( ) ;
386
362
387
- let sig = s . sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
363
+ let sig = RecoverableSignature :: sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
388
364
389
- assert_eq ! ( s . recover_ecdsa( msg, & sig ) , Ok ( pk) ) ;
365
+ assert_eq ! ( sig . recover_ecdsa( msg) , Ok ( pk) ) ;
390
366
}
391
367
392
368
#[ test]
393
- #[ cfg( feature = "std" ) ]
394
369
fn bad_recovery ( ) {
395
- let s = Secp256k1 :: new ( ) ;
396
-
397
370
let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
398
371
399
372
// Zero is not a valid sig
400
373
let sig = RecoverableSignature :: from_compact ( & [ 0 ; 64 ] , RecoveryId :: Zero ) . unwrap ( ) ;
401
- assert_eq ! ( s . recover_ecdsa( msg, & sig ) , Err ( Error :: InvalidSignature ) ) ;
374
+ assert_eq ! ( sig . recover_ecdsa( msg) , Err ( Error :: InvalidSignature ) ) ;
402
375
// ...but 111..111 is
403
376
let sig = RecoverableSignature :: from_compact ( & [ 1 ; 64 ] , RecoveryId :: Zero ) . unwrap ( ) ;
404
- assert ! ( s . recover_ecdsa( msg, & sig ) . is_ok( ) ) ;
377
+ assert ! ( sig . recover_ecdsa( msg) . is_ok( ) ) ;
405
378
}
406
379
407
380
#[ test]
@@ -455,21 +428,20 @@ mod tests {
455
428
}
456
429
457
430
#[ cfg( bench) ]
458
- #[ cfg( feature = "std" ) ] // Currently only a single bench that requires "rand" + "std".
459
431
mod benches {
460
432
use test:: { black_box, Bencher } ;
461
433
462
- use crate :: { Message , Secp256k1 , SecretKey } ;
434
+ use super :: RecoverableSignature ;
435
+ use crate :: { Message , SecretKey } ;
463
436
464
437
#[ bench]
465
438
pub fn bench_recover ( bh : & mut Bencher ) {
466
- let s = Secp256k1 :: new ( ) ;
467
439
let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
468
440
let sk = SecretKey :: test_random ( ) ;
469
- let sig = s . sign_ecdsa_recoverable ( msg, & sk) ;
441
+ let sig = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
470
442
471
443
bh. iter ( || {
472
- let res = s . recover_ecdsa ( msg, & sig ) . unwrap ( ) ;
444
+ let res = sig . recover_ecdsa ( msg) . unwrap ( ) ;
473
445
black_box ( res) ;
474
446
} ) ;
475
447
}
0 commit comments