@@ -10,7 +10,7 @@ use self::super_ffi::CPtr;
1010use super :: ffi as super_ffi;
1111use crate :: ecdsa:: Signature ;
1212use crate :: ffi:: recovery as ffi;
13- use crate :: { key, Error , Message , Secp256k1 , Signing , Verification } ;
13+ use crate :: { key, Error , Message } ;
1414
1515/// A tag used for recovering the public key from a compact signature.
1616#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
@@ -157,7 +157,7 @@ impl RecoverableSignature {
157157 #[ inline]
158158 #[ cfg( feature = "global-context" ) ]
159159 pub fn recover ( & self , msg : impl Into < Message > ) -> Result < key:: PublicKey , Error > {
160- crate :: SECP256K1 . recover_ecdsa ( msg, self )
160+ self . recover_ecdsa ( msg)
161161 }
162162}
163163
@@ -174,42 +174,49 @@ impl From<ffi::RecoverableSignature> for RecoverableSignature {
174174 fn from ( sig : ffi:: RecoverableSignature ) -> RecoverableSignature { RecoverableSignature ( sig) }
175175}
176176
177- impl < C : Signing > Secp256k1 < C > {
177+ impl RecoverableSignature {
178178 fn sign_ecdsa_recoverable_with_noncedata_pointer (
179- & self ,
180179 msg : impl Into < Message > ,
181180 sk : & key:: SecretKey ,
182181 noncedata_ptr : * const super_ffi:: types:: c_void ,
183- ) -> RecoverableSignature {
182+ ) -> Self {
184183 let msg = msg. into ( ) ;
185184 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;
200190 }
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+ ) ;
201209
202210 RecoverableSignature :: from ( ret)
203211 }
204212
205213 /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
206214 /// Requires a signing-capable context.
207215 pub fn sign_ecdsa_recoverable (
208- & self ,
209216 msg : impl Into < Message > ,
210217 sk : & key:: SecretKey ,
211218 ) -> 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 ( ) )
213220 }
214221
215222 /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
@@ -218,38 +225,34 @@ impl<C: Signing> Secp256k1<C> {
218225 /// signatures are needed for the same Message and SecretKey while still using RFC6979.
219226 /// Requires a signing-capable context.
220227 pub fn sign_ecdsa_recoverable_with_noncedata (
221- & self ,
222228 msg : impl Into < Message > ,
223229 sk : & key:: SecretKey ,
224230 noncedata : & [ u8 ; 32 ] ,
225231 ) -> RecoverableSignature {
226232 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)
228234 }
229- }
230235
231- impl < C : Verification > Secp256k1 < C > {
232236 /// Determines the public key for which `sig` is a valid signature for
233237 /// `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 > {
239239 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+ )
253256 }
254257}
255258
@@ -264,28 +267,13 @@ mod tests {
264267 use crate :: { Error , Message , Secp256k1 , SecretKey } ;
265268
266269 #[ test]
267- #[ cfg( feature = "std" ) ]
268270 fn capabilities ( ) {
269- let sign = Secp256k1 :: signing_only ( ) ;
270- let vrfy = Secp256k1 :: verification_only ( ) ;
271- let full = Secp256k1 :: new ( ) ;
272-
273271 let msg = crate :: test_random_32_bytes ( ) ;
274272 let msg = Message :: from_digest ( msg) ;
275273
276- // Try key generation
277274 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) ) ;
289277 }
290278
291279 #[ test]
@@ -296,15 +284,11 @@ mod tests {
296284
297285 #[ test]
298286 #[ cfg( not( secp256k1_fuzz) ) ] // fixed sig vectors can't work with fuzz-sigs
299- #[ cfg( feature = "std" ) ]
300287 #[ rustfmt:: skip]
301288 fn sign ( ) {
302- let s = Secp256k1 :: new ( ) ;
303-
304289 let sk = SecretKey :: from_byte_array ( ONE ) . unwrap ( ) ;
305290 let msg = Message :: from_digest ( ONE ) ;
306-
307- let sig = s. sign_ecdsa_recoverable ( msg, & sk) ;
291+ let sig = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
308292
309293 assert_eq ! ( Ok ( sig) , RecoverableSignature :: from_compact( & [
310294 0x66 , 0x73 , 0xff , 0xad , 0x21 , 0x47 , 0x74 , 0x1f ,
@@ -320,16 +304,13 @@ mod tests {
320304
321305 #[ test]
322306 #[ cfg( not( secp256k1_fuzz) ) ] // fixed sig vectors can't work with fuzz-sigs
323- #[ cfg( feature = "std" ) ]
324307 #[ rustfmt:: skip]
325308 fn sign_with_noncedata ( ) {
326- let s = Secp256k1 :: new ( ) ;
327-
328309 let sk = SecretKey :: from_byte_array ( ONE ) . unwrap ( ) ;
329- let msg = Message :: from_digest ( ONE ) ;
330310 let noncedata = [ 42u8 ; 32 ] ;
311+ let msg = Message :: from_digest ( ONE ) ;
331312
332- let sig = s . sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
313+ let sig = RecoverableSignature :: sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
333314
334315 assert_eq ! ( Ok ( sig) , RecoverableSignature :: from_compact( & [
335316 0xb5 , 0x0b , 0xb6 , 0x79 , 0x5f , 0x31 , 0x74 , 0x8a ,
@@ -351,57 +332,48 @@ mod tests {
351332 let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
352333 let ( sk, pk) = crate :: test_random_keypair ( ) ;
353334
354- let sigr = s . sign_ecdsa_recoverable ( msg, & sk) ;
335+ let sigr = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
355336 let sig = sigr. to_standard ( ) ;
356337
357338 let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
358339 assert_eq ! ( s. verify_ecdsa( & sig, msg, & pk) , Err ( Error :: IncorrectSignature ) ) ;
359340
360- let recovered_key = s . recover_ecdsa ( msg, & sigr ) . unwrap ( ) ;
341+ let recovered_key = sigr . recover_ecdsa ( msg) . unwrap ( ) ;
361342 assert ! ( recovered_key != pk) ;
362343 }
363344
364345 #[ test]
365- #[ cfg( feature = "std" ) ]
366346 fn sign_with_recovery ( ) {
367- let s = Secp256k1 :: new ( ) ;
368-
369347 let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
370348 let ( sk, pk) = crate :: test_random_keypair ( ) ;
371349
372- let sig = s . sign_ecdsa_recoverable ( msg, & sk) ;
350+ let sig = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
373351
374- assert_eq ! ( s . recover_ecdsa( msg, & sig ) , Ok ( pk) ) ;
352+ assert_eq ! ( sig . recover_ecdsa( msg) , Ok ( pk) ) ;
375353 }
376354
377355 #[ test]
378- #[ cfg( feature = "std" ) ]
379356 fn sign_with_recovery_and_noncedata ( ) {
380- let s = Secp256k1 :: new ( ) ;
381-
382357 let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
383358 let noncedata = crate :: test_random_32_bytes ( ) ;
384359
385360 let ( sk, pk) = crate :: test_random_keypair ( ) ;
386361
387- let sig = s . sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
362+ let sig = RecoverableSignature :: sign_ecdsa_recoverable_with_noncedata ( msg, & sk, & noncedata) ;
388363
389- assert_eq ! ( s . recover_ecdsa( msg, & sig ) , Ok ( pk) ) ;
364+ assert_eq ! ( sig . recover_ecdsa( msg) , Ok ( pk) ) ;
390365 }
391366
392367 #[ test]
393- #[ cfg( feature = "std" ) ]
394368 fn bad_recovery ( ) {
395- let s = Secp256k1 :: new ( ) ;
396-
397369 let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
398370
399371 // Zero is not a valid sig
400372 let sig = RecoverableSignature :: from_compact ( & [ 0 ; 64 ] , RecoveryId :: Zero ) . unwrap ( ) ;
401- assert_eq ! ( s . recover_ecdsa( msg, & sig ) , Err ( Error :: InvalidSignature ) ) ;
373+ assert_eq ! ( sig . recover_ecdsa( msg) , Err ( Error :: InvalidSignature ) ) ;
402374 // ...but 111..111 is
403375 let sig = RecoverableSignature :: from_compact ( & [ 1 ; 64 ] , RecoveryId :: Zero ) . unwrap ( ) ;
404- assert ! ( s . recover_ecdsa( msg, & sig ) . is_ok( ) ) ;
376+ assert ! ( sig . recover_ecdsa( msg) . is_ok( ) ) ;
405377 }
406378
407379 #[ test]
@@ -455,21 +427,20 @@ mod tests {
455427}
456428
457429#[ cfg( bench) ]
458- #[ cfg( feature = "std" ) ] // Currently only a single bench that requires "rand" + "std".
459430mod benches {
460431 use test:: { black_box, Bencher } ;
461432
462- use crate :: { Message , Secp256k1 , SecretKey } ;
433+ use super :: RecoverableSignature ;
434+ use crate :: { Message , SecretKey } ;
463435
464436 #[ bench]
465437 pub fn bench_recover ( bh : & mut Bencher ) {
466- let s = Secp256k1 :: new ( ) ;
467438 let msg = Message :: from_digest ( crate :: test_random_32_bytes ( ) ) ;
468439 let sk = SecretKey :: test_random ( ) ;
469- let sig = s . sign_ecdsa_recoverable ( msg, & sk) ;
440+ let sig = RecoverableSignature :: sign_ecdsa_recoverable ( msg, & sk) ;
470441
471442 bh. iter ( || {
472- let res = s . recover_ecdsa ( msg, & sig ) . unwrap ( ) ;
443+ let res = sig . recover_ecdsa ( msg) . unwrap ( ) ;
473444 black_box ( res) ;
474445 } ) ;
475446 }
0 commit comments