secp256k1/
lib.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Rust bindings for Pieter Wuille's secp256k1 library, which is used for
4//! fast and accurate manipulation of ECDSA and Schnorr signatures on the secp256k1
5//! curve. Such signatures are used extensively by the Bitcoin network
6//! and its derivatives.
7//!
8//! To minimize dependencies, some functions are feature-gated. To generate
9//! random keys or to re-randomize a context object, compile with the
10//! `rand` and `std` features. If you are willing to use these features, we
11//! have enabled an additional defense-in-depth sidechannel protection for
12//! our context objects, which re-blinds certain operations on secret key
13//! data. To de/serialize objects with serde, compile with "serde".
14//! **Important**: `serde` encoding is **not** the same as consensus
15//! encoding!
16//!
17//! Where possible, the bindings use the Rust type system to ensure that
18//! API usage errors are impossible. For example, the library uses context
19//! objects that contain precomputation tables which are created on object
20//! construction. Since this is a slow operation (10+ milliseconds, vs ~50
21//! microseconds for typical crypto operations, on a 2.70 Ghz i7-6820HQ)
22//! the tables are optional, giving a performance boost for users who only
23//! care about signing, only care about verification, or only care about
24//! parsing. In the upstream library, if you attempt to sign a message using
25//! a context that does not support this, it will trigger an assertion
26//! failure and terminate the program. In `rust-secp256k1`, this is caught
27//! at compile-time; in fact, it is impossible to compile code that will
28//! trigger any assertion failures in the upstream library.
29//!
30//! ```rust
31//! # #[cfg(all(feature = "rand", feature = "std"))] {
32//! use secp256k1::rand;
33//! use secp256k1::{ecdsa, Message};
34//!
35//! // Our message to sign. We explicitly obtain a hash and convert it to a
36//! // `Message`. In a real application, we would produce a signature hash
37//! // type, e.g. `bitcoin::LegacySigHash`, which is convertible to `Message`
38//! // and can be passed directly to `sign_ecdsa`.
39//! const HELLO_WORLD_SHA2: [u8; 32] = [
40//!     0x31, 0x5f, 0x5b, 0xdb, 0x76, 0xd0, 0x78, 0xc4, 0x3b, 0x8a, 0xc0, 0x06, 0x4e, 0x4a, 0x01, 0x64,
41//!     0x61, 0x2b, 0x1f, 0xce, 0x77, 0xc8, 0x69, 0x34, 0x5b, 0xfc, 0x94, 0xc7, 0x58, 0x94, 0xed, 0xd3,
42//! ];
43//!
44//! let (secret_key, public_key) = secp256k1::generate_keypair(&mut rand::rng());
45//! let message = Message::from_digest(HELLO_WORLD_SHA2);
46//!
47//! let sig = ecdsa::sign(message, &secret_key);
48//! assert!(ecdsa::verify(&sig, message, &public_key).is_ok());
49//! # }
50//! ```
51//!
52//! If the "global-context" feature is enabled you have access to an alternate API.
53//!
54//! ```rust
55//! # #[cfg(all(feature = "global-context", feature = "rand", feature = "std"))] {
56//! use secp256k1::{rand, Message};
57//!
58//! // See previous example regarding this constant.
59//! const HELLO_WORLD_SHA2: [u8; 32] = [
60//!     0x31, 0x5f, 0x5b, 0xdb, 0x76, 0xd0, 0x78, 0xc4, 0x3b, 0x8a, 0xc0, 0x06, 0x4e, 0x4a, 0x01, 0x64,
61//!     0x61, 0x2b, 0x1f, 0xce, 0x77, 0xc8, 0x69, 0x34, 0x5b, 0xfc, 0x94, 0xc7, 0x58, 0x94, 0xed, 0xd3,
62//! ];
63//!
64//! let (secret_key, public_key) = secp256k1::generate_keypair(&mut rand::rng());
65//! let message = Message::from_digest(HELLO_WORLD_SHA2);
66//!
67//! let sig = secret_key.sign_ecdsa(message);
68//! assert!(sig.verify(message, &public_key).is_ok());
69//! # }
70//! ```
71//!
72//! The above code requires `rust-secp256k1` to be compiled with the `rand`, `hashes`, and `std`
73//! feature enabled, to get access to [`generate_keypair`](struct.Secp256k1.html#method.generate_keypair)
74//! Alternately, keys and messages can be parsed from slices, like
75//!
76//! ```rust
77//! # #[cfg(feature = "alloc")] {
78//! use secp256k1::{ecdsa, Message, SecretKey, PublicKey};
79//! # fn compute_hash(_: &[u8]) -> [u8; 32] { [0xab; 32] }
80//!
81//! let secret_key = SecretKey::from_secret_bytes([0xcd; 32]).expect("32 bytes, within curve order");
82//! let public_key = PublicKey::from_secret_key(&secret_key);
83//! // If the supplied byte slice was *not* the output of a cryptographic hash function this would
84//! // be cryptographically broken. It has been trivially used in the past to execute attacks.
85//! let message = Message::from_digest(compute_hash(b"CSW is not Satoshi"));
86//!
87//! let sig = ecdsa::sign(message, &secret_key);
88//! assert!(ecdsa::verify(&sig, message, &public_key).is_ok());
89//! # }
90//! ```
91//!
92//! Users who only want to verify signatures can use a cheaper context, like so:
93//!
94//! ```rust
95//! # #[cfg(feature = "alloc")] {
96//! use secp256k1::{ecdsa, Message, PublicKey};
97//!
98//! let public_key = PublicKey::from_slice(&[
99//!     0x02,
100//!     0xc6, 0x6e, 0x7d, 0x89, 0x66, 0xb5, 0xc5, 0x55,
101//!     0xaf, 0x58, 0x05, 0x98, 0x9d, 0xa9, 0xfb, 0xf8,
102//!     0xdb, 0x95, 0xe1, 0x56, 0x31, 0xce, 0x35, 0x8c,
103//!     0x3a, 0x17, 0x10, 0xc9, 0x62, 0x67, 0x90, 0x63,
104//! ]).expect("public keys must be 33 or 65 bytes, serialized according to SEC 2");
105//!
106//! let message = Message::from_digest([
107//!     0xaa, 0xdf, 0x7d, 0xe7, 0x82, 0x03, 0x4f, 0xbe,
108//!     0x3d, 0x3d, 0xb2, 0xcb, 0x13, 0xc0, 0xcd, 0x91,
109//!     0xbf, 0x41, 0xcb, 0x08, 0xfa, 0xc7, 0xbd, 0x61,
110//!     0xd5, 0x44, 0x53, 0xcf, 0x6e, 0x82, 0xb4, 0x50,
111//! ]);
112//!
113//! let sig = ecdsa::Signature::from_compact(&[
114//!     0xdc, 0x4d, 0xc2, 0x64, 0xa9, 0xfe, 0xf1, 0x7a,
115//!     0x3f, 0x25, 0x34, 0x49, 0xcf, 0x8c, 0x39, 0x7a,
116//!     0xb6, 0xf1, 0x6f, 0xb3, 0xd6, 0x3d, 0x86, 0x94,
117//!     0x0b, 0x55, 0x86, 0x82, 0x3d, 0xfd, 0x02, 0xae,
118//!     0x3b, 0x46, 0x1b, 0xb4, 0x33, 0x6b, 0x5e, 0xcb,
119//!     0xae, 0xfd, 0x66, 0x27, 0xaa, 0x92, 0x2e, 0xfc,
120//!     0x04, 0x8f, 0xec, 0x0c, 0x88, 0x1c, 0x10, 0xc4,
121//!     0xc9, 0x42, 0x8f, 0xca, 0x69, 0xc1, 0x32, 0xa2,
122//! ]).expect("compact signatures are 64 bytes; DER signatures are 68-72 bytes");
123//!
124//! # #[cfg(not(secp256k1_fuzz))]
125//! assert!(ecdsa::verify(&sig, message, &public_key).is_ok());
126//! # }
127//! ```
128//!
129//! Observe that the same code using, say [`signing_only`](struct.Secp256k1.html#method.signing_only)
130//! to generate a context would simply not compile.
131//!
132//! ## Crate features/optional dependencies
133//!
134//! This crate provides the following opt-in Cargo features:
135//!
136//! * `std` - use standard Rust library, enabled by default.
137//! * `alloc` - use the `alloc` standard Rust library to provide heap allocations.
138//! * `rand` - use `rand` library to provide random generator (e.g. to generate keys).
139//! * `hashes` - use the `hashes` library.
140//! * `recovery` - enable functions that can compute the public key from signature.
141//! * `lowmemory` - optimize the library for low-memory environments.
142//! * `global-context` - enable use of global secp256k1 context (implies `std`).
143//! * `serde` - implements serialization and deserialization for types in this crate using `serde`.
144//!   **Important**: `serde` encoding is **not** the same as consensus encoding!
145//!
146
147// Coding conventions
148#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)]
149#![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)]
150#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
151// Experimental features we need.
152#![cfg_attr(bench, feature(test))]
153
154#[cfg(feature = "alloc")]
155extern crate alloc;
156#[cfg(any(test, feature = "std"))]
157extern crate core;
158#[cfg(bench)]
159extern crate test;
160
161#[cfg(feature = "rand")]
162pub extern crate rand;
163#[cfg(feature = "serde")]
164pub extern crate serde;
165
166#[macro_use]
167mod macros;
168#[macro_use]
169mod secret;
170mod context;
171mod key;
172#[cfg(feature = "serde")]
173mod serde_util;
174
175pub mod constants;
176pub mod ecdh;
177pub mod ecdsa;
178pub mod ellswift;
179pub mod musig;
180pub mod scalar;
181pub mod schnorr;
182
183use core::marker::PhantomData;
184use core::ptr::NonNull;
185use core::{fmt, mem, str};
186
187use crate::ffi::types::AlignedType;
188use crate::ffi::CPtr;
189
190#[rustfmt::skip]                // Keep public re-exports separate.
191pub use secp256k1_sys as ffi;
192
193#[cfg(all(feature = "global-context", feature = "std"))]
194pub use crate::context::global::{self, SECP256K1};
195#[cfg(feature = "alloc")]
196pub use crate::context::{All, SignOnly, VerifyOnly};
197#[doc(inline)]
198pub use crate::{
199    context::{
200        rerandomize_global_context, with_global_context, with_raw_global_context, AllPreallocated,
201        Context, PreallocatedContext, SignOnlyPreallocated, Signing, Verification,
202        VerifyOnlyPreallocated,
203    },
204    key::{
205        sort_pubkeys, InvalidParityValue, Keypair, Parity, PublicKey, SecretKey, XOnlyPublicKey,
206    },
207    scalar::Scalar,
208};
209
210/// A (hashed) message input to an ECDSA signature.
211#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
212pub struct Message([u8; constants::MESSAGE_SIZE]);
213impl_array_newtype!(Message, u8, constants::MESSAGE_SIZE);
214impl_pretty_debug!(Message);
215
216impl Message {
217    /// Creates a [`Message`] from a `digest`.
218    ///
219    /// The `digest` array has to be a cryptographically secure hash of the actual message that's
220    /// going to be signed. Otherwise the result of signing isn't a [secure signature].
221    ///
222    /// [secure signature]: https://twitter.com/pwuille/status/1063582706288586752
223    #[inline]
224    pub fn from_digest(digest: [u8; 32]) -> Message { Message(digest) }
225
226    /// Creates a [`Message`] from a 32 byte slice `digest`.
227    ///
228    /// The slice has to be 32 bytes long and be a cryptographically secure hash of the actual
229    /// message that's going to be signed. Otherwise the result of signing isn't a [secure
230    /// signature].
231    ///
232    /// This method is deprecated. It's best to use [`Message::from_digest`] directly with an
233    /// array. If your hash engine doesn't return an array for some reason use `.try_into()` on its
234    /// output.
235    ///
236    /// # Errors
237    ///
238    /// If `digest` is not exactly 32 bytes long.
239    ///
240    /// [secure signature]: https://twitter.com/pwuille/status/1063582706288586752
241    #[inline]
242    #[deprecated(since = "0.31.0", note = "use from_digest instead")]
243    pub fn from_digest_slice(digest: &[u8]) -> Result<Message, Error> {
244        Ok(Message::from_digest(digest.try_into().map_err(|_| Error::InvalidMessage)?))
245    }
246}
247
248impl fmt::LowerHex for Message {
249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250        for byte in self.0.iter() {
251            write!(f, "{:02x}", byte)?;
252        }
253        Ok(())
254    }
255}
256
257impl fmt::Display for Message {
258    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
259}
260
261/// The main error type for this library.
262#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]
263pub enum Error {
264    /// Signature failed verification.
265    IncorrectSignature,
266    /// Bad sized message ("messages" are actually fixed-sized digests [`constants::MESSAGE_SIZE`]).
267    InvalidMessage,
268    /// Bad public key.
269    InvalidPublicKey,
270    /// Bad signature.
271    InvalidSignature,
272    /// Bad secret key.
273    InvalidSecretKey,
274    /// Bad shared secret.
275    InvalidSharedSecret,
276    /// Bad recovery id.
277    InvalidRecoveryId,
278    /// Tried to add/multiply by an invalid tweak.
279    InvalidTweak,
280    /// Didn't pass enough memory to context creation with preallocated memory.
281    NotEnoughMemory,
282    /// Bad set of public keys.
283    InvalidPublicKeySum,
284    /// The only valid parity values are 0 or 1.
285    InvalidParityValue(key::InvalidParityValue),
286    /// Bad EllSwift value
287    InvalidEllSwift,
288}
289
290impl fmt::Display for Error {
291    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
292        use Error::*;
293
294        match *self {
295            IncorrectSignature => f.write_str("signature failed verification"),
296            InvalidMessage => f.write_str("message was not 32 bytes (do you need to hash?)"),
297            InvalidPublicKey => f.write_str("malformed public key"),
298            InvalidSignature => f.write_str("malformed signature"),
299            InvalidSecretKey => f.write_str("malformed or out-of-range secret key"),
300            InvalidSharedSecret => f.write_str("malformed or out-of-range shared secret"),
301            InvalidRecoveryId => f.write_str("bad recovery id"),
302            InvalidTweak => f.write_str("bad tweak"),
303            NotEnoughMemory => f.write_str("not enough memory allocated"),
304            InvalidPublicKeySum => f.write_str(
305                "the sum of public keys was invalid or the input vector lengths was less than 1",
306            ),
307            InvalidParityValue(e) => write_err!(f, "couldn't create parity"; e),
308            InvalidEllSwift => f.write_str("malformed EllSwift value"),
309        }
310    }
311}
312
313#[cfg(feature = "std")]
314impl std::error::Error for Error {
315    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
316        match self {
317            Error::IncorrectSignature => None,
318            Error::InvalidMessage => None,
319            Error::InvalidPublicKey => None,
320            Error::InvalidSignature => None,
321            Error::InvalidSecretKey => None,
322            Error::InvalidSharedSecret => None,
323            Error::InvalidRecoveryId => None,
324            Error::InvalidTweak => None,
325            Error::NotEnoughMemory => None,
326            Error::InvalidPublicKeySum => None,
327            Error::InvalidParityValue(error) => Some(error),
328            Error::InvalidEllSwift => None,
329        }
330    }
331}
332
333/// The secp256k1 engine, used to execute all signature operations.
334pub struct Secp256k1<C: Context> {
335    ctx: NonNull<ffi::Context>,
336    phantom: PhantomData<C>,
337}
338
339// The underlying secp context does not contain any references to memory it does not own.
340unsafe impl<C: Context> Send for Secp256k1<C> {}
341// The API does not permit any mutation of `Secp256k1` objects except through `&mut` references.
342unsafe impl<C: Context> Sync for Secp256k1<C> {}
343
344impl<C: Context> PartialEq for Secp256k1<C> {
345    fn eq(&self, _other: &Secp256k1<C>) -> bool { true }
346}
347
348impl<C: Context> Eq for Secp256k1<C> {}
349
350impl<C: Context> Drop for Secp256k1<C> {
351    fn drop(&mut self) {
352        unsafe {
353            let size = ffi::secp256k1_context_preallocated_clone_size(self.ctx.as_ptr());
354            ffi::secp256k1_context_preallocated_destroy(self.ctx);
355
356            C::deallocate(self.ctx.as_ptr() as _, size);
357        }
358    }
359}
360
361impl<C: Context> fmt::Debug for Secp256k1<C> {
362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
363        write!(f, "<secp256k1 context {:?}, {}>", self.ctx, C::DESCRIPTION)
364    }
365}
366
367impl<C: Context> Secp256k1<C> {
368    /// Getter for the raw pointer to the underlying secp256k1 context. This
369    /// shouldn't be needed with normal usage of the library. It enables
370    /// extending the Secp256k1 with more cryptographic algorithms outside of
371    /// this crate.
372    pub fn ctx(&self) -> NonNull<ffi::Context> { self.ctx }
373
374    /// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all).
375    pub fn preallocate_size_gen() -> usize {
376        let word_size = mem::size_of::<AlignedType>();
377        let bytes = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
378
379        (bytes + word_size - 1) / word_size
380    }
381
382    /// (Re)randomizes the Secp256k1 context for extra sidechannel resistance.
383    ///
384    /// Requires compilation with "rand" feature. See comment by Gregory Maxwell in
385    /// [libsecp256k1](https://github.com/bitcoin-core/secp256k1/commit/d2275795ff22a6f4738869f5528fbbb61738aa48).
386    #[cfg(feature = "rand")]
387    pub fn randomize<R: rand::Rng + ?Sized>(&mut self, rng: &mut R) {
388        let mut seed = [0u8; 32];
389        rng.fill_bytes(&mut seed);
390        self.seeded_randomize(&seed);
391    }
392
393    /// (Re)randomizes the Secp256k1 context for extra sidechannel resistance given 32 bytes of
394    /// cryptographically-secure random data;
395    /// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell.
396    pub fn seeded_randomize(&mut self, seed: &[u8; 32]) {
397        unsafe {
398            let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_c_ptr());
399            // This function cannot fail; it has an error return for future-proofing.
400            // We do not expose this error since it is impossible to hit, and we have
401            // precedent for not exposing impossible errors (for example in
402            // `PublicKey::from_secret_key` where it is impossible to create an invalid
403            // secret key through the API.)
404            // However, if this DOES fail, the result is potentially weaker side-channel
405            // resistance, which is deadly and undetectable, so we take out the entire
406            // thread to be on the safe side.
407            assert_eq!(err, 1);
408        }
409    }
410}
411
412impl<C: Signing> Secp256k1<C> {
413    /// Generates a random keypair. Convenience function for [`SecretKey::new`] and
414    /// [`PublicKey::from_secret_key`].
415    #[inline]
416    #[cfg(feature = "rand")]
417    #[deprecated(since = "0.32.0", note = "use secp256k1::generate_keypair instead")]
418    pub fn generate_keypair<R: rand::Rng + ?Sized>(
419        &self,
420        rng: &mut R,
421    ) -> (key::SecretKey, key::PublicKey) {
422        generate_keypair(rng)
423    }
424}
425
426/// Generates a random keypair. Convenience function for [`SecretKey::new`] and
427/// [`PublicKey::from_secret_key`].
428#[inline]
429#[cfg(feature = "rand")]
430pub fn generate_keypair<R: rand::Rng + ?Sized>(rng: &mut R) -> (key::SecretKey, key::PublicKey) {
431    let sk = key::SecretKey::new(rng);
432    let pk = key::PublicKey::from_secret_key(&sk);
433    (sk, pk)
434}
435
436/// Constructor for unit testing. (Calls `generate_keypair` if all
437/// the relevant features are on to get coverage of that functoin.)
438#[cfg(test)]
439#[cfg(all(feature = "global-context", feature = "rand", feature = "std"))]
440fn test_random_keypair() -> (key::SecretKey, key::PublicKey) { generate_keypair(&mut rand::rng()) }
441
442/// Constructor for unit testing.
443#[cfg(test)]
444#[cfg(not(all(feature = "global-context", feature = "rand", feature = "std")))]
445fn test_random_keypair() -> (key::SecretKey, key::PublicKey) {
446    let sk = SecretKey::test_random();
447    let pk = key::PublicKey::from_secret_key(&sk);
448    (sk, pk)
449}
450
451/// Utility function used to parse hex into a target u8 buffer. Returns
452/// the number of bytes converted or an error if it encounters an invalid
453/// character or unexpected end of string.
454fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
455    if hex.len() % 2 == 1 || hex.len() > target.len() * 2 {
456        return Err(());
457    }
458
459    let mut b = 0;
460    let mut idx = 0;
461    for c in hex.bytes() {
462        b <<= 4;
463        match c {
464            b'A'..=b'F' => b |= c - b'A' + 10,
465            b'a'..=b'f' => b |= c - b'a' + 10,
466            b'0'..=b'9' => b |= c - b'0',
467            _ => return Err(()),
468        }
469        if (idx & 1) == 1 {
470            target[idx / 2] = b;
471            b = 0;
472        }
473        idx += 1;
474    }
475    Ok(idx / 2)
476}
477
478/// Utility function used to encode hex into a target u8 buffer. Returns
479/// a reference to the target buffer as an str. Returns an error if the target
480/// buffer isn't big enough.
481#[inline]
482fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
483    let hex_len = src.len() * 2;
484    if target.len() < hex_len {
485        return Err(());
486    }
487    const HEX_TABLE: [u8; 16] = *b"0123456789abcdef";
488
489    let mut i = 0;
490    for &b in src {
491        target[i] = HEX_TABLE[usize::from(b >> 4)];
492        target[i + 1] = HEX_TABLE[usize::from(b & 0b00001111)];
493        i += 2;
494    }
495    let result = &target[..hex_len];
496    debug_assert!(str::from_utf8(result).is_ok());
497    unsafe { Ok(str::from_utf8_unchecked(result)) }
498}
499
500#[cfg(feature = "rand")]
501pub(crate) fn random_32_bytes<R: rand::Rng + ?Sized>(rng: &mut R) -> [u8; 32] {
502    let mut ret = [0u8; 32];
503    rng.fill(&mut ret);
504    ret
505}
506
507/// Generate "random" 32 bytes for unit testing purposes.
508#[cfg(test)]
509fn test_random_32_bytes() -> [u8; 32] {
510    // AtomicU64 not available on all platforms we support
511    use core::sync::atomic::{AtomicU32, Ordering};
512
513    const PRIME_1: u32 = 1021283;
514    const PRIME_2: u32 = 3348599;
515    static RNG: AtomicU32 = AtomicU32::new(0);
516
517    let mut ret = [0; 32];
518    for i in 0..8 {
519        let rng = RNG.load(Ordering::Relaxed).wrapping_mul(PRIME_1).wrapping_add(PRIME_2);
520        ret[i * 4..(i + 1) * 4].copy_from_slice(&rng.to_be_bytes());
521        RNG.store(rng, Ordering::Relaxed);
522    }
523    ret
524}
525
526#[cfg(test)]
527mod tests {
528    use std::str::FromStr;
529
530    use hex_lit::hex;
531    #[cfg(target_arch = "wasm32")]
532    use wasm_bindgen_test::wasm_bindgen_test as test;
533
534    use super::*;
535
536    #[test]
537    #[cfg(feature = "std")]
538    // In rustc 1.72 this Clippy lint was pulled out of clippy and into rustc, and
539    // was made deny-by-default, breaking compilation of this test. Aside from this
540    // breaking change, which there is no point in bugging, the rename was done so
541    // clumsily that you need four separate "allow"s to disable this wrong lint.
542    #[allow(unknown_lints)]
543    #[allow(renamed_and_removed_lints)]
544    #[allow(undropped_manually_drops)]
545    #[allow(clippy::unknown_manually_drops)]
546    fn test_raw_ctx() {
547        use std::mem::{forget, ManuallyDrop};
548
549        let ctx_full = Secp256k1::new();
550        let ctx_sign = Secp256k1::signing_only();
551        let ctx_vrfy = Secp256k1::verification_only();
552
553        let full = unsafe { Secp256k1::from_raw_all(ctx_full.ctx) };
554        let sign = unsafe { Secp256k1::from_raw_signing_only(ctx_sign.ctx) };
555        let mut vrfy = unsafe { Secp256k1::from_raw_verification_only(ctx_vrfy.ctx) };
556
557        let (sk, pk) = crate::test_random_keypair();
558        let msg = Message::from_digest([2u8; 32]);
559        // Try signing
560        assert_eq!(ecdsa::sign(msg, &sk), ecdsa::sign(msg, &sk));
561        let sig = ecdsa::sign(msg, &sk);
562
563        // Try verifying
564        assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
565        assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
566
567        // The following drop will have no effect; in fact, they will trigger a compiler
568        // error because manually dropping a `ManuallyDrop` is almost certainly incorrect.
569        // If you want to drop the inner object you should called `ManuallyDrop::drop`.
570        drop(full);
571        // This will actually drop the context, though it will leave `full` accessible and
572        // in an invalid state. However, this is almost certainly what you want to do.
573        drop(ctx_full);
574        unsafe {
575            // Need to compute the allocation size, and need to do so *before* dropping
576            // anything.
577            let sz = ffi::secp256k1_context_preallocated_clone_size(ctx_sign.ctx.as_ptr());
578            // We can alternately drop the `ManuallyDrop` by unwrapping it and then letting
579            // it be dropped. This is actually a safe function, but it will destruct the
580            // underlying context without deallocating it...
581            ManuallyDrop::into_inner(sign);
582            // ...leaving us holding the bag to deallocate the context's memory without
583            // double-calling `secp256k1_context_destroy`, which cannot be done safely.
584            SignOnly::deallocate(ctx_sign.ctx.as_ptr() as *mut u8, sz);
585            forget(ctx_sign);
586        }
587
588        unsafe {
589            // Finally, we can call `ManuallyDrop::drop`, which has the same effect, but
590            let sz = ffi::secp256k1_context_preallocated_clone_size(ctx_vrfy.ctx.as_ptr());
591            // leaves the `ManuallyDrop` itself accessible. This is marked unsafe.
592            ManuallyDrop::drop(&mut vrfy);
593            VerifyOnly::deallocate(ctx_vrfy.ctx.as_ptr() as *mut u8, sz);
594            forget(ctx_vrfy);
595        }
596    }
597
598    #[cfg(not(target_arch = "wasm32"))]
599    #[test]
600    #[ignore] // Panicking from C may trap (SIGILL) intentionally, so we test this manually.
601    #[cfg(feature = "alloc")]
602    fn test_panic_raw_ctx_should_terminate_abnormally() {
603        // Trying to use an all-zeros public key should cause an ARG_CHECK to trigger.
604        let pk = PublicKey::from(unsafe { ffi::PublicKey::new() });
605        pk.serialize();
606    }
607
608    #[test]
609    #[cfg(all(feature = "rand", feature = "std"))]
610    fn test_preallocation() {
611        let (sk, pk) = crate::generate_keypair(&mut rand::rng());
612        let msg = Message::from_digest([2u8; 32]);
613        // Try signing
614        assert_eq!(ecdsa::sign(msg, &sk), ecdsa::sign(msg, &sk));
615        let sig = ecdsa::sign(msg, &sk);
616
617        // Try verifying
618        assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
619        assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
620    }
621
622    #[test]
623    #[cfg(all(feature = "rand", feature = "std"))]
624    fn capabilities() {
625        let msg = crate::random_32_bytes(&mut rand::rng());
626        let msg = Message::from_digest(msg);
627
628        // Try key generation
629        let (sk, pk) = crate::generate_keypair(&mut rand::rng());
630
631        // Try signing
632        assert_eq!(ecdsa::sign(msg, &sk), ecdsa::sign(msg, &sk));
633        let sig = ecdsa::sign(msg, &sk);
634
635        // Try verifying
636        assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
637        assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
638
639        // Check that we can produce keys from slices with no precomputation
640        let pk_slice = &pk.serialize();
641        let new_pk = PublicKey::from_slice(pk_slice).unwrap();
642        let new_sk = SecretKey::from_secret_bytes(sk.to_secret_bytes()).unwrap();
643        assert_eq!(sk, new_sk);
644        assert_eq!(pk, new_pk);
645    }
646
647    #[test]
648    #[cfg(all(feature = "rand", feature = "std"))]
649    fn signature_serialize_roundtrip() {
650        let mut s = Secp256k1::new();
651        s.randomize(&mut rand::rng());
652
653        for _ in 0..100 {
654            let msg = crate::random_32_bytes(&mut rand::rng());
655            let msg = Message::from_digest(msg);
656
657            let (sk, _) = crate::generate_keypair(&mut rand::rng());
658            let sig1 = ecdsa::sign(msg, &sk);
659            let der = sig1.serialize_der();
660            let sig2 = ecdsa::Signature::from_der(&der[..]).unwrap();
661            assert_eq!(sig1, sig2);
662
663            let compact = sig1.serialize_compact();
664            let sig2 = ecdsa::Signature::from_compact(&compact[..]).unwrap();
665            assert_eq!(sig1, sig2);
666
667            assert!(ecdsa::Signature::from_compact(&der[..]).is_err());
668            assert!(ecdsa::Signature::from_compact(&compact[0..4]).is_err());
669            assert!(ecdsa::Signature::from_der(&compact[..]).is_err());
670            assert!(ecdsa::Signature::from_der(&der[0..4]).is_err());
671        }
672    }
673
674    #[test]
675    fn signature_display() {
676        const HEX_STR: &str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45";
677        let byte_str = hex!(HEX_STR);
678
679        assert_eq!(
680            ecdsa::Signature::from_der(&byte_str).expect("byte str decode"),
681            ecdsa::Signature::from_str(HEX_STR).expect("byte str decode")
682        );
683
684        let sig = ecdsa::Signature::from_str(HEX_STR).expect("byte str decode");
685        assert_eq!(&sig.to_string(), HEX_STR);
686        assert_eq!(&format!("{:?}", sig), HEX_STR);
687
688        assert!(ecdsa::Signature::from_str(
689            "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
690             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4"
691        )
692        .is_err());
693        assert!(ecdsa::Signature::from_str(
694            "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
695             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab"
696        )
697        .is_err());
698        assert!(ecdsa::Signature::from_str(
699            "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
700             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx"
701        )
702        .is_err());
703        assert!(ecdsa::Signature::from_str(
704            "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
705             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
706             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
707             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
708             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
709             72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"
710        )
711        .is_err());
712
713        // 71 byte signature
714        let hex_str = "30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce774b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776";
715        let sig = ecdsa::Signature::from_str(hex_str).expect("byte str decode");
716        assert_eq!(&format!("{}", sig), hex_str);
717    }
718
719    #[test]
720    fn signature_lax_der() {
721        macro_rules! check_lax_sig(
722            ($hex:expr) => ({
723                let sig = hex!($hex);
724                assert!(ecdsa::Signature::from_der_lax(&sig[..]).is_ok());
725            })
726        );
727
728        check_lax_sig!("304402204c2dd8a9b6f8d425fcd8ee9a20ac73b619906a6367eac6cb93e70375225ec0160220356878eff111ff3663d7e6bf08947f94443845e0dcc54961664d922f7660b80c");
729        check_lax_sig!("304402202ea9d51c7173b1d96d331bd41b3d1b4e78e66148e64ed5992abd6ca66290321c0220628c47517e049b3e41509e9d71e480a0cdc766f8cdec265ef0017711c1b5336f");
730        check_lax_sig!("3045022100bf8e050c85ffa1c313108ad8c482c4849027937916374617af3f2e9a881861c9022023f65814222cab09d5ec41032ce9c72ca96a5676020736614de7b78a4e55325a");
731        check_lax_sig!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45");
732        check_lax_sig!("3046022100eaa5f90483eb20224616775891397d47efa64c68b969db1dacb1c30acdfc50aa022100cf9903bbefb1c8000cf482b0aeeb5af19287af20bd794de11d82716f9bae3db1");
733        check_lax_sig!("3045022047d512bc85842ac463ca3b669b62666ab8672ee60725b6c06759e476cebdc6c102210083805e93bd941770109bcc797784a71db9e48913f702c56e60b1c3e2ff379a60");
734        check_lax_sig!("3044022023ee4e95151b2fbbb08a72f35babe02830d14d54bd7ed1320e4751751d1baa4802206235245254f58fd1be6ff19ca291817da76da65c2f6d81d654b5185dd86b8acf");
735    }
736
737    #[test]
738    #[cfg(all(feature = "rand", feature = "std"))]
739    fn sign_and_verify_ecdsa() {
740        let mut s = Secp256k1::new();
741        s.randomize(&mut rand::rng());
742
743        let noncedata = [42u8; 32];
744        for _ in 0..100 {
745            let msg = crate::random_32_bytes(&mut rand::rng());
746            let msg = Message::from_digest(msg);
747
748            let (sk, pk) = crate::generate_keypair(&mut rand::rng());
749            let sig = ecdsa::sign(msg, &sk);
750            assert_eq!(ecdsa::verify(&sig, msg, &pk), Ok(()));
751            let noncedata_sig = ecdsa::sign_with_noncedata(msg, &sk, &noncedata);
752            assert_eq!(ecdsa::verify(&noncedata_sig, msg, &pk), Ok(()));
753            let low_r_sig = ecdsa::sign_low_r(msg, &sk);
754            assert_eq!(ecdsa::verify(&low_r_sig, msg, &pk), Ok(()));
755            let grind_r_sig = ecdsa::sign_grind_r(msg, &sk, 1);
756            assert_eq!(ecdsa::verify(&grind_r_sig, msg, &pk), Ok(()));
757            let compact = sig.serialize_compact();
758            if compact[0] < 0x80 {
759                assert_eq!(sig, low_r_sig);
760            } else {
761                #[cfg(not(secp256k1_fuzz))] // mocked sig generation doesn't produce low-R sigs
762                assert_ne!(sig, low_r_sig);
763            }
764            #[cfg(not(secp256k1_fuzz))] // mocked sig generation doesn't produce low-R sigs
765            assert!(ecdsa::compact_sig_has_zero_first_bit(&low_r_sig.0));
766            #[cfg(not(secp256k1_fuzz))] // mocked sig generation doesn't produce low-R sigs
767            assert!(ecdsa::der_length_check(&grind_r_sig.0, 70));
768        }
769    }
770
771    #[test]
772    #[cfg(all(feature = "rand", feature = "std"))]
773    fn sign_and_verify_extreme() {
774        let mut s = Secp256k1::new();
775        s.randomize(&mut rand::rng());
776
777        // Wild keys: 1, CURVE_ORDER - 1
778        // Wild msgs: 1, CURVE_ORDER - 1
779        let mut wild_keys = [[0u8; 32]; 2];
780        let mut wild_msgs = [[0u8; 32]; 2];
781
782        wild_keys[0][0] = 1;
783        wild_msgs[0][0] = 1;
784
785        use constants;
786        wild_keys[1][..].copy_from_slice(&constants::CURVE_ORDER[..]);
787        wild_msgs[1][..].copy_from_slice(&constants::CURVE_ORDER[..]);
788
789        wild_keys[1][0] -= 1;
790        wild_msgs[1][0] -= 1;
791
792        for key in wild_keys.iter().copied().map(SecretKey::from_secret_bytes).map(Result::unwrap) {
793            for msg in wild_msgs.into_iter().map(Message::from_digest) {
794                let sig = ecdsa::sign(msg, &key);
795                let low_r_sig = ecdsa::sign_low_r(msg, &key);
796                let grind_r_sig = ecdsa::sign_grind_r(msg, &key, 1);
797                let pk = PublicKey::from_secret_key(&key);
798                assert_eq!(ecdsa::verify(&sig, msg, &pk), Ok(()));
799                assert_eq!(ecdsa::verify(&low_r_sig, msg, &pk), Ok(()));
800                assert_eq!(ecdsa::verify(&grind_r_sig, msg, &pk), Ok(()));
801            }
802        }
803    }
804
805    #[test]
806    #[cfg(all(feature = "rand", feature = "std"))]
807    fn sign_and_verify_fail() {
808        let mut s = Secp256k1::new();
809        s.randomize(&mut rand::rng());
810
811        let msg = crate::random_32_bytes(&mut rand::rng());
812        let msg = Message::from_digest(msg);
813
814        let (sk, pk) = crate::generate_keypair(&mut rand::rng());
815
816        let sig = ecdsa::sign(msg, &sk);
817
818        let msg = crate::random_32_bytes(&mut rand::rng());
819        let msg = Message::from_digest(msg);
820        assert_eq!(ecdsa::verify(&sig, msg, &pk), Err(Error::IncorrectSignature));
821    }
822
823    #[test]
824    #[allow(deprecated)]
825    fn test_bad_slice() {
826        assert_eq!(
827            ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]),
828            Err(Error::InvalidSignature)
829        );
830        assert_eq!(
831            ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]),
832            Err(Error::InvalidSignature)
833        );
834
835        assert_eq!(
836            Message::from_digest_slice(&[0; constants::MESSAGE_SIZE - 1]),
837            Err(Error::InvalidMessage)
838        );
839        assert_eq!(
840            Message::from_digest_slice(&[0; constants::MESSAGE_SIZE + 1]),
841            Err(Error::InvalidMessage)
842        );
843        assert!(Message::from_digest_slice(&[0; constants::MESSAGE_SIZE]).is_ok());
844        assert!(Message::from_digest_slice(&[1; constants::MESSAGE_SIZE]).is_ok());
845    }
846
847    #[test]
848    #[cfg(all(feature = "rand", feature = "std"))]
849    fn test_hex() {
850        use rand::RngCore;
851
852        use super::to_hex;
853
854        let mut rng = rand::rng();
855        const AMOUNT: usize = 1024;
856        for i in 0..AMOUNT {
857            // 255 isn't a valid utf8 character.
858            let mut hex_buf = [255u8; AMOUNT * 2];
859            let mut src_buf = [0u8; AMOUNT];
860            let mut result_buf = [0u8; AMOUNT];
861            let src = &mut src_buf[0..i];
862            rng.fill_bytes(src);
863
864            let hex = to_hex(src, &mut hex_buf).unwrap();
865            assert_eq!(from_hex(hex, &mut result_buf).unwrap(), i);
866            assert_eq!(src, &result_buf[..i]);
867        }
868
869        assert!(to_hex(&[1; 2], &mut [0u8; 3]).is_err());
870        assert!(to_hex(&[1; 2], &mut [0u8; 4]).is_ok());
871        assert!(from_hex("deadbeaf", &mut [0u8; 3]).is_err());
872        assert!(from_hex("deadbeaf", &mut [0u8; 4]).is_ok());
873        assert!(from_hex("a", &mut [0u8; 4]).is_err());
874        assert!(from_hex("ag", &mut [0u8; 4]).is_err());
875    }
876
877    #[test]
878    #[cfg(not(secp256k1_fuzz))] // fuzz-sigs have fixed size/format
879    #[cfg(any(feature = "alloc", feature = "std"))]
880    fn test_noncedata() {
881        let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
882        let msg = Message::from_digest(msg);
883        let noncedata = [42u8; 32];
884        let sk =
885            SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead")
886                .unwrap();
887        let expected_sig = hex!("24861b3edd4e7da43319c635091405feced6efa4ec99c3c3c35f6c3ba0ed8816116772e84994084db85a6c20589f6a85af569d42275c2a5dd900da5776b99d5d");
888        let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
889
890        let sig = ecdsa::sign_with_noncedata(msg, &sk, &noncedata);
891
892        assert_eq!(expected_sig, sig);
893    }
894
895    #[test]
896    #[cfg(not(secp256k1_fuzz))] // fixed sig vectors can't work with fuzz-sigs
897    #[cfg(any(feature = "alloc", feature = "std"))]
898    fn test_low_s() {
899        // nb this is a transaction on testnet
900        // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9
901        //      input number 3
902        let sig = hex!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45");
903        let pk = hex!("031ee99d2b786ab3b0991325f2de8489246a6a3fdb700f6d0511b1d80cf5f4cd43");
904        let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
905
906        let mut sig = ecdsa::Signature::from_der(&sig[..]).unwrap();
907        let pk = PublicKey::from_slice(&pk[..]).unwrap();
908        let msg = Message::from_digest(msg);
909
910        // without normalization we expect this will fail
911        assert_eq!(ecdsa::verify(&sig, msg, &pk), Err(Error::IncorrectSignature));
912        // after normalization it should pass
913        sig.normalize_s();
914        assert_eq!(ecdsa::verify(&sig, msg, &pk), Ok(()));
915    }
916
917    #[test]
918    #[cfg(not(secp256k1_fuzz))] // fuzz-sigs have fixed size/format
919    #[cfg(any(feature = "alloc", feature = "std"))]
920    fn test_low_r() {
921        let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
922        let msg = Message::from_digest(msg);
923        let sk =
924            SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead")
925                .unwrap();
926        let expected_sig = hex!("047dd4d049db02b430d24c41c7925b2725bcd5a85393513bdec04b4dc363632b1054d0180094122b380f4cfa391e6296244da773173e78fc745c1b9c79f7b713");
927        let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
928
929        let sig = ecdsa::sign_low_r(msg, &sk);
930
931        assert_eq!(expected_sig, sig);
932    }
933
934    #[test]
935    #[cfg(not(secp256k1_fuzz))] // fuzz-sigs have fixed size/format
936    #[cfg(any(feature = "alloc", feature = "std"))]
937    fn test_grind_r() {
938        let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
939        let msg = Message::from_digest(msg);
940        let sk =
941            SecretKey::from_str("848355d75fe1c354cf05539bb29b2015f1863065bcb6766b44d399ab95c3fa0b")
942                .unwrap();
943        let expected_sig = ecdsa::Signature::from_str("304302202ffc447100d518c8ba643d11f3e6a83a8640488e7d2537b1954b942408be6ea3021f26e1248dd1e52160c3a38af9769d91a1a806cab5f9d508c103464d3c02d6e1").unwrap();
944
945        let sig = ecdsa::sign_grind_r(msg, &sk, 2);
946
947        assert_eq!(expected_sig, sig);
948    }
949
950    #[cfg(feature = "serde")]
951    #[cfg(not(secp256k1_fuzz))] // fixed sig vectors can't work with fuzz-sigs
952    #[cfg(any(feature = "alloc", feature = "std"))]
953    #[test]
954    fn test_serde() {
955        use serde_test::{assert_tokens, Configure, Token};
956
957        let msg = Message::from_digest([1; 32]);
958        let sk = SecretKey::from_secret_bytes([2; 32]).unwrap();
959        let sig = ecdsa::sign(msg, &sk);
960        static SIG_BYTES: [u8; 71] = [
961            48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237, 179, 76, 119, 72,
962            102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148, 8, 230, 206, 119, 75, 2, 32, 40,
963            118, 231, 16, 47, 32, 79, 107, 254, 226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125,
964            75, 1, 0, 98, 225, 147, 247, 99, 25, 15, 103, 118,
965        ];
966        static SIG_STR: &str = "\
967            30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce77\
968            4b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776\
969        ";
970
971        assert_tokens(&sig.compact(), &[Token::BorrowedBytes(&SIG_BYTES[..])]);
972        assert_tokens(&sig.compact(), &[Token::Bytes(&SIG_BYTES)]);
973        assert_tokens(&sig.compact(), &[Token::ByteBuf(&SIG_BYTES)]);
974
975        assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
976        assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
977        assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
978    }
979
980    #[cfg(feature = "global-context")]
981    #[test]
982    fn test_global_context() {
983        let sk_data = hex!("e6dd32f8761625f105c39a39f19370b3521d845a12456d60ce44debd0a362641");
984        let sk = SecretKey::from_secret_bytes(sk_data).unwrap();
985        let msg_data = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
986        let msg = Message::from_digest(msg_data);
987
988        // Check usage as explicit parameter
989        let pk = PublicKey::from_secret_key(&sk);
990
991        // Check usage as self
992        let sig = ecdsa::sign(msg, &sk);
993        assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
994    }
995}
996
997#[cfg(bench)]
998#[cfg(all(feature = "rand", feature = "std"))]
999mod benches {
1000    use rand::rngs::mock::StepRng;
1001    use test::{black_box, Bencher};
1002
1003    use super::*;
1004
1005    #[bench]
1006    pub fn generate(bh: &mut Bencher) {
1007        let s = Secp256k1::new();
1008        let mut r = StepRng::new(1, 1);
1009        bh.iter(|| {
1010            let (sk, pk) = s.generate_keypair(&mut r);
1011            black_box(sk);
1012            black_box(pk);
1013        });
1014    }
1015
1016    #[bench]
1017    pub fn bench_sign_ecdsa(bh: &mut Bencher) {
1018        let s = Secp256k1::new();
1019        let msg = crate::random_32_bytes(&mut rand::rng());
1020        let msg = Message::from_digest(msg);
1021        let (sk, _) = s.generate_keypair(&mut rand::rng());
1022
1023        bh.iter(|| {
1024            let sig = s.sign_ecdsa(msg, &sk);
1025            black_box(sig);
1026        });
1027    }
1028
1029    #[bench]
1030    pub fn bench_verify_ecdsa(bh: &mut Bencher) {
1031        let s = Secp256k1::new();
1032        let msg = crate::random_32_bytes(&mut rand::rng());
1033        let msg = Message::from_digest(msg);
1034        let (sk, pk) = s.generate_keypair(&mut rand::rng());
1035        let sig = s.sign_ecdsa(msg, &sk);
1036
1037        bh.iter(|| {
1038            let res = ecdsa::verify(&sig, msg, &pk).unwrap();
1039            black_box(res);
1040        });
1041    }
1042}