1use crate::crypto::traits::{PublicKey, Signature, Signer, Verifier};
19use crate::error::{AptosError, AptosResult};
20use p256::ecdsa::{
21 Signature as P256Signature, SigningKey, VerifyingKey,
22 signature::Signer as P256Signer,
23 signature::Verifier as P256Verifier,
24 signature::hazmat::{PrehashSigner, PrehashVerifier},
25};
26use serde::{Deserialize, Serialize};
27use std::fmt;
28use zeroize::Zeroize;
29
30pub const SECP256R1_PRIVATE_KEY_LENGTH: usize = 32;
32pub const SECP256R1_PUBLIC_KEY_LENGTH: usize = 33;
34pub const SECP256R1_SIGNATURE_LENGTH: usize = 64;
36
37#[derive(Clone, Zeroize)]
41#[zeroize(drop)]
42pub struct Secp256r1PrivateKey {
43 #[zeroize(skip)]
44 #[allow(unused)] inner: SigningKey,
46}
47
48impl Secp256r1PrivateKey {
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() != SECP256R1_PRIVATE_KEY_LENGTH {
64 return Err(AptosError::InvalidPrivateKey(format!(
65 "expected {} bytes, got {}",
66 SECP256R1_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 = "secp256r1-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; SECP256R1_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!("secp256r1-priv-{}", self.to_hex())
119 }
120
121 pub fn public_key(&self) -> Secp256r1PublicKey {
123 Secp256r1PublicKey {
124 inner: *self.inner.verifying_key(),
125 }
126 }
127
128 pub fn sign(&self, message: &[u8]) -> Secp256r1Signature {
133 let signature: P256Signature = self.inner.sign(message);
141 let normalized = signature.normalize_s().unwrap_or(signature);
144 Secp256r1Signature { inner: normalized }
145 }
146
147 pub fn sign_prehashed(&self, hash: &[u8; 32]) -> Secp256r1Signature {
165 let signature: P256Signature = self
168 .inner
169 .sign_prehash(hash)
170 .expect("32-byte digest is a valid ECDSA prehash");
171 let normalized = signature.normalize_s().unwrap_or(signature);
173 Secp256r1Signature { inner: normalized }
174 }
175}
176
177impl Signer for Secp256r1PrivateKey {
178 type Signature = Secp256r1Signature;
179
180 fn sign(&self, message: &[u8]) -> Secp256r1Signature {
181 Secp256r1PrivateKey::sign(self, message)
182 }
183
184 fn public_key(&self) -> Secp256r1PublicKey {
185 Secp256r1PrivateKey::public_key(self)
186 }
187}
188
189impl fmt::Debug for Secp256r1PrivateKey {
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 write!(f, "Secp256r1PrivateKey([REDACTED])")
192 }
193}
194
195#[derive(Clone, Copy, PartialEq, Eq)]
197pub struct Secp256r1PublicKey {
198 inner: VerifyingKey,
199}
200
201impl Secp256r1PublicKey {
202 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
215 if bytes.len() == 64 {
218 let mut sec1 = Vec::with_capacity(65);
219 sec1.push(0x04);
220 sec1.extend_from_slice(bytes);
221 return VerifyingKey::from_sec1_bytes(&sec1)
222 .map(|inner| Self { inner })
223 .map_err(|e| AptosError::InvalidPublicKey(e.to_string()));
224 }
225 let verifying_key = VerifyingKey::from_sec1_bytes(bytes)
226 .map_err(|e| AptosError::InvalidPublicKey(e.to_string()))?;
227 Ok(Self {
228 inner: verifying_key,
229 })
230 }
231
232 pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
241 let bytes = const_hex::decode(hex_str)?;
242 Self::from_bytes(&bytes)
243 }
244
245 pub fn from_aip80(s: &str) -> AptosResult<Self> {
253 const PREFIX: &str = "secp256r1-pub-";
254 if let Some(hex_part) = s.strip_prefix(PREFIX) {
255 Self::from_hex(hex_part)
256 } else {
257 Err(AptosError::InvalidPublicKey(format!(
258 "invalid AIP-80 format: expected prefix '{PREFIX}'"
259 )))
260 }
261 }
262
263 pub fn to_bytes(&self) -> Vec<u8> {
265 #[allow(unused_imports)]
266 use p256::elliptic_curve::sec1::ToEncodedPoint;
267 self.inner.to_encoded_point(true).as_bytes().to_vec()
268 }
269
270 pub fn to_uncompressed_bytes(&self) -> Vec<u8> {
276 #[allow(unused_imports)]
277 use p256::elliptic_curve::sec1::ToEncodedPoint;
278 self.inner.to_encoded_point(false).as_bytes().to_vec()
279 }
280
281 pub fn to_raw_bytes(&self) -> [u8; 64] {
288 let uncompressed = self.to_uncompressed_bytes();
289 debug_assert_eq!(uncompressed.len(), 65);
290 debug_assert_eq!(uncompressed[0], 0x04);
291 let mut out = [0u8; 64];
292 out.copy_from_slice(&uncompressed[1..]);
293 out
294 }
295
296 pub fn to_hex(&self) -> String {
298 const_hex::encode_prefixed(self.to_bytes())
299 }
300
301 pub fn to_aip80(&self) -> String {
305 format!("secp256r1-pub-{}", self.to_hex())
306 }
307
308 pub fn verify(&self, message: &[u8], signature: &Secp256r1Signature) -> AptosResult<()> {
321 if signature.inner.normalize_s().is_some() {
323 return Err(AptosError::SignatureVerificationFailed);
324 }
325 self.inner
328 .verify(message, &signature.inner)
329 .map_err(|_| AptosError::SignatureVerificationFailed)
330 }
331
332 pub fn verify_prehashed(
344 &self,
345 hash: &[u8; 32],
346 signature: &Secp256r1Signature,
347 ) -> AptosResult<()> {
348 if signature.inner.normalize_s().is_some() {
350 return Err(AptosError::SignatureVerificationFailed);
351 }
352 self.inner
356 .verify_prehash(hash, &signature.inner)
357 .map_err(|_| AptosError::SignatureVerificationFailed)
358 }
359
360 pub fn to_address(&self) -> crate::types::AccountAddress {
367 let uncompressed = self.to_uncompressed_bytes();
373 let mut bcs_bytes = Vec::with_capacity(1 + 1 + uncompressed.len());
374 bcs_bytes.push(0x02); bcs_bytes.push(65); bcs_bytes.extend_from_slice(&uncompressed);
377 crate::crypto::derive_address(&bcs_bytes, crate::crypto::SINGLE_KEY_SCHEME)
378 }
379}
380
381impl PublicKey for Secp256r1PublicKey {
382 const LENGTH: usize = SECP256R1_PUBLIC_KEY_LENGTH;
383
384 fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
385 Secp256r1PublicKey::from_bytes(bytes)
386 }
387
388 fn to_bytes(&self) -> Vec<u8> {
389 Secp256r1PublicKey::to_bytes(self)
390 }
391}
392
393impl Verifier for Secp256r1PublicKey {
394 type Signature = Secp256r1Signature;
395
396 fn verify(&self, message: &[u8], signature: &Secp256r1Signature) -> AptosResult<()> {
397 Secp256r1PublicKey::verify(self, message, signature)
398 }
399}
400
401impl fmt::Debug for Secp256r1PublicKey {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 write!(f, "Secp256r1PublicKey({})", self.to_hex())
404 }
405}
406
407impl fmt::Display for Secp256r1PublicKey {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 write!(f, "{}", self.to_hex())
410 }
411}
412
413impl Serialize for Secp256r1PublicKey {
414 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
415 where
416 S: serde::Serializer,
417 {
418 if serializer.is_human_readable() {
419 serializer.serialize_str(&self.to_hex())
420 } else {
421 serializer.serialize_bytes(&self.to_bytes())
422 }
423 }
424}
425
426impl<'de> Deserialize<'de> for Secp256r1PublicKey {
427 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
428 where
429 D: serde::Deserializer<'de>,
430 {
431 if deserializer.is_human_readable() {
432 let s = String::deserialize(deserializer)?;
433 Self::from_hex(&s).map_err(serde::de::Error::custom)
434 } else {
435 let bytes = Vec::<u8>::deserialize(deserializer)?;
436 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
437 }
438 }
439}
440
441#[derive(Clone, Copy, PartialEq, Eq)]
443pub struct Secp256r1Signature {
444 inner: P256Signature,
445}
446
447impl Secp256r1Signature {
448 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
463 if bytes.len() != SECP256R1_SIGNATURE_LENGTH {
464 return Err(AptosError::InvalidSignature(format!(
465 "expected {} bytes, got {}",
466 SECP256R1_SIGNATURE_LENGTH,
467 bytes.len()
468 )));
469 }
470 let signature = P256Signature::from_slice(bytes)
471 .map_err(|e| AptosError::InvalidSignature(e.to_string()))?;
472 if signature.normalize_s().is_some() {
476 return Err(AptosError::InvalidSignature(
477 "high-S signature rejected: Aptos requires low-S (canonical) ECDSA signatures"
478 .into(),
479 ));
480 }
481 Ok(Self { inner: signature })
482 }
483
484 pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
491 let bytes = const_hex::decode(hex_str)?;
492 Self::from_bytes(&bytes)
493 }
494
495 pub fn to_bytes(&self) -> [u8; SECP256R1_SIGNATURE_LENGTH] {
497 self.inner.to_bytes().into()
498 }
499
500 pub fn to_hex(&self) -> String {
502 const_hex::encode_prefixed(self.to_bytes())
503 }
504}
505
506impl Signature for Secp256r1Signature {
507 type PublicKey = Secp256r1PublicKey;
508 const LENGTH: usize = SECP256R1_SIGNATURE_LENGTH;
509
510 fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
511 Secp256r1Signature::from_bytes(bytes)
512 }
513
514 fn to_bytes(&self) -> Vec<u8> {
515 self.inner.to_bytes().to_vec()
516 }
517}
518
519impl fmt::Debug for Secp256r1Signature {
520 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
521 write!(f, "Secp256r1Signature({})", self.to_hex())
522 }
523}
524
525impl fmt::Display for Secp256r1Signature {
526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527 write!(f, "{}", self.to_hex())
528 }
529}
530
531impl Serialize for Secp256r1Signature {
532 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
533 where
534 S: serde::Serializer,
535 {
536 if serializer.is_human_readable() {
537 serializer.serialize_str(&self.to_hex())
538 } else {
539 serializer.serialize_bytes(&self.to_bytes())
540 }
541 }
542}
543
544impl<'de> Deserialize<'de> for Secp256r1Signature {
545 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
546 where
547 D: serde::Deserializer<'de>,
548 {
549 if deserializer.is_human_readable() {
550 let s = String::deserialize(deserializer)?;
551 Self::from_hex(&s).map_err(serde::de::Error::custom)
552 } else {
553 let bytes = Vec::<u8>::deserialize(deserializer)?;
554 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
555 }
556 }
557}
558
559#[cfg(test)]
560mod tests {
561 use super::*;
562
563 #[test]
564 fn test_generate_and_sign() {
565 let private_key = Secp256r1PrivateKey::generate();
566 let message = b"hello world";
567 let signature = private_key.sign(message);
568
569 let public_key = private_key.public_key();
570 assert!(public_key.verify(message, &signature).is_ok());
571 }
572
573 #[test]
574 fn test_wrong_message_fails() {
575 let private_key = Secp256r1PrivateKey::generate();
576 let message = b"hello world";
577 let wrong_message = b"hello world!";
578 let signature = private_key.sign(message);
579
580 let public_key = private_key.public_key();
581 assert!(public_key.verify(wrong_message, &signature).is_err());
582 }
583
584 #[test]
585 fn test_sign_prehashed_and_verify_prehashed_roundtrip() {
586 let private_key = Secp256r1PrivateKey::generate();
587 let public_key = private_key.public_key();
588 let hash = crate::crypto::sha3_256(b"prehash roundtrip");
589
590 let signature = private_key.sign_prehashed(&hash);
591 public_key.verify_prehashed(&hash, &signature).unwrap();
592 }
593
594 #[test]
595 fn test_verify_prehashed_wrong_hash_fails() {
596 let private_key = Secp256r1PrivateKey::generate();
597 let public_key = private_key.public_key();
598 let hash = crate::crypto::sha3_256(b"prehash correct");
599 let wrong_hash = crate::crypto::sha3_256(b"prehash wrong");
600
601 let signature = private_key.sign_prehashed(&hash);
602 assert!(
603 public_key
604 .verify_prehashed(&wrong_hash, &signature)
605 .is_err()
606 );
607 }
608
609 #[test]
610 fn test_sign_prehashed_signs_digest_directly_not_double_hashed() {
611 let private_key = Secp256r1PrivateKey::generate();
617 let public_key = private_key.public_key();
618 let message = b"prehash must match single-hash signing";
619 let digest = crate::crypto::sha2_256(message);
620
621 let signature = private_key.sign_prehashed(&digest);
622 public_key
623 .verify(message, &signature)
624 .expect("signature over SHA-256(message) must verify against the message");
625 }
626
627 #[test]
628 fn test_from_bytes_roundtrip() {
629 let private_key = Secp256r1PrivateKey::generate();
630 let bytes = private_key.to_bytes();
631 let restored = Secp256r1PrivateKey::from_bytes(&bytes).unwrap();
632 assert_eq!(private_key.to_bytes(), restored.to_bytes());
633 }
634
635 #[test]
636 fn test_public_key_from_bytes_roundtrip() {
637 let private_key = Secp256r1PrivateKey::generate();
638 let public_key = private_key.public_key();
639 let bytes = public_key.to_bytes();
640 let restored = Secp256r1PublicKey::from_bytes(&bytes).unwrap();
641 assert_eq!(public_key.to_bytes(), restored.to_bytes());
642 }
643
644 #[test]
645 fn test_signature_from_bytes_roundtrip() {
646 let private_key = Secp256r1PrivateKey::generate();
647 let signature = private_key.sign(b"test");
648 let bytes = signature.to_bytes();
649 let restored = Secp256r1Signature::from_bytes(&bytes).unwrap();
650 assert_eq!(signature.to_bytes(), restored.to_bytes());
651 }
652
653 #[test]
654 fn test_hex_roundtrip() {
655 let private_key = Secp256r1PrivateKey::generate();
656 let hex = private_key.to_hex();
657 let restored = Secp256r1PrivateKey::from_hex(&hex).unwrap();
658 assert_eq!(private_key.to_bytes(), restored.to_bytes());
659 }
660
661 #[test]
662 fn test_public_key_hex_roundtrip() {
663 let private_key = Secp256r1PrivateKey::generate();
664 let public_key = private_key.public_key();
665 let hex = public_key.to_hex();
666 let restored = Secp256r1PublicKey::from_hex(&hex).unwrap();
667 assert_eq!(public_key.to_bytes(), restored.to_bytes());
668 }
669
670 #[test]
671 fn test_signature_hex_roundtrip() {
672 let private_key = Secp256r1PrivateKey::generate();
673 let signature = private_key.sign(b"test");
674 let hex = signature.to_hex();
675 let restored = Secp256r1Signature::from_hex(&hex).unwrap();
676 assert_eq!(signature.to_bytes(), restored.to_bytes());
677 }
678
679 #[test]
680 fn test_invalid_private_key_bytes() {
681 let bytes = vec![0u8; 16]; let result = Secp256r1PrivateKey::from_bytes(&bytes);
683 assert!(result.is_err());
684 }
685
686 #[test]
687 fn test_invalid_public_key_bytes() {
688 let bytes = vec![0u8; 16]; let result = Secp256r1PublicKey::from_bytes(&bytes);
690 assert!(result.is_err());
691 }
692
693 #[test]
694 fn test_invalid_signature_bytes() {
695 let bytes = vec![0u8; 16]; let result = Secp256r1Signature::from_bytes(&bytes);
697 assert!(result.is_err());
698 }
699
700 #[test]
701 fn test_high_s_signature_rejected() {
702 use p256::elliptic_curve::ops::Neg;
703
704 let private_key = Secp256r1PrivateKey::generate();
706 let signature = private_key.sign(b"test message");
707
708 let low_s_sig = P256Signature::from_slice(&signature.to_bytes()).unwrap();
710 let (r, s) = low_s_sig.split_scalars();
711 let neg_s = s.neg();
712 let high_s_sig = P256Signature::from_scalars(r, neg_s).unwrap();
713 assert!(
715 high_s_sig.normalize_s().is_some(),
716 "constructed signature should be high-S"
717 );
718 let high_s_bytes = high_s_sig.to_bytes();
719
720 let result = Secp256r1Signature::from_bytes(&high_s_bytes);
722 assert!(result.is_err(), "high-S signature should be rejected");
723 assert!(
724 result
725 .unwrap_err()
726 .to_string()
727 .contains("high-S signature rejected"),
728 "error message should mention high-S rejection"
729 );
730
731 let sig_with_high_s = Secp256r1Signature { inner: high_s_sig };
733 let public_key = private_key.public_key();
734 let result = public_key.verify(b"test message", &sig_with_high_s);
735 assert!(result.is_err(), "verify should reject high-S signature");
736 }
737
738 #[test]
739 fn test_signing_always_produces_low_s() {
740 for _ in 0..20 {
742 let private_key = Secp256r1PrivateKey::generate();
743 let signature = private_key.sign(b"test low-s");
744 assert!(
746 signature.inner.normalize_s().is_none(),
747 "signing must always produce low-S signatures"
748 );
749 }
750 }
751
752 #[test]
753 fn test_json_serialization_public_key() {
754 let private_key = Secp256r1PrivateKey::generate();
755 let public_key = private_key.public_key();
756 let json = serde_json::to_string(&public_key).unwrap();
757 let restored: Secp256r1PublicKey = serde_json::from_str(&json).unwrap();
758 assert_eq!(public_key.to_bytes(), restored.to_bytes());
759 }
760
761 #[test]
762 fn test_json_serialization_signature() {
763 let private_key = Secp256r1PrivateKey::generate();
764 let signature = private_key.sign(b"test");
765 let json = serde_json::to_string(&signature).unwrap();
766 let restored: Secp256r1Signature = serde_json::from_str(&json).unwrap();
767 assert_eq!(signature.to_bytes(), restored.to_bytes());
768 }
769
770 #[test]
771 fn test_key_lengths() {
772 assert_eq!(Secp256r1PublicKey::LENGTH, SECP256R1_PUBLIC_KEY_LENGTH);
773 assert_eq!(Secp256r1Signature::LENGTH, SECP256R1_SIGNATURE_LENGTH);
774 }
775
776 #[test]
777 fn test_display_debug() {
778 let private_key = Secp256r1PrivateKey::generate();
779 let public_key = private_key.public_key();
780 let signature = private_key.sign(b"test");
781
782 assert!(format!("{public_key:?}").contains("Secp256r1PublicKey"));
784 assert!(format!("{signature:?}").contains("Secp256r1Signature"));
785
786 assert!(format!("{public_key}").starts_with("0x"));
788 assert!(format!("{signature}").starts_with("0x"));
789 }
790
791 #[test]
792 fn test_compressed_public_key_length() {
793 let private_key = Secp256r1PrivateKey::generate();
794 let public_key = private_key.public_key();
795 assert_eq!(public_key.to_bytes().len(), 33);
797 }
798
799 #[test]
800 fn test_private_key_aip80_roundtrip() {
801 let private_key = Secp256r1PrivateKey::generate();
802 let aip80 = private_key.to_aip80();
803
804 assert!(aip80.starts_with("secp256r1-priv-0x"));
806
807 let restored = Secp256r1PrivateKey::from_aip80(&aip80).unwrap();
809 assert_eq!(private_key.to_bytes(), restored.to_bytes());
810 }
811
812 #[test]
813 fn test_private_key_aip80_format() {
814 let bytes = [0x01; 32];
815 let private_key = Secp256r1PrivateKey::from_bytes(&bytes).unwrap();
816 let aip80 = private_key.to_aip80();
817
818 let expected = format!("secp256r1-priv-0x{}", "01".repeat(32));
820 assert_eq!(aip80, expected);
821 }
822
823 #[test]
824 fn test_private_key_aip80_invalid_prefix() {
825 let result = Secp256r1PrivateKey::from_aip80("ed25519-priv-0x01");
826 assert!(result.is_err());
827 }
828
829 #[test]
830 fn test_public_key_aip80_roundtrip() {
831 let private_key = Secp256r1PrivateKey::generate();
832 let public_key = private_key.public_key();
833 let aip80 = public_key.to_aip80();
834
835 assert!(aip80.starts_with("secp256r1-pub-0x"));
837
838 let restored = Secp256r1PublicKey::from_aip80(&aip80).unwrap();
840 assert_eq!(public_key.to_bytes(), restored.to_bytes());
841 }
842
843 #[test]
844 fn test_public_key_aip80_invalid_prefix() {
845 let result = Secp256r1PublicKey::from_aip80("ed25519-pub-0x01");
846 assert!(result.is_err());
847 }
848
849 #[test]
850 fn test_signer_trait() {
851 use crate::crypto::traits::Signer;
852
853 let private_key = Secp256r1PrivateKey::generate();
854 let message = b"trait test";
855
856 let signature = Signer::sign(&private_key, message);
857 let public_key = Signer::public_key(&private_key);
858
859 assert!(public_key.verify(message, &signature).is_ok());
860 }
861
862 #[test]
863 fn test_verifier_trait() {
864 use crate::crypto::traits::Verifier;
865
866 let private_key = Secp256r1PrivateKey::generate();
867 let public_key = private_key.public_key();
868 let message = b"verifier test";
869 let signature = private_key.sign(message);
870
871 assert!(Verifier::verify(&public_key, message, &signature).is_ok());
872 }
873
874 #[test]
875 fn test_public_key_trait() {
876 use crate::crypto::traits::PublicKey;
877
878 let private_key = Secp256r1PrivateKey::generate();
879 let public_key = private_key.public_key();
880 let bytes = PublicKey::to_bytes(&public_key);
881 let restored = Secp256r1PublicKey::from_bytes(&bytes).unwrap();
882 assert_eq!(public_key.to_bytes(), restored.to_bytes());
883 }
884
885 #[test]
886 fn test_signature_trait() {
887 use crate::crypto::traits::Signature;
888
889 let private_key = Secp256r1PrivateKey::generate();
890 let signature = private_key.sign(b"test");
891 let bytes = Signature::to_bytes(&signature);
892 let restored = Secp256r1Signature::from_bytes(&bytes).unwrap();
893 assert_eq!(signature.to_bytes(), restored.to_bytes());
894 }
895
896 #[test]
897 fn test_private_key_debug() {
898 let private_key = Secp256r1PrivateKey::generate();
899 let debug = format!("{private_key:?}");
900 assert!(debug.contains("REDACTED"));
901 assert!(!debug.contains(&private_key.to_hex()));
902 }
903
904 #[test]
905 fn test_address_derivation() {
906 let private_key = Secp256r1PrivateKey::generate();
907 let public_key = private_key.public_key();
908 let address = public_key.to_address();
909
910 assert!(!address.is_zero());
912
913 let address2 = public_key.to_address();
915 assert_eq!(address, address2);
916 }
917
918 #[test]
919 fn test_uncompressed_bytes() {
920 let private_key = Secp256r1PrivateKey::generate();
921 let public_key = private_key.public_key();
922
923 let uncompressed = public_key.to_uncompressed_bytes();
925 assert_eq!(uncompressed.len(), 65);
926 assert_eq!(uncompressed[0], 0x04); }
928
929 #[test]
930 fn test_private_key_clone() {
931 let private_key = Secp256r1PrivateKey::generate();
932 let cloned = private_key.clone();
933 assert_eq!(private_key.to_bytes(), cloned.to_bytes());
934 }
935
936 #[test]
937 fn test_public_key_equality() {
938 let private_key = Secp256r1PrivateKey::generate();
939 let pk1 = private_key.public_key();
940 let pk2 = private_key.public_key();
941 assert_eq!(pk1, pk2);
942
943 let different = Secp256r1PrivateKey::generate().public_key();
944 assert_ne!(pk1, different);
945 }
946
947 #[test]
948 fn test_signature_verification() {
949 let private_key = Secp256r1PrivateKey::generate();
950 let sig1 = private_key.sign(b"test");
951 let sig2 = private_key.sign(b"test");
952 let public_key = private_key.public_key();
955 assert!(public_key.verify(b"test", &sig1).is_ok());
956 assert!(public_key.verify(b"test", &sig2).is_ok());
957 }
958
959 #[test]
963 fn test_inner_key_zeroizes_on_drop() {
964 fn assert_zeroize_on_drop<T: zeroize::ZeroizeOnDrop>() {}
965 assert_zeroize_on_drop::<SigningKey>();
966 }
967}