Skip to content

Commit 9d7a33f

Browse files
committed
Put back in deprecated context methods
During the removal of the context from the public API I brashly deleted a bunch of impls on the `Secp256k1` type when we could have just deprecated them. This means that when upgrading downstream crates the upgrade is way more painful than it is if we deprecate. Add back in the context impls. To do this I copied from `v0.31.1`. I'm not totally sure that there wasn't changes to this code in `master` but since we are explicitly doing this to help upgrade then it seems reasonable to do it like this. Add deprecated since 0.32 attributes because we are going to push this as a `0.32.0-beta.1` release. Sorry for the pain in reviewing this, I'm not entirely sure how you are supposed to convince yourself that the code is exactly as it was?
1 parent 4cfcc4b commit 9d7a33f

File tree

4 files changed

+366
-3
lines changed

4 files changed

+366
-3
lines changed

src/ecdsa/mod.rs

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use core::{fmt, ptr, str};
1313
pub use self::recovery::{RecoverableSignature, RecoveryId};
1414
pub use self::serialized_signature::SerializedSignature;
1515
use crate::ffi::CPtr;
16-
use crate::{ecdsa, ffi, from_hex, Error, Message, PublicKey, Secp256k1, SecretKey};
16+
use crate::{ecdsa, ffi, from_hex, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
1717

1818
/// An ECDSA signature
1919
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
@@ -341,6 +341,177 @@ pub fn sign_low_r(msg: impl Into<Message>, sk: &SecretKey) -> Signature {
341341
sign_grind_with_check(msg, sk, compact_sig_has_zero_first_bit)
342342
}
343343

344+
impl<C: Signing> Secp256k1<C> {
345+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa_with_noncedata_pointer instead")]
346+
fn sign_ecdsa_with_noncedata_pointer(
347+
&self,
348+
msg: impl Into<Message>,
349+
sk: &SecretKey,
350+
noncedata: Option<&[u8; 32]>,
351+
) -> Signature {
352+
let msg = msg.into();
353+
unsafe {
354+
let mut ret = ffi::Signature::new();
355+
let noncedata_ptr = match noncedata {
356+
Some(arr) => arr.as_c_ptr() as *const _,
357+
None => ptr::null(),
358+
};
359+
// We can assume the return value because it's not possible to construct
360+
// an invalid signature from a valid `Message` and `SecretKey`
361+
assert_eq!(
362+
ffi::secp256k1_ecdsa_sign(
363+
self.ctx.as_ptr(),
364+
&mut ret,
365+
msg.as_c_ptr(),
366+
sk.as_c_ptr(),
367+
ffi::secp256k1_nonce_function_rfc6979,
368+
noncedata_ptr
369+
),
370+
1
371+
);
372+
Signature::from(ret)
373+
}
374+
}
375+
376+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
377+
/// Requires a signing-capable context.
378+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa instead")]
379+
pub fn sign_ecdsa(&self, msg: impl Into<Message>, sk: &SecretKey) -> Signature {
380+
self.sign_ecdsa_with_noncedata_pointer(msg, sk, None)
381+
}
382+
383+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
384+
/// and includes 32 bytes of noncedata in the nonce generation via inclusion in
385+
/// one of the hash operations during nonce generation. This is useful when multiple
386+
/// signatures are needed for the same Message and SecretKey while still using RFC6979.
387+
/// Requires a signing-capable context.
388+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa_with_noncedata instead")]
389+
pub fn sign_ecdsa_with_noncedata(
390+
&self,
391+
msg: impl Into<Message>,
392+
sk: &SecretKey,
393+
noncedata: &[u8; 32],
394+
) -> Signature {
395+
self.sign_ecdsa_with_noncedata_pointer(msg, sk, Some(noncedata))
396+
}
397+
398+
fn sign_grind_with_check(
399+
&self,
400+
msg: impl Into<Message>,
401+
sk: &SecretKey,
402+
check: impl Fn(&ffi::Signature) -> bool,
403+
) -> Signature {
404+
let mut entropy_p: *const ffi::types::c_void = ptr::null();
405+
let mut counter: u32 = 0;
406+
let mut extra_entropy = [0u8; 32];
407+
let msg = msg.into();
408+
loop {
409+
unsafe {
410+
let mut ret = ffi::Signature::new();
411+
// We can assume the return value because it's not possible to construct
412+
// an invalid signature from a valid `Message` and `SecretKey`
413+
assert_eq!(
414+
ffi::secp256k1_ecdsa_sign(
415+
self.ctx.as_ptr(),
416+
&mut ret,
417+
msg.as_c_ptr(),
418+
sk.as_c_ptr(),
419+
ffi::secp256k1_nonce_function_rfc6979,
420+
entropy_p
421+
),
422+
1
423+
);
424+
if check(&ret) {
425+
return Signature::from(ret);
426+
}
427+
428+
counter += 1;
429+
extra_entropy[..4].copy_from_slice(&counter.to_le_bytes());
430+
entropy_p = extra_entropy.as_c_ptr().cast::<ffi::types::c_void>();
431+
432+
// When fuzzing, these checks will usually spinloop forever, so just short-circuit them.
433+
#[cfg(secp256k1_fuzz)]
434+
return Signature::from(ret);
435+
}
436+
}
437+
}
438+
439+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
440+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
441+
/// a signature that is less than 71 - `bytes_to_grind` bytes. The number
442+
/// of signing operation performed by this function is exponential in the
443+
/// number of bytes grinded.
444+
/// Requires a signing capable context.
445+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa_grind_r instead")]
446+
pub fn sign_ecdsa_grind_r(
447+
&self,
448+
msg: impl Into<Message>,
449+
sk: &SecretKey,
450+
bytes_to_grind: usize,
451+
) -> Signature {
452+
let len_check = |s: &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
453+
self.sign_grind_with_check(msg, sk, len_check)
454+
}
455+
456+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
457+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
458+
/// a signature that is less than 71 bytes and compatible with the low r
459+
/// signature implementation of bitcoin core. In average, this function
460+
/// will perform two signing operations.
461+
/// Requires a signing capable context.
462+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa_low_r instead")]
463+
pub fn sign_ecdsa_low_r(&self, msg: impl Into<Message>, sk: &SecretKey) -> Signature {
464+
self.sign_grind_with_check(msg, sk, compact_sig_has_zero_first_bit)
465+
}
466+
}
467+
468+
impl<C: Verification> Secp256k1<C> {
469+
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
470+
/// key `pubkey`. Returns `Ok(())` on success. Note that this function cannot
471+
/// be used for Bitcoin consensus checking since there may exist signatures
472+
/// which OpenSSL would verify but not libsecp256k1, or vice-versa. Requires a
473+
/// verify-capable context.
474+
///
475+
/// ```rust
476+
/// # #[cfg(all(feature = "rand", feature = "std"))] {
477+
/// # use secp256k1::{rand, Secp256k1, Message, Error};
478+
/// #
479+
/// # let secp = Secp256k1::new();
480+
/// # let (secret_key, public_key) = secp.generate_keypair(&mut rand::rng());
481+
/// #
482+
/// let message = Message::from_digest_slice(&[0xab; 32]).expect("32 bytes");
483+
/// let sig = secp.sign_ecdsa(message, &secret_key);
484+
/// assert_eq!(secp.verify_ecdsa(&sig, message, &public_key), Ok(()));
485+
///
486+
/// let message = Message::from_digest_slice(&[0xcd; 32]).expect("32 bytes");
487+
/// assert_eq!(secp.verify_ecdsa(&sig, message, &public_key), Err(Error::IncorrectSignature));
488+
/// # }
489+
/// ```
490+
#[inline]
491+
#[deprecated(since = "0.32", note = "use ecdsa::verify instead")]
492+
pub fn verify_ecdsa(
493+
&self,
494+
sig: &Signature,
495+
msg: impl Into<Message>,
496+
pk: &PublicKey,
497+
) -> Result<(), Error> {
498+
let msg = msg.into();
499+
unsafe {
500+
if ffi::secp256k1_ecdsa_verify(
501+
self.ctx.as_ptr(),
502+
sig.as_c_ptr(),
503+
msg.as_c_ptr(),
504+
pk.as_c_ptr(),
505+
) == 0
506+
{
507+
Err(Error::IncorrectSignature)
508+
} else {
509+
Ok(())
510+
}
511+
}
512+
}
513+
}
514+
344515
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
345516
/// key `pubkey`. Returns `Ok(())` on success. Note that this function cannot
346517
/// be used for Bitcoin consensus checking since there may exist signatures

src/ecdsa/recovery.rs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use self::super_ffi::CPtr;
1010
use super::ffi as super_ffi;
1111
use crate::ecdsa::Signature;
1212
use crate::ffi::recovery as ffi;
13-
use crate::{key, Error, Message};
13+
use crate::{key, Error, Message, Secp256k1, Signing, Verification};
1414

1515
/// A tag used for recovering the public key from a compact signature.
1616
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -229,6 +229,88 @@ impl RecoverableSignature {
229229
}
230230
}
231231

