1use crate::crypto::traits::{PublicKey, Signature, Signer, Verifier};
18use crate::error::{AptosError, AptosResult};
19use k256::ecdsa::{
20 Signature as K256Signature, SigningKey, VerifyingKey,
21 signature::hazmat::{PrehashSigner, PrehashVerifier},
22};
23use serde::{Deserialize, Serialize};
24use std::fmt;
25use zeroize::Zeroize;
26
27pub const SECP256K1_PRIVATE_KEY_LENGTH: usize = 32;
29pub const SECP256K1_PUBLIC_KEY_LENGTH: usize = 33;
31#[allow(dead_code)] pub const SECP256K1_PUBLIC_KEY_UNCOMPRESSED_LENGTH: usize = 65;
34pub const SECP256K1_SIGNATURE_LENGTH: usize = 64;
36
37#[derive(Clone, Zeroize)]
41#[zeroize(drop)]
42pub struct Secp256k1PrivateKey {
43 #[zeroize(skip)]
44 #[allow(unused)] inner: SigningKey,
46}
47
48impl Secp256k1PrivateKey {
49 pub fn generate() -> Self {
51 let signing_key = SigningKey::random(&mut rand::rngs::OsRng);
52 Self { inner: signing_key }
53 }
54
55 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
63 if bytes.len() != SECP256K1_PRIVATE_KEY_LENGTH {
64 return Err(AptosError::InvalidPrivateKey(format!(
65 "expected {} bytes, got {}",
66 SECP256K1_PRIVATE_KEY_LENGTH,
67 bytes.len()
68 )));
69 }
70 let signing_key = SigningKey::from_slice(bytes)
71 .map_err(|e| AptosError::InvalidPrivateKey(e.to_string()))?;
72 Ok(Self { inner: signing_key })
73 }
74
75 pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
82 let bytes = const_hex::decode(hex_str)?;
83 Self::from_bytes(&bytes)
84 }
85
86 pub fn from_aip80(s: &str) -> AptosResult<Self> {
94 const PREFIX: &str = "secp256k1-priv-";
95 if let Some(hex_part) = s.strip_prefix(PREFIX) {
96 Self::from_hex(hex_part)
97 } else {
98 Err(AptosError::InvalidPrivateKey(format!(
99 "invalid AIP-80 format: expected prefix '{PREFIX}'"
100 )))
101 }
102 }
103
104 pub fn to_bytes(&self) -> [u8; SECP256K1_PRIVATE_KEY_LENGTH] {
106 self.inner.to_bytes().into()
107 }
108
109 pub fn to_hex(&self) -> String {
111 const_hex::encode_prefixed(self.inner.to_bytes())
112 }
113
114 pub fn to_aip80(&self) -> String {
118 format!("secp256k1-priv-{}", self.to_hex())
119 }
120
121 pub fn public_key(&self) -> Secp256k1PublicKey {
123 Secp256k1PublicKey {
124 inner: *self.inner.verifying_key(),
125 }
126 }
127
128 pub fn sign(&self, message: &[u8]) -> Secp256k1Signature {
150 let digest = crate::crypto::sha3_256(message);
151 let signature: K256Signature = self
152 .inner
153 .sign_prehash(&digest)
154 .expect("32-byte SHA3-256 digest is a valid ECDSA prehash");
155 let normalized = signature.normalize_s().unwrap_or(signature);
157 Secp256k1Signature { inner: normalized }
158 }
159
160 pub fn sign_prehashed(&self, digest: &[u8; 32]) -> Secp256k1Signature {
172 let signature: K256Signature = self
173 .inner
174 .sign_prehash(digest)
175 .expect("32-byte digest is a valid ECDSA prehash");
176 let normalized = signature.normalize_s().unwrap_or(signature);
177 Secp256k1Signature { inner: normalized }
178 }
179}
180
181impl Signer for Secp256k1PrivateKey {
182 type Signature = Secp256k1Signature;
183
184 fn sign(&self, message: &[u8]) -> Secp256k1Signature {
185 Secp256k1PrivateKey::sign(self, message)
186 }
187
188 fn public_key(&self) -> Secp256k1PublicKey {
189 Secp256k1PrivateKey::public_key(self)
190 }
191}
192
193impl fmt::Debug for Secp256k1PrivateKey {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 write!(f, "Secp256k1PrivateKey([REDACTED])")
196 }
197}
198
199#[derive(Clone, Copy, PartialEq, Eq)]
201pub struct Secp256k1PublicKey {
202 inner: VerifyingKey,
203}
204
205impl Secp256k1PublicKey {
206 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
219 if bytes.len() == 64 {
224 let mut sec1 = Vec::with_capacity(65);
225 sec1.push(0x04);
226 sec1.extend_from_slice(bytes);
227 return VerifyingKey::from_sec1_bytes(&sec1)
228 .map(|inner| Self { inner })
229 .map_err(|e| AptosError::InvalidPublicKey(e.to_string()));
230 }
231 let verifying_key = VerifyingKey::from_sec1_bytes(bytes)
232 .map_err(|e| AptosError::InvalidPublicKey(e.to_string()))?;
233 Ok(Self {
234 inner: verifying_key,
235 })
236 }
237
238 pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
247 let bytes = const_hex::decode(hex_str)?;
248 Self::from_bytes(&bytes)
249 }
250
251 pub fn from_aip80(s: &str) -> AptosResult<Self> {
259 const PREFIX: &str = "secp256k1-pub-";
260 if let Some(hex_part) = s.strip_prefix(PREFIX) {
261 Self::from_hex(hex_part)
262 } else {
263 Err(AptosError::InvalidPublicKey(format!(
264 "invalid AIP-80 format: expected prefix '{PREFIX}'"
265 )))
266 }
267 }
268
269 pub fn to_bytes(&self) -> Vec<u8> {
271 self.inner.to_sec1_bytes().to_vec()
272 }
273
274 pub fn to_uncompressed_bytes(&self) -> Vec<u8> {
280 #[allow(unused_imports)]
281 use k256::elliptic_curve::sec1::ToEncodedPoint;
282 self.inner.to_encoded_point(false).as_bytes().to_vec()
283 }
284
285 pub fn to_raw_bytes(&self) -> [u8; 64] {
293 let uncompressed = self.to_uncompressed_bytes();
294 debug_assert_eq!(uncompressed.len(), 65);
297 debug_assert_eq!(uncompressed[0], 0x04);
298 let mut out = [0u8; 64];
299 out.copy_from_slice(&uncompressed[1..]);
300 out
301 }
302
303 pub fn to_hex(&self) -> String {
305 const_hex::encode_prefixed(self.to_bytes())
306 }
307
308 pub fn to_aip80(&self) -> String {
312 format!("secp256k1-pub-{}", self.to_hex())
313 }
314
315 pub fn verify(&self, message: &[u8], signature: &Secp256k1Signature) -> AptosResult<()> {
328 if signature.inner.normalize_s().is_some() {
330 return Err(AptosError::SignatureVerificationFailed);
331 }
332 let digest = crate::crypto::sha3_256(message);
336 self.inner
337 .verify_prehash(&digest, &signature.inner)
338 .map_err(|_| AptosError::SignatureVerificationFailed)
339 }
340
341 pub fn verify_prehashed(
353 &self,
354 hash: &[u8; 32],
355 signature: &Secp256k1Signature,
356 ) -> AptosResult<()> {
357 if signature.inner.normalize_s().is_some() {
359 return Err(AptosError::SignatureVerificationFailed);
360 }
361 self.inner
363 .verify_prehash(hash, &signature.inner)
364 .map_err(|_| AptosError::SignatureVerificationFailed)
365 }
366
367 pub fn to_address(&self) -> crate::types::AccountAddress {
374 let uncompressed = self.to_uncompressed_bytes();
385 let mut bcs_bytes = Vec::with_capacity(1 + 1 + uncompressed.len());
386 bcs_bytes.push(0x01); bcs_bytes.push(65); bcs_bytes.extend_from_slice(&uncompressed);
389 crate::crypto::derive_address(&bcs_bytes, crate::crypto::SINGLE_KEY_SCHEME)
390 }
391}
392
393impl PublicKey for Secp256k1PublicKey {
394 const LENGTH: usize = SECP256K1_PUBLIC_KEY_LENGTH;
395
396 fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
397 Secp256k1PublicKey::from_bytes(bytes)
398 }
399
400 fn to_bytes(&self) -> Vec<u8> {
401 Secp256k1PublicKey::to_bytes(self)
402 }
403}
404
405impl Verifier for Secp256k1PublicKey {
406 type Signature = Secp256k1Signature;
407
408 fn verify(&self, message: &[u8], signature: &Secp256k1Signature) -> AptosResult<()> {
409 Secp256k1PublicKey::verify(self, message, signature)
410 }
411}
412
413impl fmt::Debug for Secp256k1PublicKey {
414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415 write!(f, "Secp256k1PublicKey({})", self.to_hex())
416 }
417}
418
419impl fmt::Display for Secp256k1PublicKey {
420 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421 write!(f, "{}", self.to_hex())
422 }
423}
424
425impl Serialize for Secp256k1PublicKey {
426 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
427 where
428 S: serde::Serializer,
429 {
430 if serializer.is_human_readable() {
431 serializer.serialize_str(&self.to_hex())
432 } else {
433 serializer.serialize_bytes(&self.to_bytes())
434 }
435 }
436}
437
438impl<'de> Deserialize<'de> for Secp256k1PublicKey {
439 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
440 where
441 D: serde::Deserializer<'de>,
442 {
443 if deserializer.is_human_readable() {
444 let s = String::deserialize(deserializer)?;
445 Self::from_hex(&s).map_err(serde::de::Error::custom)
446 } else {
447 let bytes = Vec::<u8>::deserialize(deserializer)?;
448 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
449 }
450 }
451}
452
453#[derive(Clone, Copy, PartialEq, Eq)]
455pub struct Secp256k1Signature {
456 inner: K256Signature,
457}
458
459impl Secp256k1Signature {
460 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
475 if bytes.len() != SECP256K1_SIGNATURE_LENGTH {
476 return Err(AptosError::InvalidSignature(format!(
477 "expected {} bytes, got {}",
478 SECP256K1_SIGNATURE_LENGTH,
479 bytes.len()
480 )));
481 }
482 let signature = K256Signature::from_slice(bytes)
483 .map_err(|e| AptosError::InvalidSignature(e.to_string()))?;
484 if signature.normalize_s().is_some() {
488 return Err(AptosError::InvalidSignature(
489 "high-S signature rejected: Aptos requires low-S (canonical) ECDSA signatures"
490 .into(),
491 ));
492 }
493 Ok(Self { inner: signature })
494 }
495
496 pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
503 let bytes = const_hex::decode(hex_str)?;
504 Self::from_bytes(&bytes)
505 }
506
507 pub fn to_bytes(&self) -> [u8; SECP256K1_SIGNATURE_LENGTH] {
509 self.inner.to_bytes().into()
510 }
511
512 pub fn to_hex(&self) -> String {
514 const_hex::encode_prefixed(self.to_bytes())
515 }
516}
517
518impl Signature for Secp256k1Signature {
519 type PublicKey = Secp256k1PublicKey;
520 const LENGTH: usize = SECP256K1_SIGNATURE_LENGTH;
521
522 fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
523 Secp256k1Signature::from_bytes(bytes)
524 }
525
526 fn to_bytes(&self) -> Vec<u8> {
527 self.inner.to_bytes().to_vec()
528 }
529}
530
531impl fmt::Debug for Secp256k1Signature {
532 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
533 write!(f, "Secp256k1Signature({})", self.to_hex())
534 }
535}
536
537impl fmt::Display for Secp256k1Signature {
538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 write!(f, "{}", self.to_hex())
540 }
541}
542
543impl Serialize for Secp256k1Signature {
544 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
545 where
546 S: serde::Serializer,
547 {
548 if serializer.is_human_readable() {
549 serializer.serialize_str(&self.to_hex())
550 } else {
551 serializer.serialize_bytes(&self.to_bytes())
552 }
553 }
554}
555
556impl<'de> Deserialize<'de> for Secp256k1Signature {
557 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
558 where
559 D: serde::Deserializer<'de>,
560 {
561 if deserializer.is_human_readable() {
562 let s = String::deserialize(deserializer)?;
563 Self::from_hex(&s).map_err(serde::de::Error::custom)
564 } else {
565 let bytes = Vec::<u8>::deserialize(deserializer)?;
566 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
567 }
568 }
569}
570
571#[cfg(test)]
572mod tests {
573 use super::*;
574
575 #[test]
576 fn test_generate_and_sign() {
577 let private_key = Secp256k1PrivateKey::generate();
578 let message = b"hello world";
579 let signature = private_key.sign(message);
580
581 let public_key = private_key.public_key();
582 assert!(public_key.verify(message, &signature).is_ok());
583 }
584
585 #[test]
586 fn test_wrong_message_fails() {
587 let private_key = Secp256k1PrivateKey::generate();
588 let message = b"hello world";
589 let wrong_message = b"hello world!";
590 let signature = private_key.sign(message);
591
592 let public_key = private_key.public_key();
593 assert!(public_key.verify(wrong_message, &signature).is_err());
594 }
595
596 #[test]
597 fn test_from_bytes_roundtrip() {
598 let private_key = Secp256k1PrivateKey::generate();
599 let bytes = private_key.to_bytes();
600 let restored = Secp256k1PrivateKey::from_bytes(&bytes).unwrap();
601 assert_eq!(private_key.to_bytes(), restored.to_bytes());
602 }
603
604 #[test]
605 fn test_public_key_compressed() {
606 let private_key = Secp256k1PrivateKey::generate();
607 let public_key = private_key.public_key();
608
609 assert_eq!(public_key.to_bytes().len(), 33);
611
612 assert_eq!(public_key.to_uncompressed_bytes().len(), 65);
614 }
615
616 #[test]
617 fn test_public_key_from_bytes_roundtrip() {
618 let private_key = Secp256k1PrivateKey::generate();
619 let public_key = private_key.public_key();
620 let bytes = public_key.to_bytes();
621 let restored = Secp256k1PublicKey::from_bytes(&bytes).unwrap();
622 assert_eq!(public_key.to_bytes(), restored.to_bytes());
623 }
624
625 #[test]
626 fn test_signature_from_bytes_roundtrip() {
627 let private_key = Secp256k1PrivateKey::generate();
628 let signature = private_key.sign(b"test");
629 let bytes = signature.to_bytes();
630 let restored = Secp256k1Signature::from_bytes(&bytes).unwrap();
631 assert_eq!(signature.to_bytes(), restored.to_bytes());
632 }
633
634 #[test]
635 fn test_hex_roundtrip() {
636 let private_key = Secp256k1PrivateKey::generate();
637 let hex = private_key.to_hex();
638 let restored = Secp256k1PrivateKey::from_hex(&hex).unwrap();
639 assert_eq!(private_key.to_bytes(), restored.to_bytes());
640 }
641
642 #[test]
643 fn test_public_key_hex_roundtrip() {
644 let private_key = Secp256k1PrivateKey::generate();
645 let public_key = private_key.public_key();
646 let hex = public_key.to_hex();
647 let restored = Secp256k1PublicKey::from_hex(&hex).unwrap();
648 assert_eq!(public_key.to_bytes(), restored.to_bytes());
649 }
650
651 #[test]
652 fn test_signature_hex_roundtrip() {
653 let private_key = Secp256k1PrivateKey::generate();
654 let signature = private_key.sign(b"test");
655 let hex = signature.to_hex();
656 let restored = Secp256k1Signature::from_hex(&hex).unwrap();
657 assert_eq!(signature.to_bytes(), restored.to_bytes());
658 }
659
660 #[test]
661 fn test_invalid_private_key_bytes() {
662 let bytes = vec![0u8; 16]; let result = Secp256k1PrivateKey::from_bytes(&bytes);
664 assert!(result.is_err());
665 }
666
667 #[test]
668 fn test_invalid_public_key_bytes() {
669 let bytes = vec![0u8; 16]; let result = Secp256k1PublicKey::from_bytes(&bytes);
671 assert!(result.is_err());
672 }
673
674 #[test]
675 fn test_invalid_signature_bytes() {
676 let bytes = vec![0u8; 16]; let result = Secp256k1Signature::from_bytes(&bytes);
678 assert!(result.is_err());
679 }
680
681 #[test]
682 fn test_high_s_signature_rejected() {
683 use k256::elliptic_curve::ops::Neg;
684
685 let private_key = Secp256k1PrivateKey::generate();
687 let signature = private_key.sign(b"test message");
688
689 let low_s_sig = k256::ecdsa::Signature::from_slice(&signature.to_bytes()).unwrap();
691 let (r, s) = low_s_sig.split_scalars();
692 let neg_s = s.neg();
693 let high_s_sig = k256::ecdsa::Signature::from_scalars(r, neg_s).unwrap();
694 assert!(
696 high_s_sig.normalize_s().is_some(),
697 "constructed signature should be high-S"
698 );
699 let high_s_bytes = high_s_sig.to_bytes();
700
701 let result = Secp256k1Signature::from_bytes(&high_s_bytes);
703 assert!(result.is_err(), "high-S signature should be rejected");
704 assert!(
705 result
706 .unwrap_err()
707 .to_string()
708 .contains("high-S signature rejected"),
709 "error message should mention high-S rejection"
710 );
711
712 let sig_with_high_s = Secp256k1Signature { inner: high_s_sig };
714 let public_key = private_key.public_key();
715 let result = public_key.verify(b"test message", &sig_with_high_s);
716 assert!(result.is_err(), "verify should reject high-S signature");
717 }
718
719 #[test]
720 fn test_signing_always_produces_low_s() {
721 for _ in 0..20 {
723 let private_key = Secp256k1PrivateKey::generate();
724 let signature = private_key.sign(b"test low-s");
725 assert!(
727 signature.inner.normalize_s().is_none(),
728 "signing must always produce low-S signatures"
729 );
730 }
731 }
732
733 #[test]
734 fn test_sign_prehashed_and_verify_prehashed_roundtrip() {
735 let private_key = Secp256k1PrivateKey::generate();
736 let public_key = private_key.public_key();
737 let hash = crate::crypto::sha3_256(b"prehash roundtrip");
738
739 let signature = private_key.sign_prehashed(&hash);
740 public_key.verify_prehashed(&hash, &signature).unwrap();
741 }
742
743 #[test]
744 fn test_verify_prehashed_wrong_hash_fails() {
745 let private_key = Secp256k1PrivateKey::generate();
746 let public_key = private_key.public_key();
747 let hash = crate::crypto::sha3_256(b"prehash correct");
748 let wrong_hash = crate::crypto::sha3_256(b"prehash wrong");
749 let signature = private_key.sign_prehashed(&hash);
750
751 let result = public_key.verify_prehashed(&wrong_hash, &signature);
752 assert!(result.is_err());
753 }
754
755 #[test]
756 fn test_json_serialization_public_key() {
757 let private_key = Secp256k1PrivateKey::generate();
758 let public_key = private_key.public_key();
759 let json = serde_json::to_string(&public_key).unwrap();
760 let restored: Secp256k1PublicKey = serde_json::from_str(&json).unwrap();
761 assert_eq!(public_key.to_bytes(), restored.to_bytes());
762 }
763
764 #[test]
765 fn test_json_serialization_signature() {
766 let private_key = Secp256k1PrivateKey::generate();
767 let signature = private_key.sign(b"test");
768 let json = serde_json::to_string(&signature).unwrap();
769 let restored: Secp256k1Signature = serde_json::from_str(&json).unwrap();
770 assert_eq!(signature.to_bytes(), restored.to_bytes());
771 }
772
773 #[test]
774 fn test_key_lengths() {
775 assert_eq!(Secp256k1PublicKey::LENGTH, SECP256K1_PUBLIC_KEY_LENGTH);
776 assert_eq!(Secp256k1Signature::LENGTH, SECP256K1_SIGNATURE_LENGTH);
777 }
778
779 #[test]
780 fn test_display_debug() {
781 let private_key = Secp256k1PrivateKey::generate();
782 let public_key = private_key.public_key();
783 let signature = private_key.sign(b"test");
784
785 assert!(format!("{public_key:?}").contains("Secp256k1PublicKey"));
787 assert!(format!("{signature:?}").contains("Secp256k1Signature"));
788
789 assert!(format!("{public_key}").starts_with("0x"));
791 assert!(format!("{signature}").starts_with("0x"));
792 }
793
794 #[test]
795 fn test_private_key_aip80_roundtrip() {
796 let private_key = Secp256k1PrivateKey::generate();
797 let aip80 = private_key.to_aip80();
798
799 assert!(aip80.starts_with("secp256k1-priv-0x"));
801
802 let restored = Secp256k1PrivateKey::from_aip80(&aip80).unwrap();
804 assert_eq!(private_key.to_bytes(), restored.to_bytes());
805 }
806
807 #[test]
808 fn test_private_key_aip80_format() {
809 let bytes = [0x01; 32];
810 let private_key = Secp256k1PrivateKey::from_bytes(&bytes).unwrap();
811 let aip80 = private_key.to_aip80();
812
813 let expected = format!("secp256k1-priv-0x{}", "01".repeat(32));
815 assert_eq!(aip80, expected);
816 }
817
818 #[test]
819 fn test_private_key_aip80_invalid_prefix() {
820 let result = Secp256k1PrivateKey::from_aip80("ed25519-priv-0x01");
821 assert!(result.is_err());
822 }
823
824 #[test]
825 fn test_public_key_aip80_roundtrip() {
826 let private_key = Secp256k1PrivateKey::generate();
827 let public_key = private_key.public_key();
828 let aip80 = public_key.to_aip80();
829
830 assert!(aip80.starts_with("secp256k1-pub-0x"));
832
833 let restored = Secp256k1PublicKey::from_aip80(&aip80).unwrap();
835 assert_eq!(public_key.to_bytes(), restored.to_bytes());
836 }
837
838 #[test]
839 fn test_public_key_aip80_invalid_prefix() {
840 let result = Secp256k1PublicKey::from_aip80("ed25519-pub-0x01");
841 assert!(result.is_err());
842 }
843
844 #[test]
845 fn test_signer_trait() {
846 use crate::crypto::traits::Signer;
847
848 let private_key = Secp256k1PrivateKey::generate();
849 let message = b"trait test";
850
851 let signature = Signer::sign(&private_key, message);
852 let public_key = Signer::public_key(&private_key);
853
854 assert!(public_key.verify(message, &signature).is_ok());
855 }
856
857 #[test]
858 fn test_verifier_trait() {
859 use crate::crypto::traits::Verifier;
860
861 let private_key = Secp256k1PrivateKey::generate();
862 let public_key = private_key.public_key();
863 let message = b"verifier test";
864 let signature = private_key.sign(message);
865
866 assert!(Verifier::verify(&public_key, message, &signature).is_ok());
867 }
868
869 #[test]
870 fn test_public_key_trait() {
871 use crate::crypto::traits::PublicKey;
872
873 let private_key = Secp256k1PrivateKey::generate();
874 let public_key = private_key.public_key();
875 let bytes = PublicKey::to_bytes(&public_key);
876 let restored = Secp256k1PublicKey::from_bytes(&bytes).unwrap();
877 assert_eq!(public_key.to_bytes(), restored.to_bytes());
878 }
879
880 #[test]
881 fn test_signature_trait() {
882 use crate::crypto::traits::Signature;
883
884 let private_key = Secp256k1PrivateKey::generate();
885 let signature = private_key.sign(b"test");
886 let bytes = Signature::to_bytes(&signature);
887 let restored = Secp256k1Signature::from_bytes(&bytes).unwrap();
888 assert_eq!(signature.to_bytes(), restored.to_bytes());
889 }
890
891 #[test]
892 fn test_private_key_debug() {
893 let private_key = Secp256k1PrivateKey::generate();
894 let debug = format!("{private_key:?}");
895 assert!(debug.contains("REDACTED"));
896 assert!(!debug.contains(&private_key.to_hex()));
897 }
898
899 #[test]
900 fn test_address_derivation() {
901 let private_key = Secp256k1PrivateKey::generate();
902 let public_key = private_key.public_key();
903 let address = public_key.to_address();
904
905 assert!(!address.is_zero());
907
908 let address2 = public_key.to_address();
910 assert_eq!(address, address2);
911 }
912
913 #[test]
914 fn test_uncompressed_bytes() {
915 let private_key = Secp256k1PrivateKey::generate();
916 let public_key = private_key.public_key();
917
918 let uncompressed = public_key.to_uncompressed_bytes();
920 assert_eq!(uncompressed.len(), 65);
921 assert_eq!(uncompressed[0], 0x04); }
923
924 #[test]
925 fn test_private_key_clone() {
926 let private_key = Secp256k1PrivateKey::generate();
927 let cloned = private_key.clone();
928 assert_eq!(private_key.to_bytes(), cloned.to_bytes());
929 }
930
931 #[test]
932 fn test_public_key_equality() {
933 let private_key = Secp256k1PrivateKey::generate();
934 let pk1 = private_key.public_key();
935 let pk2 = private_key.public_key();
936 assert_eq!(pk1, pk2);
937
938 let different = Secp256k1PrivateKey::generate().public_key();
939 assert_ne!(pk1, different);
940 }
941
942 #[test]
943 fn test_signature_equality() {
944 let private_key = Secp256k1PrivateKey::generate();
945 let sig1 = private_key.sign(b"test");
946 let sig2 = private_key.sign(b"test");
947 let public_key = private_key.public_key();
950 assert!(public_key.verify(b"test", &sig1).is_ok());
951 assert!(public_key.verify(b"test", &sig2).is_ok());
952 }
953
954 #[test]
958 fn test_inner_key_zeroizes_on_drop() {
959 fn assert_zeroize_on_drop<T: zeroize::ZeroizeOnDrop>() {}
960 assert_zeroize_on_drop::<SigningKey>();
961 }
962}