Skip to main content

aptos_sdk/crypto/
ed25519.rs

1//! Ed25519 signature scheme implementation.
2//!
3//! Ed25519 is the default and most commonly used signature scheme on Aptos.
4
5use crate::crypto::traits::{PublicKey, Signature, Signer, Verifier};
6use crate::error::{AptosError, AptosResult};
7use ed25519_dalek::{Signer as DalekSigner, Verifier as DalekVerifier};
8use serde::{Deserialize, Serialize};
9use std::fmt;
10use zeroize::Zeroize;
11
12/// Ed25519 private key length in bytes.
13pub const ED25519_PRIVATE_KEY_LENGTH: usize = 32;
14/// Ed25519 public key length in bytes.
15pub const ED25519_PUBLIC_KEY_LENGTH: usize = 32;
16/// Ed25519 signature length in bytes.
17pub const ED25519_SIGNATURE_LENGTH: usize = 64;
18
19/// An Ed25519 private key.
20///
21/// The private key is zeroized when dropped to prevent sensitive
22/// data from remaining in memory.
23///
24/// # Example
25///
26/// ```rust
27/// use aptos_sdk::crypto::{Ed25519PrivateKey, Signer};
28///
29/// // Generate a random key
30/// let private_key = Ed25519PrivateKey::generate();
31///
32/// // Sign a message
33/// let signature = private_key.sign(b"hello");
34///
35/// // Get the public key
36/// let public_key = private_key.public_key();
37/// ```
38#[derive(Clone, Zeroize)]
39#[zeroize(drop)]
40pub struct Ed25519PrivateKey {
41    #[zeroize(skip)]
42    #[allow(unused)] // Field is used; lint false positive from Zeroize derive
43    inner: ed25519_dalek::SigningKey,
44}
45
46impl Ed25519PrivateKey {
47    /// Generates a new random Ed25519 private key.
48    pub fn generate() -> Self {
49        let mut csprng = rand::rngs::OsRng;
50        let signing_key = ed25519_dalek::SigningKey::generate(&mut csprng);
51        Self { inner: signing_key }
52    }
53
54    /// Creates a private key from raw bytes.
55    ///
56    /// # Errors
57    ///
58    /// Returns [`AptosError::InvalidPrivateKey`] if:
59    /// - The byte slice length is not exactly 32 bytes
60    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
61        if bytes.len() != ED25519_PRIVATE_KEY_LENGTH {
62            return Err(AptosError::InvalidPrivateKey(format!(
63                "expected {} bytes, got {}",
64                ED25519_PRIVATE_KEY_LENGTH,
65                bytes.len()
66            )));
67        }
68        let mut key_bytes = [0u8; ED25519_PRIVATE_KEY_LENGTH];
69        key_bytes.copy_from_slice(bytes);
70        let signing_key = ed25519_dalek::SigningKey::from_bytes(&key_bytes);
71        Ok(Self { inner: signing_key })
72    }
73
74    /// Creates a private key from a hex string.
75    ///
76    /// # Errors
77    ///
78    /// Returns [`AptosError::Hex`] if the hex string is invalid.
79    /// Returns [`AptosError::InvalidPrivateKey`] if the decoded bytes are not exactly 32 bytes.
80    pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
81        let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
82        let bytes = hex::decode(hex_str)?;
83        Self::from_bytes(&bytes)
84    }
85
86    /// Creates a private key from AIP-80 format string.
87    ///
88    /// AIP-80 format: `ed25519-priv-0x{hex_bytes}`
89    ///
90    /// # Errors
91    ///
92    /// Returns an error if the format is invalid or the key bytes are invalid.
93    ///
94    /// # Example
95    ///
96    /// ```rust
97    /// use aptos_sdk::crypto::Ed25519PrivateKey;
98    ///
99    /// let key = Ed25519PrivateKey::from_aip80(
100    ///     "ed25519-priv-0x0000000000000000000000000000000000000000000000000000000000000001"
101    /// ).unwrap();
102    /// ```
103    pub fn from_aip80(s: &str) -> AptosResult<Self> {
104        const PREFIX: &str = "ed25519-priv-";
105        if let Some(hex_part) = s.strip_prefix(PREFIX) {
106            Self::from_hex(hex_part)
107        } else {
108            Err(AptosError::InvalidPrivateKey(format!(
109                "invalid AIP-80 format: expected prefix '{PREFIX}'"
110            )))
111        }
112    }
113
114    /// Returns the private key as bytes.
115    ///
116    /// **Warning**: Handle the returned bytes carefully to avoid leaking
117    /// sensitive key material.
118    pub fn to_bytes(&self) -> [u8; ED25519_PRIVATE_KEY_LENGTH] {
119        self.inner.to_bytes()
120    }
121
122    /// Returns the private key as a hex string.
123    pub fn to_hex(&self) -> String {
124        format!("0x{}", hex::encode(self.inner.to_bytes()))
125    }
126
127    /// Returns the private key in AIP-80 format.
128    ///
129    /// AIP-80 format: `ed25519-priv-0x{hex_bytes}`
130    ///
131    /// # Example
132    ///
133    /// ```rust
134    /// use aptos_sdk::crypto::Ed25519PrivateKey;
135    ///
136    /// let key = Ed25519PrivateKey::generate();
137    /// let aip80 = key.to_aip80();
138    /// assert!(aip80.starts_with("ed25519-priv-0x"));
139    /// ```
140    pub fn to_aip80(&self) -> String {
141        format!("ed25519-priv-{}", self.to_hex())
142    }
143
144    /// Returns the corresponding public key.
145    pub fn public_key(&self) -> Ed25519PublicKey {
146        Ed25519PublicKey {
147            inner: self.inner.verifying_key(),
148        }
149    }
150
151    /// Signs a message and returns the signature.
152    pub fn sign(&self, message: &[u8]) -> Ed25519Signature {
153        let signature = self.inner.sign(message);
154        Ed25519Signature { inner: signature }
155    }
156}
157
158impl Signer for Ed25519PrivateKey {
159    type Signature = Ed25519Signature;
160
161    fn sign(&self, message: &[u8]) -> Ed25519Signature {
162        Ed25519PrivateKey::sign(self, message)
163    }
164
165    fn public_key(&self) -> Ed25519PublicKey {
166        Ed25519PrivateKey::public_key(self)
167    }
168}
169
170impl fmt::Debug for Ed25519PrivateKey {
171    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172        write!(f, "Ed25519PrivateKey([REDACTED])")
173    }
174}
175
176/// An Ed25519 public key.
177///
178/// # Example
179///
180/// ```rust
181/// use aptos_sdk::crypto::{Ed25519PrivateKey, Ed25519PublicKey, Signer, Verifier};
182///
183/// let private_key = Ed25519PrivateKey::generate();
184/// let public_key = private_key.public_key();
185///
186/// let message = b"hello";
187/// let signature = private_key.sign(message);
188///
189/// assert!(public_key.verify(message, &signature).is_ok());
190/// ```
191#[derive(Clone, Copy, PartialEq, Eq)]
192pub struct Ed25519PublicKey {
193    inner: ed25519_dalek::VerifyingKey,
194}
195
196impl Ed25519PublicKey {
197    /// Creates a public key from raw bytes.
198    ///
199    /// # Errors
200    ///
201    /// Returns [`AptosError::InvalidPublicKey`] if:
202    /// - The byte slice length is not exactly 32 bytes
203    /// - The bytes do not represent a valid Ed25519 public key
204    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
205        if bytes.len() != ED25519_PUBLIC_KEY_LENGTH {
206            return Err(AptosError::InvalidPublicKey(format!(
207                "expected {} bytes, got {}",
208                ED25519_PUBLIC_KEY_LENGTH,
209                bytes.len()
210            )));
211        }
212        let mut key_bytes = [0u8; ED25519_PUBLIC_KEY_LENGTH];
213        key_bytes.copy_from_slice(bytes);
214        let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(&key_bytes)
215            .map_err(|e| AptosError::InvalidPublicKey(e.to_string()))?;
216        Ok(Self {
217            inner: verifying_key,
218        })
219    }
220
221    /// Creates a public key from a hex string.
222    ///
223    /// # Errors
224    ///
225    /// Returns [`AptosError::Hex`] if the hex string is invalid.
226    /// Returns [`AptosError::InvalidPublicKey`] if the decoded bytes are not exactly 32 bytes or do not represent a valid Ed25519 public key.
227    pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
228        let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
229        let bytes = hex::decode(hex_str)?;
230        Self::from_bytes(&bytes)
231    }
232
233    /// Creates a public key from AIP-80 format string.
234    ///
235    /// AIP-80 format: `ed25519-pub-0x{hex_bytes}`
236    ///
237    /// # Errors
238    ///
239    /// Returns an error if the format is invalid or the key bytes are invalid.
240    pub fn from_aip80(s: &str) -> AptosResult<Self> {
241        const PREFIX: &str = "ed25519-pub-";
242        if let Some(hex_part) = s.strip_prefix(PREFIX) {
243            Self::from_hex(hex_part)
244        } else {
245            Err(AptosError::InvalidPublicKey(format!(
246                "invalid AIP-80 format: expected prefix '{PREFIX}'"
247            )))
248        }
249    }
250
251    /// Returns the public key as bytes.
252    pub fn to_bytes(&self) -> [u8; ED25519_PUBLIC_KEY_LENGTH] {
253        self.inner.to_bytes()
254    }
255
256    /// Returns the public key as a hex string.
257    pub fn to_hex(&self) -> String {
258        format!("0x{}", hex::encode(self.inner.to_bytes()))
259    }
260
261    /// Returns the public key in AIP-80 format.
262    ///
263    /// AIP-80 format: `ed25519-pub-0x{hex_bytes}`
264    pub fn to_aip80(&self) -> String {
265        format!("ed25519-pub-{}", self.to_hex())
266    }
267
268    /// Verifies a signature against a message.
269    ///
270    /// # Errors
271    ///
272    /// Returns [`AptosError::SignatureVerificationFailed`] if the signature is invalid or does not match the message.
273    pub fn verify(&self, message: &[u8], signature: &Ed25519Signature) -> AptosResult<()> {
274        self.inner
275            .verify(message, &signature.inner)
276            .map_err(|_| AptosError::SignatureVerificationFailed)
277    }
278
279    /// Derives the account address for this public key.
280    ///
281    /// Uses the Ed25519 single-key scheme (scheme byte 0).
282    pub fn to_address(&self) -> crate::types::AccountAddress {
283        crate::crypto::derive_address(&self.to_bytes(), crate::crypto::ED25519_SCHEME)
284    }
285
286    /// Derives the authentication key for this public key.
287    pub fn to_authentication_key(&self) -> [u8; 32] {
288        crate::crypto::derive_authentication_key(&self.to_bytes(), crate::crypto::ED25519_SCHEME)
289    }
290}
291
292impl PublicKey for Ed25519PublicKey {
293    const LENGTH: usize = ED25519_PUBLIC_KEY_LENGTH;
294
295    fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
296        Ed25519PublicKey::from_bytes(bytes)
297    }
298
299    fn to_bytes(&self) -> Vec<u8> {
300        self.inner.to_bytes().to_vec()
301    }
302}
303
304impl Verifier for Ed25519PublicKey {
305    type Signature = Ed25519Signature;
306
307    fn verify(&self, message: &[u8], signature: &Ed25519Signature) -> AptosResult<()> {
308        Ed25519PublicKey::verify(self, message, signature)
309    }
310}
311
312impl fmt::Debug for Ed25519PublicKey {
313    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314        write!(f, "Ed25519PublicKey({})", self.to_hex())
315    }
316}
317
318impl fmt::Display for Ed25519PublicKey {
319    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
320        write!(f, "{}", self.to_hex())
321    }
322}
323
324impl Serialize for Ed25519PublicKey {
325    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
326    where
327        S: serde::Serializer,
328    {
329        if serializer.is_human_readable() {
330            serializer.serialize_str(&self.to_hex())
331        } else {
332            serializer.serialize_bytes(&self.inner.to_bytes())
333        }
334    }
335}
336
337impl<'de> Deserialize<'de> for Ed25519PublicKey {
338    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
339    where
340        D: serde::Deserializer<'de>,
341    {
342        if deserializer.is_human_readable() {
343            let s = String::deserialize(deserializer)?;
344            Self::from_hex(&s).map_err(serde::de::Error::custom)
345        } else {
346            let bytes = <[u8; ED25519_PUBLIC_KEY_LENGTH]>::deserialize(deserializer)?;
347            Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
348        }
349    }
350}
351
352/// An Ed25519 signature.
353#[derive(Clone, Copy, PartialEq, Eq)]
354pub struct Ed25519Signature {
355    inner: ed25519_dalek::Signature,
356}
357
358impl Ed25519Signature {
359    /// Creates a signature from raw bytes.
360    ///
361    /// # Errors
362    ///
363    /// Returns [`AptosError::InvalidSignature`] if:
364    /// - The byte slice length is not exactly 64 bytes
365    /// - The bytes do not represent a valid Ed25519 signature
366    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
367        if bytes.len() != ED25519_SIGNATURE_LENGTH {
368            return Err(AptosError::InvalidSignature(format!(
369                "expected {} bytes, got {}",
370                ED25519_SIGNATURE_LENGTH,
371                bytes.len()
372            )));
373        }
374        let signature = ed25519_dalek::Signature::from_slice(bytes)
375            .map_err(|e| AptosError::InvalidSignature(e.to_string()))?;
376        Ok(Self { inner: signature })
377    }
378
379    /// Creates a signature from a hex string.
380    ///
381    /// # Errors
382    ///
383    /// Returns [`AptosError::Hex`] if the hex string is invalid.
384    /// Returns [`AptosError::InvalidSignature`] if the decoded bytes are not exactly 64 bytes or do not represent a valid Ed25519 signature.
385    pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
386        let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
387        let bytes = hex::decode(hex_str)?;
388        Self::from_bytes(&bytes)
389    }
390
391    /// Returns the signature as bytes.
392    pub fn to_bytes(&self) -> [u8; ED25519_SIGNATURE_LENGTH] {
393        self.inner.to_bytes()
394    }
395
396    /// Returns the signature as a hex string.
397    pub fn to_hex(&self) -> String {
398        format!("0x{}", hex::encode(self.inner.to_bytes()))
399    }
400}
401
402impl Signature for Ed25519Signature {
403    type PublicKey = Ed25519PublicKey;
404    const LENGTH: usize = ED25519_SIGNATURE_LENGTH;
405
406    fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
407        Ed25519Signature::from_bytes(bytes)
408    }
409
410    fn to_bytes(&self) -> Vec<u8> {
411        self.inner.to_bytes().to_vec()
412    }
413}
414
415impl fmt::Debug for Ed25519Signature {
416    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417        write!(f, "Ed25519Signature({})", self.to_hex())
418    }
419}
420
421impl fmt::Display for Ed25519Signature {
422    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423        write!(f, "{}", self.to_hex())
424    }
425}
426
427impl Serialize for Ed25519Signature {
428    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
429    where
430        S: serde::Serializer,
431    {
432        if serializer.is_human_readable() {
433            serializer.serialize_str(&self.to_hex())
434        } else {
435            serializer.serialize_bytes(&self.inner.to_bytes())
436        }
437    }
438}
439
440impl<'de> Deserialize<'de> for Ed25519Signature {
441    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
442    where
443        D: serde::Deserializer<'de>,
444    {
445        if deserializer.is_human_readable() {
446            let s = String::deserialize(deserializer)?;
447            Self::from_hex(&s).map_err(serde::de::Error::custom)
448        } else {
449            let bytes = Vec::<u8>::deserialize(deserializer)?;
450            Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
451        }
452    }
453}
454
455#[cfg(test)]
456mod tests {
457    use super::*;
458
459    #[test]
460    fn test_generate_and_sign() {
461        let private_key = Ed25519PrivateKey::generate();
462        let message = b"hello world";
463        let signature = private_key.sign(message);
464
465        let public_key = private_key.public_key();
466        assert!(public_key.verify(message, &signature).is_ok());
467    }
468
469    #[test]
470    fn test_wrong_message_fails() {
471        let private_key = Ed25519PrivateKey::generate();
472        let message = b"hello world";
473        let wrong_message = b"hello world!";
474        let signature = private_key.sign(message);
475
476        let public_key = private_key.public_key();
477        assert!(public_key.verify(wrong_message, &signature).is_err());
478    }
479
480    #[test]
481    fn test_from_bytes_roundtrip() {
482        let private_key = Ed25519PrivateKey::generate();
483        let bytes = private_key.to_bytes();
484        let restored = Ed25519PrivateKey::from_bytes(&bytes).unwrap();
485        assert_eq!(private_key.to_bytes(), restored.to_bytes());
486    }
487
488    #[test]
489    fn test_from_hex_roundtrip() {
490        let private_key = Ed25519PrivateKey::generate();
491        let hex = private_key.to_hex();
492        let restored = Ed25519PrivateKey::from_hex(&hex).unwrap();
493        assert_eq!(private_key.to_bytes(), restored.to_bytes());
494    }
495
496    #[test]
497    fn test_public_key_serialization() {
498        let private_key = Ed25519PrivateKey::generate();
499        let public_key = private_key.public_key();
500
501        let json = serde_json::to_string(&public_key).unwrap();
502        let restored: Ed25519PublicKey = serde_json::from_str(&json).unwrap();
503        assert_eq!(public_key, restored);
504    }
505
506    #[test]
507    fn test_address_derivation() {
508        let private_key = Ed25519PrivateKey::generate();
509        let public_key = private_key.public_key();
510        let address = public_key.to_address();
511
512        // Address should not be zero
513        assert!(!address.is_zero());
514
515        // Same public key should always derive same address
516        let address2 = public_key.to_address();
517        assert_eq!(address, address2);
518    }
519
520    #[test]
521    fn test_private_key_aip80_roundtrip() {
522        let private_key = Ed25519PrivateKey::generate();
523        let aip80 = private_key.to_aip80();
524
525        // Should have correct prefix
526        assert!(aip80.starts_with("ed25519-priv-0x"));
527
528        // Should roundtrip correctly
529        let restored = Ed25519PrivateKey::from_aip80(&aip80).unwrap();
530        assert_eq!(private_key.to_bytes(), restored.to_bytes());
531    }
532
533    #[test]
534    fn test_private_key_aip80_format() {
535        let bytes = [0x01; 32];
536        let private_key = Ed25519PrivateKey::from_bytes(&bytes).unwrap();
537        let aip80 = private_key.to_aip80();
538
539        // Expected format: ed25519-priv-0x0101...01
540        let expected = format!("ed25519-priv-0x{}", "01".repeat(32));
541        assert_eq!(aip80, expected);
542    }
543
544    #[test]
545    fn test_private_key_aip80_invalid_prefix() {
546        let result = Ed25519PrivateKey::from_aip80("secp256k1-priv-0x01");
547        assert!(result.is_err());
548    }
549
550    #[test]
551    fn test_public_key_aip80_roundtrip() {
552        let private_key = Ed25519PrivateKey::generate();
553        let public_key = private_key.public_key();
554        let aip80 = public_key.to_aip80();
555
556        // Should have correct prefix
557        assert!(aip80.starts_with("ed25519-pub-0x"));
558
559        // Should roundtrip correctly
560        let restored = Ed25519PublicKey::from_aip80(&aip80).unwrap();
561        assert_eq!(public_key.to_bytes(), restored.to_bytes());
562    }
563
564    #[test]
565    fn test_public_key_aip80_invalid_prefix() {
566        let result = Ed25519PublicKey::from_aip80("secp256k1-pub-0x01");
567        assert!(result.is_err());
568    }
569
570    #[test]
571    fn test_invalid_private_key_bytes_length() {
572        let bytes = vec![0u8; 16]; // Wrong length
573        let result = Ed25519PrivateKey::from_bytes(&bytes);
574        assert!(result.is_err());
575    }
576
577    #[test]
578    fn test_invalid_public_key_bytes_length() {
579        let bytes = vec![0u8; 16]; // Wrong length
580        let result = Ed25519PublicKey::from_bytes(&bytes);
581        assert!(result.is_err());
582    }
583
584    #[test]
585    fn test_invalid_signature_bytes_length() {
586        let bytes = vec![0u8; 32]; // Wrong length
587        let result = Ed25519Signature::from_bytes(&bytes);
588        assert!(result.is_err());
589    }
590
591    #[test]
592    fn test_public_key_from_hex_roundtrip() {
593        let private_key = Ed25519PrivateKey::generate();
594        let public_key = private_key.public_key();
595        let hex = public_key.to_hex();
596        let restored = Ed25519PublicKey::from_hex(&hex).unwrap();
597        assert_eq!(public_key, restored);
598    }
599
600    #[test]
601    fn test_signature_from_hex_roundtrip() {
602        let private_key = Ed25519PrivateKey::generate();
603        let signature = private_key.sign(b"test");
604        let hex = signature.to_hex();
605        let restored = Ed25519Signature::from_hex(&hex).unwrap();
606        assert_eq!(signature.to_bytes(), restored.to_bytes());
607    }
608
609    #[test]
610    fn test_public_key_bytes_roundtrip() {
611        let private_key = Ed25519PrivateKey::generate();
612        let public_key = private_key.public_key();
613        let bytes = public_key.to_bytes();
614        let restored = Ed25519PublicKey::from_bytes(&bytes).unwrap();
615        assert_eq!(public_key, restored);
616    }
617
618    #[test]
619    fn test_signature_bytes_roundtrip() {
620        let private_key = Ed25519PrivateKey::generate();
621        let signature = private_key.sign(b"test");
622        let bytes = signature.to_bytes();
623        let restored = Ed25519Signature::from_bytes(&bytes).unwrap();
624        assert_eq!(signature.to_bytes(), restored.to_bytes());
625    }
626
627    #[test]
628    fn test_private_key_debug() {
629        let private_key = Ed25519PrivateKey::generate();
630        let debug = format!("{private_key:?}");
631        assert!(debug.contains("REDACTED"));
632        assert!(!debug.contains(&private_key.to_hex()));
633    }
634
635    #[test]
636    fn test_public_key_debug() {
637        let private_key = Ed25519PrivateKey::generate();
638        let public_key = private_key.public_key();
639        let debug = format!("{public_key:?}");
640        assert!(debug.contains("Ed25519PublicKey"));
641    }
642
643    #[test]
644    fn test_public_key_display() {
645        let private_key = Ed25519PrivateKey::generate();
646        let public_key = private_key.public_key();
647        let display = format!("{public_key}");
648        assert!(display.starts_with("0x"));
649    }
650
651    #[test]
652    fn test_signature_debug() {
653        let private_key = Ed25519PrivateKey::generate();
654        let signature = private_key.sign(b"test");
655        let debug = format!("{signature:?}");
656        assert!(debug.contains("Ed25519Signature"));
657    }
658
659    #[test]
660    fn test_signature_display() {
661        let private_key = Ed25519PrivateKey::generate();
662        let signature = private_key.sign(b"test");
663        let display = format!("{signature}");
664        assert!(display.starts_with("0x"));
665    }
666
667    #[test]
668    fn test_signer_trait() {
669        use crate::crypto::traits::Signer;
670
671        let private_key = Ed25519PrivateKey::generate();
672        let message = b"trait test";
673
674        let signature = Signer::sign(&private_key, message);
675        let public_key = Signer::public_key(&private_key);
676
677        assert!(public_key.verify(message, &signature).is_ok());
678    }
679
680    #[test]
681    fn test_verifier_trait() {
682        use crate::crypto::traits::Verifier;
683
684        let private_key = Ed25519PrivateKey::generate();
685        let public_key = private_key.public_key();
686        let message = b"verifier test";
687        let signature = private_key.sign(message);
688
689        assert!(Verifier::verify(&public_key, message, &signature).is_ok());
690    }
691
692    #[test]
693    fn test_public_key_trait() {
694        use crate::crypto::traits::PublicKey;
695
696        let private_key = Ed25519PrivateKey::generate();
697        let public_key = private_key.public_key();
698        let bytes = PublicKey::to_bytes(&public_key);
699        let restored = Ed25519PublicKey::from_bytes(&bytes).unwrap();
700        assert_eq!(public_key, restored);
701    }
702
703    #[test]
704    fn test_signature_trait() {
705        use crate::crypto::traits::Signature;
706
707        let private_key = Ed25519PrivateKey::generate();
708        let signature = private_key.sign(b"test");
709        let bytes = Signature::to_bytes(&signature);
710        let restored = Ed25519Signature::from_bytes(&bytes).unwrap();
711        assert_eq!(signature.to_bytes(), restored.to_bytes());
712    }
713
714    #[test]
715    fn test_authentication_key() {
716        let private_key = Ed25519PrivateKey::generate();
717        let public_key = private_key.public_key();
718        let auth_key = public_key.to_authentication_key();
719        assert_eq!(auth_key.len(), 32);
720    }
721
722    #[test]
723    fn test_signature_json_serialization() {
724        let private_key = Ed25519PrivateKey::generate();
725        let signature = private_key.sign(b"test");
726
727        let json = serde_json::to_string(&signature).unwrap();
728        let restored: Ed25519Signature = serde_json::from_str(&json).unwrap();
729        assert_eq!(signature.to_bytes(), restored.to_bytes());
730    }
731
732    #[test]
733    fn test_private_key_clone() {
734        let private_key = Ed25519PrivateKey::generate();
735        let cloned = private_key.clone();
736        assert_eq!(private_key.to_bytes(), cloned.to_bytes());
737    }
738
739    #[test]
740    fn test_public_key_equality() {
741        let private_key = Ed25519PrivateKey::generate();
742        let pk1 = private_key.public_key();
743        let pk2 = private_key.public_key();
744        assert_eq!(pk1, pk2);
745
746        let different = Ed25519PrivateKey::generate().public_key();
747        assert_ne!(pk1, different);
748    }
749}