232+
impl<C: Signing> Secp256k1<C> {
233+
fn sign_ecdsa_recoverable_with_noncedata_pointer(
234+
&self,
235+
msg: impl Into<Message>,
236+
sk: &key::SecretKey,
237+
noncedata_ptr: *const super_ffi::types::c_void,
238+
) -> RecoverableSignature {
239+
let msg = msg.into();
240+
let mut ret = ffi::RecoverableSignature::new();
241+
unsafe {
242+
// We can assume the return value because it's not possible to construct
243+
// an invalid signature from a valid `Message` and `SecretKey`
244+
assert_eq!(
245+
ffi::secp256k1_ecdsa_sign_recoverable(
246+
self.ctx.as_ptr(),
247+
&mut ret,
248+
msg.as_c_ptr(),
249+
sk.as_c_ptr(),
250+
super_ffi::secp256k1_nonce_function_rfc6979,
251+
noncedata_ptr
252+
),
253+
1
254+
);
255+
}
256+
257+
RecoverableSignature::from(ret)
258+
}
259+
260+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
261+
/// Requires a signing-capable context.
262+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa_recoverable instead")]
263+
pub fn sign_ecdsa_recoverable(
264+
&self,
265+
msg: impl Into<Message>,
266+
sk: &key::SecretKey,
267+
) -> RecoverableSignature {
268+
self.sign_ecdsa_recoverable_with_noncedata_pointer(msg, sk, ptr::null())
269+
}
270+
271+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
272+
/// and includes 32 bytes of noncedata in the nonce generation via inclusion in
273+
/// one of the hash operations during nonce generation. This is useful when multiple
274+
/// signatures are needed for the same Message and SecretKey while still using RFC6979.
275+
/// Requires a signing-capable context.
276+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa_recoverable_with_noncedata instead")]
277+
pub fn sign_ecdsa_recoverable_with_noncedata(
278+
&self,
279+
msg: impl Into<Message>,
280+
sk: &key::SecretKey,
281+
noncedata: &[u8; 32],
282+
) -> RecoverableSignature {
283+
let noncedata_ptr = noncedata.as_ptr() as *const super_ffi::types::c_void;
284+
self.sign_ecdsa_recoverable_with_noncedata_pointer(msg, sk, noncedata_ptr)
285+
}
286+
}
287+
288+
impl<C: Verification> Secp256k1<C> {
289+
/// Determines the public key for which `sig` is a valid signature for
290+
/// `msg`. Requires a verify-capable context.
291+
#[deprecated(since = "0.32", note = "use ecdsa::sign_ecdsa instead")]
292+
pub fn recover_ecdsa(
293+
&self,
294+
msg: impl Into<Message>,
295+
sig: &RecoverableSignature,
296+
) -> Result<key::PublicKey, Error> {
297+
let msg = msg.into();
298+
unsafe {
299+
let mut pk = super_ffi::PublicKey::new();
300+
if ffi::secp256k1_ecdsa_recover(
301+
self.ctx.as_ptr(),
302+
&mut pk,
303+
sig.as_c_ptr(),
304+
msg.as_c_ptr(),
305+
) != 1
306+
{
307+
return Err(Error::InvalidSignature);
308+
}
309+
Ok(key::PublicKey::from(pk))
310+
}
311+
}
312+
}
313+
232314
#[cfg(test)]
233315
#[allow(unused_imports)]
234316
mod tests {

src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,22 @@ impl<C: Context> Secp256k1<C> {
410410
}
411411
}
412412

413+
impl<C: Signing> Secp256k1<C> {
414+
/// Generates a random keypair. Convenience function for [`SecretKey::new`] and
415+
/// [`PublicKey::from_secret_key`].
416+
#[inline]
417+
#[cfg(feature = "rand")]
418+
#[deprecated(since = "0.32", note = "use secp256k1::generate_keypair instead")]
419+
pub fn generate_keypair<R: rand::Rng + ?Sized>(
420+
&self,
421+
rng: &mut R,
422+
) -> (key::SecretKey, key::PublicKey) {
423+
let sk = key::SecretKey::new(rng);
424+
let pk = key::PublicKey::from_secret_key(&sk);
425+
(sk, pk)
426+
}
427+
}
428+
413429
/// Generates a random keypair. Convenience function for [`SecretKey::new`] and
414430
/// [`PublicKey::from_secret_key`].
415431
#[inline]

0 commit comments

Comments
 (0)