1#![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#![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] pub 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#[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 #[inline]
224 pub fn from_digest(digest: [u8; 32]) -> Message { Message(digest) }
225
226 #[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#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]
263pub enum Error {
264 IncorrectSignature,
266 InvalidMessage,
268 InvalidPublicKey,
270 InvalidSignature,
272 InvalidSecretKey,
274 InvalidSharedSecret,
276 InvalidRecoveryId,
278 InvalidTweak,
280 NotEnoughMemory,
282 InvalidPublicKeySum,
284 InvalidParityValue(key::InvalidParityValue),
286 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
333pub struct Secp256k1<C: Context> {
335 ctx: NonNull<ffi::Context>,
336 phantom: PhantomData<C>,
337}
338
339unsafe impl<C: Context> Send for Secp256k1<C> {}
341unsafe 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 pub fn ctx(&self) -> NonNull<ffi::Context> { self.ctx }
373
374 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 #[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 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 assert_eq!(err, 1);
408 }
409 }
410}
411
412impl<C: Signing> Secp256k1<C> {
413 #[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#[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#[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#[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
451fn 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#[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#[cfg(test)]
509fn test_random_32_bytes() -> [u8; 32] {
510 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 #[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 assert_eq!(ecdsa::sign(msg, &sk), ecdsa::sign(msg, &sk));
561 let sig = ecdsa::sign(msg, &sk);
562
563 assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
565 assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
566
567 drop(full);
571 drop(ctx_full);
574 unsafe {
575 let sz = ffi::secp256k1_context_preallocated_clone_size(ctx_sign.ctx.as_ptr());
578 ManuallyDrop::into_inner(sign);
582 SignOnly::deallocate(ctx_sign.ctx.as_ptr() as *mut u8, sz);
585 forget(ctx_sign);
586 }
587
588 unsafe {
589 let sz = ffi::secp256k1_context_preallocated_clone_size(ctx_vrfy.ctx.as_ptr());
591 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] #[cfg(feature = "alloc")]
602 fn test_panic_raw_ctx_should_terminate_abnormally() {
603 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 assert_eq!(ecdsa::sign(msg, &sk), ecdsa::sign(msg, &sk));
615 let sig = ecdsa::sign(msg, &sk);
616
617 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 let (sk, pk) = crate::generate_keypair(&mut rand::rng());
630
631 assert_eq!(ecdsa::sign(msg, &sk), ecdsa::sign(msg, &sk));
633 let sig = ecdsa::sign(msg, &sk);
634
635 assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
637 assert!(ecdsa::verify(&sig, msg, &pk).is_ok());
638
639 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 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))] assert_ne!(sig, low_r_sig);
763 }
764 #[cfg(not(secp256k1_fuzz))] assert!(ecdsa::compact_sig_has_zero_first_bit(&low_r_sig.0));
766 #[cfg(not(secp256k1_fuzz))] 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 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 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))] #[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))] #[cfg(any(feature = "alloc", feature = "std"))]
898 fn test_low_s() {
899 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 assert_eq!(ecdsa::verify(&sig, msg, &pk), Err(Error::IncorrectSignature));
912 sig.normalize_s();
914 assert_eq!(ecdsa::verify(&sig, msg, &pk), Ok(()));
915 }
916
917 #[test]
918 #[cfg(not(secp256k1_fuzz))] #[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))] #[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))] #[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 let pk = PublicKey::from_secret_key(&sk);
990
991 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}