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