Skip to content

Commit 58c7ba2

Browse files
committed
Remove context from signing APIs
1 parent 403f541 commit 58c7ba2

File tree

7 files changed

+187
-254
lines changed

7 files changed

+187
-254
lines changed

examples/sign_verify.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
1616
extern crate secp256k1;
1717

18-
use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing};
18+
use secp256k1::{ecdsa, Error, Message, PublicKey, SecretKey};
1919

2020
fn verify(sig: [u8; 64], msg_digest: [u8; 32], pubkey: [u8; 33]) -> Result<bool, Error> {
2121
let msg = Message::from_digest(msg_digest);
@@ -25,19 +25,13 @@ fn verify(sig: [u8; 64], msg_digest: [u8; 32], pubkey: [u8; 33]) -> Result<bool,
2525
Ok(ecdsa::verify(&sig, msg, &pubkey).is_ok())
2626
}
2727

28-
fn sign<C: Signing>(
29-
secp: &Secp256k1<C>,
30-
msg_digest: [u8; 32],
31-
seckey: [u8; 32],
32-
) -> Result<ecdsa::Signature, Error> {
28+
fn sign(msg_digest: [u8; 32], seckey: [u8; 32]) -> Result<ecdsa::Signature, Error> {
3329
let msg = Message::from_digest(msg_digest);
3430
let seckey = SecretKey::from_secret_bytes(seckey)?;
35-
Ok(secp.sign_ecdsa(msg, &seckey))
31+
Ok(ecdsa::sign(msg, &seckey))
3632
}
3733

3834
fn main() {
39-
let secp = Secp256k1::new();
40-
4135
let seckey = [
4236
59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253,
4337
102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
@@ -48,7 +42,7 @@ fn main() {
4842
];
4943
let msg_digest = *b"this must be secure hash output.";
5044

51-
let signature = sign(&secp, msg_digest, seckey).unwrap();
45+
let signature = sign(msg_digest, seckey).unwrap();
5246

5347
let serialize_sig = signature.serialize_compact();
5448

no_std_test/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
8282
let public_key = PublicKey::from_secret_key(&secret_key);
8383
let message = Message::from_digest_slice(&[0xab; 32]).expect("32 bytes");
8484

85-
let sig = secp.sign_ecdsa(message, &secret_key);
85+
let sig = ecdsa::sign(message, &secret_key);
8686
assert!(ecdsa::verify(&sig, message, &public_key).is_ok());
8787

8888
let rec_sig = ecdsa::RecoverableSignature::sign_ecdsa_recoverable(message, &secret_key);
@@ -109,7 +109,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
109109
let public_key = PublicKey::from_secret_key(&secret_key);
110110
let message = Message::from_digest_slice(&[0xab; 32]).expect("32 bytes");
111111

112-
let sig = secp_alloc.sign_ecdsa(message, &secret_key);
112+
let sig = ecdsa::sign(message, &secret_key);
113113
assert!(ecdsa::verify(&sig, message, &public_key).is_ok());
114114
unsafe { libc::printf("Verified alloc Successfully!\n\0".as_ptr() as _) };
115115
}

src/ecdsa/mod.rs

Lines changed: 99 additions & 101 deletions
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, Signing};
16+
use crate::{ecdsa, ffi, from_hex, Error, Message, PublicKey, Secp256k1, SecretKey};
1717

1818
/// An ECDSA signature
1919
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
@@ -236,123 +236,122 @@ impl<'de> serde::Deserialize<'de> for Signature {
236236
}
237237
}
238238

