Skip to main content

aptos_sdk/crypto/
bls12381.rs

1//! BLS12-381 signature scheme implementation.
2//!
3//! BLS signatures support aggregation, which is used for validator
4//! consensus signatures on Aptos.
5
6use crate::crypto::traits::{PublicKey, Signature, Signer, Verifier};
7use crate::error::{AptosError, AptosResult};
8use blst::BLST_ERROR;
9use blst::min_pk::{PublicKey as BlstPublicKey, SecretKey, Signature as BlstSignature};
10use rand::RngCore;
11use serde::{Deserialize, Serialize};
12use std::fmt;
13use zeroize::Zeroize;
14
15/// BLS12-381 private key length in bytes.
16pub const BLS12381_PRIVATE_KEY_LENGTH: usize = 32;
17/// BLS12-381 public key length in bytes (compressed).
18pub const BLS12381_PUBLIC_KEY_LENGTH: usize = 48;
19/// BLS12-381 signature length in bytes (compressed).
20pub const BLS12381_SIGNATURE_LENGTH: usize = 96;
21/// BLS12-381 proof of possession length in bytes.
22pub const BLS12381_POP_LENGTH: usize = 96;
23
24/// The domain separation tag for BLS signatures in Aptos.
25const DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
26/// The domain separation tag for BLS proof of possession.
27const DST_POP: &[u8] = b"BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
28
29/// A BLS12-381 private key.
30#[derive(Clone, Zeroize)]
31#[zeroize(drop)]
32pub struct Bls12381PrivateKey {
33    #[zeroize(skip)]
34    #[allow(unused)] // Field is used; lint false positive from Zeroize derive
35    inner: SecretKey,
36}
37
38impl Bls12381PrivateKey {
39    /// Generates a new random BLS12-381 private key.
40    ///
41    /// # Panics
42    ///
43    /// This function will not panic in normal operation. The internal `expect`
44    /// is a defensive check for the blst library's key generation, which only
45    /// fails if the input keying material (IKM) is less than 32 bytes. Since
46    /// we always provide exactly 32 bytes of random data, this cannot fail.
47    pub fn generate() -> Self {
48        let mut ikm = [0u8; 32];
49        rand::rngs::OsRng.fill_bytes(&mut ikm);
50        // SAFETY: key_gen only fails if IKM is < 32 bytes. We provide exactly 32.
51        let secret_key = SecretKey::key_gen(&ikm, &[])
52            .expect("internal error: BLS key generation failed with 32-byte IKM");
53        Self { inner: secret_key }
54    }
55
56    /// Creates a private key from a 32-byte seed.
57    ///
58    /// This uses the BLS key derivation function to derive a key from the seed.
59    ///
60    /// # Errors
61    ///
62    /// Returns an error if the seed is less than 32 bytes or if key derivation fails.
63    pub fn from_seed(seed: &[u8]) -> AptosResult<Self> {
64        if seed.len() < 32 {
65            return Err(AptosError::InvalidPrivateKey(
66                "seed must be at least 32 bytes".to_string(),
67            ));
68        }
69        let secret_key = SecretKey::key_gen(seed, &[])
70            .map_err(|e| AptosError::InvalidPrivateKey(format!("{e:?}")))?;
71        Ok(Self { inner: secret_key })
72    }
73
74    /// Creates a private key from raw bytes.
75    ///
76    /// # Errors
77    ///
78    /// Returns an error if the bytes length is not 32 bytes or if the key deserialization fails.
79    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
80        if bytes.len() != BLS12381_PRIVATE_KEY_LENGTH {
81            return Err(AptosError::InvalidPrivateKey(format!(
82                "expected {} bytes, got {}",
83                BLS12381_PRIVATE_KEY_LENGTH,
84                bytes.len()
85            )));
86        }
87        let secret_key = SecretKey::from_bytes(bytes)
88            .map_err(|e| AptosError::InvalidPrivateKey(format!("{e:?}")))?;
89        Ok(Self { inner: secret_key })
90    }
91
92    /// Creates a private key from a hex string.
93    ///
94    /// # Errors
95    ///
96    /// Returns an error if hex decoding fails or if the resulting bytes are invalid.
97    pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
98        let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
99        let bytes = hex::decode(hex_str)?;
100        Self::from_bytes(&bytes)
101    }
102
103    /// Returns the private key as bytes.
104    pub fn to_bytes(&self) -> [u8; BLS12381_PRIVATE_KEY_LENGTH] {
105        self.inner.to_bytes()
106    }
107
108    /// Returns the private key as a hex string.
109    pub fn to_hex(&self) -> String {
110        format!("0x{}", hex::encode(self.inner.to_bytes()))
111    }
112
113    /// Returns the corresponding public key.
114    pub fn public_key(&self) -> Bls12381PublicKey {
115        Bls12381PublicKey {
116            inner: self.inner.sk_to_pk(),
117        }
118    }
119
120    /// Signs a message and returns the signature.
121    pub fn sign(&self, message: &[u8]) -> Bls12381Signature {
122        let signature = self.inner.sign(message, DST, &[]);
123        Bls12381Signature { inner: signature }
124    }
125
126    /// Creates a proof of possession for this key pair.
127    ///
128    /// A proof of possession (`PoP`) proves ownership of the private key
129    /// and prevents rogue key attacks in aggregate signature schemes.
130    pub fn create_proof_of_possession(&self) -> Bls12381ProofOfPossession {
131        let pk = self.public_key();
132        let pk_bytes = pk.to_bytes();
133        let pop = self.inner.sign(&pk_bytes, DST_POP, &[]);
134        Bls12381ProofOfPossession { inner: pop }
135    }
136}
137
138impl Signer for Bls12381PrivateKey {
139    type Signature = Bls12381Signature;
140
141    fn sign(&self, message: &[u8]) -> Bls12381Signature {
142        Bls12381PrivateKey::sign(self, message)
143    }
144
145    fn public_key(&self) -> Bls12381PublicKey {
146        Bls12381PrivateKey::public_key(self)
147    }
148}
149
150impl fmt::Debug for Bls12381PrivateKey {
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        write!(f, "Bls12381PrivateKey([REDACTED])")
153    }
154}
155
156/// A BLS12-381 public key.
157#[derive(Clone, PartialEq, Eq)]
158pub struct Bls12381PublicKey {
159    inner: BlstPublicKey,
160}
161
162impl Bls12381PublicKey {
163    /// Creates a public key from compressed bytes (48 bytes).
164    ///
165    /// # Errors
166    ///
167    /// Returns an error if the bytes length is not 48 bytes or if the key deserialization fails.
168    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
169        if bytes.len() != BLS12381_PUBLIC_KEY_LENGTH {
170            return Err(AptosError::InvalidPublicKey(format!(
171                "expected {} bytes, got {}",
172                BLS12381_PUBLIC_KEY_LENGTH,
173                bytes.len()
174            )));
175        }
176        let public_key = BlstPublicKey::from_bytes(bytes)
177            .map_err(|e| AptosError::InvalidPublicKey(format!("{e:?}")))?;
178        Ok(Self { inner: public_key })
179    }
180
181    /// Creates a public key from a hex string.
182    ///
183    /// # Errors
184    ///
185    /// Returns an error if hex decoding fails or if the resulting bytes are invalid.
186    pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
187        let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
188        let bytes = hex::decode(hex_str)?;
189        Self::from_bytes(&bytes)
190    }
191
192    /// Returns the public key as compressed bytes (48 bytes).
193    pub fn to_bytes(&self) -> Vec<u8> {
194        self.inner.compress().to_vec()
195    }
196
197    /// Returns the public key as a hex string.
198    pub fn to_hex(&self) -> String {
199        format!("0x{}", hex::encode(self.inner.compress()))
200    }
201
202    /// Verifies a signature against a message.
203    ///
204    /// # Errors
205    ///
206    /// Returns an error if signature verification fails.
207    pub fn verify(&self, message: &[u8], signature: &Bls12381Signature) -> AptosResult<()> {
208        let result = signature
209            .inner
210            .verify(true, message, DST, &[], &self.inner, true);
211        if result == BLST_ERROR::BLST_SUCCESS {
212            Ok(())
213        } else {
214            Err(AptosError::SignatureVerificationFailed)
215        }
216    }
217}
218
219impl Bls12381PublicKey {
220    /// Aggregates multiple public keys into a single aggregated public key.
221    ///
222    /// The aggregated public key can be used to verify an aggregated signature.
223    ///
224    /// WARNING: This assumes all public keys have had their proofs-of-possession verified.
225    ///
226    /// # Errors
227    ///
228    /// Returns an error if the list of public keys is empty or if aggregation fails.
229    pub fn aggregate(public_keys: &[&Bls12381PublicKey]) -> AptosResult<Bls12381PublicKey> {
230        if public_keys.is_empty() {
231            return Err(AptosError::InvalidPublicKey(
232                "cannot aggregate empty list of public keys".to_string(),
233            ));
234        }
235        let blst_pks: Vec<&BlstPublicKey> = public_keys.iter().map(|pk| &pk.inner).collect();
236        let agg_pk = blst::min_pk::AggregatePublicKey::aggregate(&blst_pks, false)
237            .map_err(|e| AptosError::InvalidPublicKey(format!("{e:?}")))?;
238        Ok(Bls12381PublicKey {
239            inner: agg_pk.to_public_key(),
240        })
241    }
242}
243
244impl PublicKey for Bls12381PublicKey {
245    const LENGTH: usize = BLS12381_PUBLIC_KEY_LENGTH;
246
247    /// Creates a public key from compressed bytes (48 bytes).
248    ///
249    /// # Errors
250    ///
251    /// Returns an error if the bytes length is not 48 bytes or if the key deserialization fails.
252    fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
253        Bls12381PublicKey::from_bytes(bytes)
254    }
255
256    fn to_bytes(&self) -> Vec<u8> {
257        Bls12381PublicKey::to_bytes(self)
258    }
259}
260
261impl Verifier for Bls12381PublicKey {
262    type Signature = Bls12381Signature;
263
264    /// Verifies a signature against a message.
265    ///
266    /// # Errors
267    ///
268    /// Returns an error if signature verification fails.
269    fn verify(&self, message: &[u8], signature: &Bls12381Signature) -> AptosResult<()> {
270        Bls12381PublicKey::verify(self, message, signature)
271    }
272}
273
274impl fmt::Debug for Bls12381PublicKey {
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        write!(f, "Bls12381PublicKey({})", self.to_hex())
277    }
278}
279
280impl fmt::Display for Bls12381PublicKey {
281    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282        write!(f, "{}", self.to_hex())
283    }
284}
285
286impl Serialize for Bls12381PublicKey {
287    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
288    where
289        S: serde::Serializer,
290    {
291        if serializer.is_human_readable() {
292            serializer.serialize_str(&self.to_hex())
293        } else {
294            serializer.serialize_bytes(&self.to_bytes())
295        }
296    }
297}
298
299impl<'de> Deserialize<'de> for Bls12381PublicKey {
300    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
301    where
302        D: serde::Deserializer<'de>,
303    {
304        if deserializer.is_human_readable() {
305            let s = String::deserialize(deserializer)?;
306            Self::from_hex(&s).map_err(serde::de::Error::custom)
307        } else {
308            let bytes = Vec::<u8>::deserialize(deserializer)?;
309            Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
310        }
311    }
312}
313
314/// A BLS12-381 signature.
315#[derive(Clone, PartialEq, Eq)]
316pub struct Bls12381Signature {
317    inner: BlstSignature,
318}
319
320impl Bls12381Signature {
321    /// Creates a signature from compressed bytes (96 bytes).
322    ///
323    /// # Errors
324    ///
325    /// Returns an error if the bytes length is not 96 bytes or if the signature deserialization fails.
326    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
327        if bytes.len() != BLS12381_SIGNATURE_LENGTH {
328            return Err(AptosError::InvalidSignature(format!(
329                "expected {} bytes, got {}",
330                BLS12381_SIGNATURE_LENGTH,
331                bytes.len()
332            )));
333        }
334        let signature = BlstSignature::from_bytes(bytes)
335            .map_err(|e| AptosError::InvalidSignature(format!("{e:?}")))?;
336        Ok(Self { inner: signature })
337    }
338
339    /// Creates a signature from a hex string.
340    ///
341    /// # Errors
342    ///
343    /// Returns an error if hex decoding fails or if the resulting bytes are invalid.
344    pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
345        let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
346        let bytes = hex::decode(hex_str)?;
347        Self::from_bytes(&bytes)
348    }
349
350    /// Returns the signature as compressed bytes (96 bytes).
351    pub fn to_bytes(&self) -> Vec<u8> {
352        self.inner.compress().to_vec()
353    }
354
355    /// Returns the signature as a hex string.
356    pub fn to_hex(&self) -> String {
357        format!("0x{}", hex::encode(self.inner.compress()))
358    }
359}
360
361impl Bls12381Signature {
362    /// Aggregates multiple signatures into a single aggregated signature.
363    ///
364    /// The aggregated signature can be verified against an aggregated public key
365    /// for the same message, or against individual public keys for different messages.
366    ///
367    /// # Errors
368    ///
369    /// Returns an error if the list of signatures is empty or if aggregation fails.
370    pub fn aggregate(signatures: &[&Bls12381Signature]) -> AptosResult<Bls12381Signature> {
371        if signatures.is_empty() {
372            return Err(AptosError::InvalidSignature(
373                "cannot aggregate empty list of signatures".to_string(),
374            ));
375        }
376        let blst_sigs: Vec<&BlstSignature> = signatures.iter().map(|s| &s.inner).collect();
377        let agg_sig = blst::min_pk::AggregateSignature::aggregate(&blst_sigs, false)
378            .map_err(|e| AptosError::InvalidSignature(format!("{e:?}")))?;
379        Ok(Bls12381Signature {
380            inner: agg_sig.to_signature(),
381        })
382    }
383}
384
385impl Signature for Bls12381Signature {
386    type PublicKey = Bls12381PublicKey;
387    const LENGTH: usize = BLS12381_SIGNATURE_LENGTH;
388
389    /// Creates a signature from compressed bytes (96 bytes).
390    ///
391    /// # Errors
392    ///
393    /// Returns an error if the bytes length is not 96 bytes or if the signature deserialization fails.
394    fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
395        Bls12381Signature::from_bytes(bytes)
396    }
397
398    fn to_bytes(&self) -> Vec<u8> {
399        Bls12381Signature::to_bytes(self)
400    }
401}
402
403impl fmt::Debug for Bls12381Signature {
404    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405        write!(f, "Bls12381Signature({})", self.to_hex())
406    }
407}
408
409impl fmt::Display for Bls12381Signature {
410    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
411        write!(f, "{}", self.to_hex())
412    }
413}
414
415impl Serialize for Bls12381Signature {
416    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
417    where
418        S: serde::Serializer,
419    {
420        if serializer.is_human_readable() {
421            serializer.serialize_str(&self.to_hex())
422        } else {
423            serializer.serialize_bytes(&self.to_bytes())
424        }
425    }
426}
427
428impl<'de> Deserialize<'de> for Bls12381Signature {
429    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
430    where
431        D: serde::Deserializer<'de>,
432    {
433        if deserializer.is_human_readable() {
434            let s = String::deserialize(deserializer)?;
435            Self::from_hex(&s).map_err(serde::de::Error::custom)
436        } else {
437            let bytes = Vec::<u8>::deserialize(deserializer)?;
438            Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
439        }
440    }
441}
442
443/// A BLS12-381 proof of possession.
444///
445/// A proof of possession (`PoP`) proves ownership of the private key corresponding
446/// to a public key. This prevents rogue key attacks in aggregate signature schemes.
447#[derive(Clone, PartialEq, Eq)]
448pub struct Bls12381ProofOfPossession {
449    inner: BlstSignature,
450}
451
452impl Bls12381ProofOfPossession {
453    /// Creates a proof of possession from compressed bytes (96 bytes).
454    ///
455    /// # Errors
456    ///
457    /// Returns an error if the bytes length is not 96 bytes or if the proof of possession deserialization fails.
458    pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
459        if bytes.len() != BLS12381_POP_LENGTH {
460            return Err(AptosError::InvalidSignature(format!(
461                "expected {} bytes, got {}",
462                BLS12381_POP_LENGTH,
463                bytes.len()
464            )));
465        }
466        let pop = BlstSignature::from_bytes(bytes)
467            .map_err(|e| AptosError::InvalidSignature(format!("{e:?}")))?;
468        Ok(Self { inner: pop })
469    }
470
471    /// Creates a proof of possession from a hex string.
472    ///
473    /// # Errors
474    ///
475    /// Returns an error if hex decoding fails or if the resulting bytes are invalid.
476    pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
477        let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
478        let bytes = hex::decode(hex_str)?;
479        Self::from_bytes(&bytes)
480    }
481
482    /// Returns the proof of possession as compressed bytes (96 bytes).
483    pub fn to_bytes(&self) -> Vec<u8> {
484        self.inner.compress().to_vec()
485    }
486
487    /// Returns the proof of possession as a hex string.
488    pub fn to_hex(&self) -> String {
489        format!("0x{}", hex::encode(self.inner.compress()))
490    }
491
492    /// Verifies this proof of possession against a public key.
493    ///
494    /// Returns Ok(()) if the `PoP` is valid, or an error if invalid.
495    ///
496    /// # Errors
497    ///
498    /// Returns an error if proof of possession verification fails.
499    pub fn verify(&self, public_key: &Bls12381PublicKey) -> AptosResult<()> {
500        let pk_bytes = public_key.to_bytes();
501        let result = self
502            .inner
503            .verify(true, &pk_bytes, DST_POP, &[], &public_key.inner, true);
504        if result == BLST_ERROR::BLST_SUCCESS {
505            Ok(())
506        } else {
507            Err(AptosError::SignatureVerificationFailed)
508        }
509    }
510}
511
512impl fmt::Debug for Bls12381ProofOfPossession {
513    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514        write!(f, "Bls12381ProofOfPossession({})", self.to_hex())
515    }
516}
517
518impl fmt::Display for Bls12381ProofOfPossession {
519    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520        write!(f, "{}", self.to_hex())
521    }
522}
523
524#[cfg(test)]
525mod tests {
526    use super::*;
527
528    #[test]
529    fn test_generate_and_sign() {
530        let private_key = Bls12381PrivateKey::generate();
531        let message = b"hello world";
532        let signature = private_key.sign(message);
533
534        let public_key = private_key.public_key();
535        assert!(public_key.verify(message, &signature).is_ok());
536    }
537
538    #[test]
539    fn test_wrong_message_fails() {
540        let private_key = Bls12381PrivateKey::generate();
541        let message = b"hello world";
542        let wrong_message = b"hello world!";
543        let signature = private_key.sign(message);
544
545        let public_key = private_key.public_key();
546        assert!(public_key.verify(wrong_message, &signature).is_err());
547    }
548
549    #[test]
550    fn test_from_bytes_roundtrip() {
551        let private_key = Bls12381PrivateKey::generate();
552        let bytes = private_key.to_bytes();
553        let restored = Bls12381PrivateKey::from_bytes(&bytes).unwrap();
554        assert_eq!(private_key.to_bytes(), restored.to_bytes());
555    }
556
557    #[test]
558    fn test_public_key_from_bytes_roundtrip() {
559        let private_key = Bls12381PrivateKey::generate();
560        let public_key = private_key.public_key();
561        let bytes = public_key.to_bytes();
562        let restored = Bls12381PublicKey::from_bytes(&bytes).unwrap();
563        assert_eq!(public_key.to_bytes(), restored.to_bytes());
564    }
565
566    #[test]
567    fn test_signature_from_bytes_roundtrip() {
568        let private_key = Bls12381PrivateKey::generate();
569        let signature = private_key.sign(b"test");
570        let bytes = signature.to_bytes();
571        let restored = Bls12381Signature::from_bytes(&bytes).unwrap();
572        assert_eq!(signature.to_bytes(), restored.to_bytes());
573    }
574
575    #[test]
576    fn test_hex_roundtrip() {
577        let private_key = Bls12381PrivateKey::generate();
578        let hex = private_key.to_hex();
579        let restored = Bls12381PrivateKey::from_hex(&hex).unwrap();
580        assert_eq!(private_key.to_bytes(), restored.to_bytes());
581    }
582
583    #[test]
584    fn test_public_key_hex_roundtrip() {
585        let private_key = Bls12381PrivateKey::generate();
586        let public_key = private_key.public_key();
587        let hex = public_key.to_hex();
588        let restored = Bls12381PublicKey::from_hex(&hex).unwrap();
589        assert_eq!(public_key.to_bytes(), restored.to_bytes());
590    }
591
592    #[test]
593    fn test_signature_hex_roundtrip() {
594        let private_key = Bls12381PrivateKey::generate();
595        let signature = private_key.sign(b"test");
596        let hex = signature.to_hex();
597        let restored = Bls12381Signature::from_hex(&hex).unwrap();
598        assert_eq!(signature.to_bytes(), restored.to_bytes());
599    }
600
601    #[test]
602    fn test_public_key_length() {
603        assert_eq!(Bls12381PublicKey::LENGTH, BLS12381_PUBLIC_KEY_LENGTH);
604    }
605
606    #[test]
607    fn test_signature_length() {
608        assert_eq!(Bls12381Signature::LENGTH, BLS12381_SIGNATURE_LENGTH);
609    }
610
611    #[test]
612    fn test_invalid_private_key_bytes() {
613        let bytes = vec![0u8; 16]; // Wrong length
614        let result = Bls12381PrivateKey::from_bytes(&bytes);
615        assert!(result.is_err());
616    }
617
618    #[test]
619    fn test_invalid_public_key_bytes() {
620        let bytes = vec![0u8; 16]; // Wrong length
621        let result = Bls12381PublicKey::from_bytes(&bytes);
622        assert!(result.is_err());
623    }
624
625    #[test]
626    fn test_invalid_signature_bytes() {
627        let bytes = vec![0u8; 16]; // Wrong length
628        let result = Bls12381Signature::from_bytes(&bytes);
629        assert!(result.is_err());
630    }
631
632    #[test]
633    fn test_json_serialization_public_key() {
634        let private_key = Bls12381PrivateKey::generate();
635        let public_key = private_key.public_key();
636        let json = serde_json::to_string(&public_key).unwrap();
637        let restored: Bls12381PublicKey = serde_json::from_str(&json).unwrap();
638        assert_eq!(public_key.to_bytes(), restored.to_bytes());
639    }
640
641    #[test]
642    fn test_json_serialization_signature() {
643        let private_key = Bls12381PrivateKey::generate();
644        let signature = private_key.sign(b"test");
645        let json = serde_json::to_string(&signature).unwrap();
646        let restored: Bls12381Signature = serde_json::from_str(&json).unwrap();
647        assert_eq!(signature.to_bytes(), restored.to_bytes());
648    }
649
650    #[test]
651    fn test_proof_of_possession() {
652        let private_key = Bls12381PrivateKey::generate();
653        let public_key = private_key.public_key();
654        let pop = private_key.create_proof_of_possession();
655
656        // PoP should verify against the public key
657        assert!(pop.verify(&public_key).is_ok());
658
659        // PoP should fail against a different public key
660        let other_key = Bls12381PrivateKey::generate().public_key();
661        assert!(pop.verify(&other_key).is_err());
662    }
663
664    #[test]
665    fn test_pop_bytes_roundtrip() {
666        let private_key = Bls12381PrivateKey::generate();
667        let pop = private_key.create_proof_of_possession();
668
669        let bytes = pop.to_bytes();
670        assert_eq!(bytes.len(), BLS12381_POP_LENGTH);
671
672        let restored = Bls12381ProofOfPossession::from_bytes(&bytes).unwrap();
673        assert_eq!(pop.to_bytes(), restored.to_bytes());
674    }
675
676    #[test]
677    fn test_pop_hex_roundtrip() {
678        let private_key = Bls12381PrivateKey::generate();
679        let pop = private_key.create_proof_of_possession();
680
681        let hex = pop.to_hex();
682        assert!(hex.starts_with("0x"));
683
684        let restored = Bls12381ProofOfPossession::from_hex(&hex).unwrap();
685        assert_eq!(pop.to_bytes(), restored.to_bytes());
686    }
687
688    #[test]
689    fn test_pop_invalid_bytes_length() {
690        let bytes = vec![0u8; 32]; // Wrong length
691        let result = Bls12381ProofOfPossession::from_bytes(&bytes);
692        assert!(result.is_err());
693    }
694
695    #[test]
696    fn test_aggregate_public_keys() {
697        let pk1 = Bls12381PrivateKey::generate().public_key();
698        let pk2 = Bls12381PrivateKey::generate().public_key();
699        let pk3 = Bls12381PrivateKey::generate().public_key();
700
701        let agg = Bls12381PublicKey::aggregate(&[&pk1, &pk2, &pk3]).unwrap();
702        assert!(!agg.to_bytes().is_empty());
703    }
704
705    #[test]
706    fn test_aggregate_public_keys_empty() {
707        let result = Bls12381PublicKey::aggregate(&[]);
708        assert!(result.is_err());
709    }
710
711    #[test]
712    fn test_aggregate_signatures() {
713        let pk1 = Bls12381PrivateKey::generate();
714        let pk2 = Bls12381PrivateKey::generate();
715
716        let message = b"aggregate test";
717        let sig1 = pk1.sign(message);
718        let sig2 = pk2.sign(message);
719
720        let agg_sig = Bls12381Signature::aggregate(&[&sig1, &sig2]).unwrap();
721        assert!(!agg_sig.to_bytes().is_empty());
722    }
723
724    #[test]
725    fn test_aggregate_signatures_empty() {
726        let result = Bls12381Signature::aggregate(&[]);
727        assert!(result.is_err());
728    }
729
730    #[test]
731    fn test_from_seed() {
732        let seed = [42u8; 32];
733        let pk1 = Bls12381PrivateKey::from_seed(&seed).unwrap();
734        let pk2 = Bls12381PrivateKey::from_seed(&seed).unwrap();
735
736        // Same seed should produce same key
737        assert_eq!(pk1.to_bytes(), pk2.to_bytes());
738    }
739
740    #[test]
741    fn test_from_seed_too_short() {
742        let seed = [42u8; 16]; // Too short
743        let result = Bls12381PrivateKey::from_seed(&seed);
744        assert!(result.is_err());
745    }
746
747    #[test]
748    fn test_private_key_debug() {
749        let private_key = Bls12381PrivateKey::generate();
750        let debug = format!("{private_key:?}");
751        assert!(debug.contains("REDACTED"));
752        assert!(!debug.contains(&private_key.to_hex()));
753    }
754
755    #[test]
756    fn test_public_key_debug() {
757        let private_key = Bls12381PrivateKey::generate();
758        let public_key = private_key.public_key();
759        let debug = format!("{public_key:?}");
760        assert!(debug.contains("Bls12381PublicKey"));
761    }
762
763    #[test]
764    fn test_public_key_display() {
765        let private_key = Bls12381PrivateKey::generate();
766        let public_key = private_key.public_key();
767        let display = format!("{public_key}");
768        assert!(display.starts_with("0x"));
769    }
770
771    #[test]
772    fn test_signature_debug() {
773        let private_key = Bls12381PrivateKey::generate();
774        let signature = private_key.sign(b"test");
775        let debug = format!("{signature:?}");
776        assert!(debug.contains("Bls12381Signature"));
777    }
778
779    #[test]
780    fn test_signature_display() {
781        let private_key = Bls12381PrivateKey::generate();
782        let signature = private_key.sign(b"test");
783        let display = format!("{signature}");
784        assert!(display.starts_with("0x"));
785    }
786
787    #[test]
788    fn test_pop_debug() {
789        let private_key = Bls12381PrivateKey::generate();
790        let pop = private_key.create_proof_of_possession();
791        let debug = format!("{pop:?}");
792        assert!(debug.contains("Bls12381ProofOfPossession"));
793    }
794
795    #[test]
796    fn test_pop_display() {
797        let private_key = Bls12381PrivateKey::generate();
798        let pop = private_key.create_proof_of_possession();
799        let display = format!("{pop}");
800        assert!(display.starts_with("0x"));
801    }
802
803    #[test]
804    fn test_signer_trait() {
805        use crate::crypto::traits::Signer;
806
807        let private_key = Bls12381PrivateKey::generate();
808        let message = b"trait test";
809
810        let signature = Signer::sign(&private_key, message);
811        let public_key = Signer::public_key(&private_key);
812
813        assert!(public_key.verify(message, &signature).is_ok());
814    }
815
816    #[test]
817    fn test_verifier_trait() {
818        use crate::crypto::traits::Verifier;
819
820        let private_key = Bls12381PrivateKey::generate();
821        let public_key = private_key.public_key();
822        let message = b"verifier test";
823        let signature = private_key.sign(message);
824
825        assert!(Verifier::verify(&public_key, message, &signature).is_ok());
826    }
827
828    #[test]
829    fn test_public_key_trait() {
830        use crate::crypto::traits::PublicKey;
831
832        let private_key = Bls12381PrivateKey::generate();
833        let public_key = private_key.public_key();
834        let bytes = PublicKey::to_bytes(&public_key);
835        let restored = Bls12381PublicKey::from_bytes(&bytes).unwrap();
836        assert_eq!(public_key, restored);
837    }
838
839    #[test]
840    fn test_signature_trait() {
841        use crate::crypto::traits::Signature;
842
843        let private_key = Bls12381PrivateKey::generate();
844        let signature = private_key.sign(b"test");
845        let bytes = Signature::to_bytes(&signature);
846        let restored = Bls12381Signature::from_bytes(&bytes).unwrap();
847        assert_eq!(signature, restored);
848    }
849}