239-
impl<C: Signing> Secp256k1<C> {
240-
fn sign_ecdsa_with_noncedata_pointer(
241-
&self,
242-
msg: impl Into<Message>,
243-
sk: &SecretKey,
244-
noncedata: Option<&[u8; 32]>,
245-
) -> Signature {
246-
let msg = msg.into();
247-
unsafe {
248-
let mut ret = ffi::Signature::new();
249-
let noncedata_ptr = match noncedata {
250-
Some(arr) => arr.as_c_ptr() as *const _,
251-
None => ptr::null(),
252-
};
253-
// We can assume the return value because it's not possible to construct
254-
// an invalid signature from a valid `Message` and `SecretKey`
255-
assert_eq!(
239+
fn sign_ecdsa_with_noncedata_pointer(
240+
msg: impl Into<Message>,
241+
sk: &SecretKey,
242+
noncedata: Option<&[u8; 32]>,
243+
) -> Signature {
244+
let msg = msg.into();
245+
unsafe {
246+
let mut ret = ffi::Signature::new();
247+
let noncedata_ptr = match noncedata {
248+
Some(arr) => arr.as_c_ptr() as *const _,
249+
None => ptr::null(),
250+
};
251+
// We can assume the return value because it's not possible to construct
252+
// an invalid signature from a valid `Message` and `SecretKey`
253+
let res = crate::with_global_context(
254+
|secp: &Secp256k1<crate::AllPreallocated>| {
256255
ffi::secp256k1_ecdsa_sign(
257-
self.ctx.as_ptr(),
256+
secp.ctx.as_ptr(),
258257
&mut ret,
259258
msg.as_c_ptr(),
260259
sk.as_c_ptr(),
261260
ffi::secp256k1_nonce_function_rfc6979,
262-
noncedata_ptr
263-
),
264-
1
265-
);
266-
Signature::from(ret)
267-
}
268-
}
261+
noncedata_ptr,
262+
)
263+
},
264+
Some(&sk.to_secret_bytes()),
265+
);
269266

270-
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
271-
/// Requires a signing-capable context.
272-
pub fn sign_ecdsa(&self, msg: impl Into<Message>, sk: &SecretKey) -> Signature {
273-
self.sign_ecdsa_with_noncedata_pointer(msg, sk, None)
274-
}
267+
assert_eq!(res, 1);
275268

276-
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
277-
/// and includes 32 bytes of noncedata in the nonce generation via inclusion in
278-
/// one of the hash operations during nonce generation. This is useful when multiple
279-
/// signatures are needed for the same Message and SecretKey while still using RFC6979.
280-
/// Requires a signing-capable context.
281-
pub fn sign_ecdsa_with_noncedata(
282-
&self,
283-
msg: impl Into<Message>,
284-
sk: &SecretKey,
285-
noncedata: &[u8; 32],
286-
) -> Signature {
287-
self.sign_ecdsa_with_noncedata_pointer(msg, sk, Some(noncedata))
269+
Signature::from(ret)
288270
}
271+
}
289272

290-
fn sign_grind_with_check(
291-
&self,
292-
msg: impl Into<Message>,
293-
sk: &SecretKey,
294-
check: impl Fn(&ffi::Signature) -> bool,
295-
) -> Signature {
296-
let mut entropy_p: *const ffi::types::c_void = ptr::null();
297-
let mut counter: u32 = 0;
298-
let mut extra_entropy = [0u8; 32];
299-
let msg = msg.into();
300-
loop {
301-
unsafe {
302-
let mut ret = ffi::Signature::new();
303-
// We can assume the return value because it's not possible to construct
304-
// an invalid signature from a valid `Message` and `SecretKey`
305-
assert_eq!(
273+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
274+
/// Requires a signing-capable context.
275+
pub fn sign(msg: impl Into<Message>, sk: &SecretKey) -> Signature {
276+
sign_ecdsa_with_noncedata_pointer(msg, sk, None)
277+
}
278+
279+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
280+
/// and includes 32 bytes of noncedata in the nonce generation via inclusion in
281+
/// one of the hash operations during nonce generation. This is useful when multiple
282+
/// signatures are needed for the same Message and SecretKey while still using RFC6979.
283+
/// Requires a signing-capable context.
284+
pub fn sign_with_noncedata(
285+
msg: impl Into<Message>,
286+
sk: &SecretKey,
287+
noncedata: &[u8; 32],
288+
) -> Signature {
289+
sign_ecdsa_with_noncedata_pointer(msg, sk, Some(noncedata))
290+
}
291+
292+
fn sign_grind_with_check(
293+
msg: impl Into<Message>,
294+
sk: &SecretKey,
295+
check: impl Fn(&ffi::Signature) -> bool,
296+
) -> Signature {
297+
let mut entropy_p: *const ffi::types::c_void = ptr::null();
298+
let mut counter: u32 = 0;
299+
let mut extra_entropy = [0u8; 32];
300+
let msg = msg.into();
301+
loop {
302+
unsafe {
303+
let mut ret = ffi::Signature::new();
304+
// We can assume the return value because it's not possible to construct
305+
// an invalid signature from a valid `Message` and `SecretKey`
306+
let res = crate::with_global_context(
307+
|secp: &Secp256k1<crate::AllPreallocated>| {
306308
ffi::secp256k1_ecdsa_sign(
307-
self.ctx.as_ptr(),
309+
secp.ctx.as_ptr(),
308310
&mut ret,
309311
msg.as_c_ptr(),
310312
sk.as_c_ptr(),
311313
ffi::secp256k1_nonce_function_rfc6979,
312-
entropy_p
313-
),
314-
1
315-
);
316-
if check(&ret) {
317-
return Signature::from(ret);
318-
}
319-
320-
counter += 1;
321-
extra_entropy[..4].copy_from_slice(&counter.to_le_bytes());
322-
entropy_p = extra_entropy.as_c_ptr().cast::<ffi::types::c_void>();
323-
324-
// When fuzzing, these checks will usually spinloop forever, so just short-circuit them.
325-
#[cfg(secp256k1_fuzz)]
314+
entropy_p,
315+
)
316+
},
317+
Some(&sk.to_secret_bytes()),
318+
);
319+
assert_eq!(res, 1);
320+
321+
if check(&ret) {
326322
return Signature::from(ret);
327323
}
324+
325+
counter += 1;
326+
extra_entropy[..4].copy_from_slice(&counter.to_le_bytes());
327+
entropy_p = extra_entropy.as_c_ptr().cast::<ffi::types::c_void>();
328+
329+
// When fuzzing, these checks will usually spinloop forever, so just short-circuit them.
330+
#[cfg(secp256k1_fuzz)]
331+
return Signature::from(ret);
328332
}
329333
}
334+
}
330335

331-
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
332-
/// and "grinds" the nonce by passing extra entropy if necessary to produce
333-
/// a signature that is less than 71 - `bytes_to_grind` bytes. The number
334-
/// of signing operation performed by this function is exponential in the
335-
/// number of bytes grinded.
336-
/// Requires a signing capable context.
337-
pub fn sign_ecdsa_grind_r(
338-
&self,
339-
msg: impl Into<Message>,
340-
sk: &SecretKey,
341-
bytes_to_grind: usize,
342-
) -> Signature {
343-
let len_check = |s: &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
344-
self.sign_grind_with_check(msg, sk, len_check)
345-
}
336+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
337+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
338+
/// a signature that is less than 71 - `bytes_to_grind` bytes. The number
339+
/// of signing operation performed by this function is exponential in the
340+
/// number of bytes grinded.
341+
/// Requires a signing capable context.
342+
pub fn sign_grind_r(msg: impl Into<Message>, sk: &SecretKey, bytes_to_grind: usize) -> Signature {
343+
let len_check = |s: &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
344+
sign_grind_with_check(msg, sk, len_check)
345+
}
346346

347-
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
348-
/// and "grinds" the nonce by passing extra entropy if necessary to produce
349-
/// a signature that is less than 71 bytes and compatible with the low r
350-
/// signature implementation of bitcoin core. In average, this function
351-
/// will perform two signing operations.
352-
/// Requires a signing capable context.
353-
pub fn sign_ecdsa_low_r(&self, msg: impl Into<Message>, sk: &SecretKey) -> Signature {
354-
self.sign_grind_with_check(msg, sk, compact_sig_has_zero_first_bit)
355-
}
347+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
348+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
349+
/// a signature that is less than 71 bytes and compatible with the low r
350+
/// signature implementation of bitcoin core. In average, this function
351+
/// will perform two signing operations.
352+
/// Requires a signing capable context.
353+
pub fn sign_low_r(msg: impl Into<Message>, sk: &SecretKey) -> Signature {
354+
sign_grind_with_check(msg, sk, compact_sig_has_zero_first_bit)
356355
}
357356

358357
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
@@ -363,13 +362,12 @@ impl<C: Signing> Secp256k1<C> {
363362
///
364363
/// ```rust
365364
/// # #[cfg(all(feature = "rand", feature = "std"))] {
366-
/// # use secp256k1::{rand, ecdsa, Secp256k1, Message, Error};
365+
/// # use secp256k1::{rand, ecdsa, Message, Error};
367366
/// #
368-
/// # let secp = Secp256k1::new();
369367
/// # let (secret_key, public_key) = secp256k1::generate_keypair(&mut rand::rng());
370368
/// #
371369
/// let message = Message::from_digest_slice(&[0xab; 32]).expect("32 bytes");
372-
/// let sig = secp.sign_ecdsa(message, &secret_key);
370+
/// let sig = ecdsa::sign(message, &secret_key);
373371
/// assert_eq!(ecdsa::verify(&sig, message, &public_key), Ok(()));
374372
///
375373
/// let message = Message::from_digest_slice(&[0xcd; 32]).expect("32 bytes");

src/key/mod.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ use crate::ellswift::ElligatorSwift;
1919
use crate::ffi::types::c_uint;
2020
use crate::ffi::{self, CPtr};
2121
use crate::Error::{self, InvalidPublicKey, InvalidPublicKeySum};
22-
#[cfg(feature = "global-context")]
23-
use crate::SECP256K1;
2422
use crate::{constants, ecdsa, from_hex, schnorr, Message, Scalar, Secp256k1, Verification};
2523

2624
/// Public key - used to verify ECDSA signatures and to do Taproot tweaks.
@@ -712,19 +710,15 @@ impl Keypair {
712710
XOnlyPublicKey::from_keypair(self)
713711
}
714712

715-
/// Constructs a schnorr signature for `msg` using the global [`SECP256K1`] context.
713+
/// Constructs a schnorr signature for `msg`.
716714
#[inline]
717-
#[cfg(all(feature = "global-context", feature = "rand", feature = "std"))]
718-
pub fn sign_schnorr(&self, msg: &[u8]) -> schnorr::Signature {
719-
SECP256K1.sign_schnorr(msg, self)
720-
}
715+
#[cfg(all(feature = "rand", feature = "std"))]
716+
pub fn sign_schnorr(&self, msg: &[u8]) -> schnorr::Signature { schnorr::sign(msg, self) }
721717

722-
/// Constructs a schnorr signature without aux rand for `msg` using the global
723-
/// [`SECP256K1`] context.
718+
/// Constructs a schnorr signature without aux rand for `msg`.
724719
#[inline]
725-
#[cfg(all(feature = "global-context", feature = "std"))]
726720
pub fn sign_schnorr_no_aux_rand(&self, msg: &[u8]) -> schnorr::Signature {
727-
SECP256K1.sign_schnorr_no_aux_rand(msg, self)
721+
schnorr::sign_no_aux_rand(msg, self)
728722
}
729723

730724
/// Attempts to erase the secret within the underlying array.

src/key/secret.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ use core::{ops, str};
77
use serde::ser::SerializeTuple;
88

99
use crate::ffi::CPtr as _;
10-
use crate::{constants, ffi, from_hex, Error, Keypair, Parity, PublicKey, Scalar, XOnlyPublicKey};
11-
#[cfg(feature = "global-context")]
12-
use crate::{ecdsa, Message, SECP256K1};
10+
use crate::{
11+
constants, ecdsa, ffi, from_hex, Error, Keypair, Message, Parity, PublicKey, Scalar,
12+
XOnlyPublicKey,
13+
};
1314

1415
mod encapsulate {
1516
use crate::constants::SECRET_KEY_SIZE;
@@ -271,12 +272,9 @@ impl SecretKey {
271272
}
272273
}
273274

274-
/// Constructs an ECDSA signature for `msg` using the global [`SECP256K1`] context.
275+
/// Constructs an ECDSA signature for `msg`.
275276
#[inline]
276-
#[cfg(feature = "global-context")]
277-
pub fn sign_ecdsa(&self, msg: impl Into<Message>) -> ecdsa::Signature {
278-
SECP256K1.sign_ecdsa(msg, self)
279-
}
277+
pub fn sign_ecdsa(&self, msg: impl Into<Message>) -> ecdsa::Signature { ecdsa::sign(msg, self) }
280278

281279
/// Returns the [`Keypair`] for this [`SecretKey`].
282280
///

0 commit comments

Comments
 (0)