Skip to main content

post_quantum_web3_security/
lib.rs

1//! Post-Quantum Web3 Security
2//!
3//! Hybrid post-quantum signatures combining Ed25519 (current standard)
4//! with Falcon-512 (NIST PQC) for Solana, Aptos, and other blockchains.
5
6use falconed::{SigningKey as FalconSigningKey, VerifyingKey as FalconVerifyingKey, Signature as FalconSignature};
7use rand_core::OsRng;
8
9/// Private key size in bytes (1313)
10pub const SIGNING_KEY_SIZE: usize = 1313;
11/// Public key size in bytes (929)
12pub const VERIFYING_KEY_SIZE: usize = 929;
13/// Signature size in bytes (730)
14pub const SIGNATURE_SIZE: usize = 730;
15
16/// Hybrid private key (Ed25519 + Falcon-512)
17pub struct SigningKey(FalconSigningKey);
18
19impl SigningKey {
20    /// Generate a new hybrid key pair
21    pub fn generate() -> Self {
22        Self(FalconSigningKey::generate(&mut OsRng))
23    }
24
25    /// Create a key from fixed-size byte array
26    pub fn from_bytes(bytes: &[u8; SIGNING_KEY_SIZE]) -> Result<Self, &'static str> {
27        FalconSigningKey::from_bytes(bytes)
28            .map(Self)
29            .map_err(|_| "Invalid private key bytes")
30    }
31
32    /// Export key as byte array
33    pub fn to_bytes(&self) -> [u8; SIGNING_KEY_SIZE] {
34        self.0.to_bytes()
35    }
36
37    /// Get the corresponding public key
38    pub fn verifying_key(&self) -> VerifyingKey {
39        VerifyingKey(self.0.verifying_key().unwrap())
40    }
41
42    /// Sign a message, returns hybrid signature
43    pub fn sign(&self, message: &[u8]) -> Result<Signature, &'static str> {
44        self.0.sign(message)
45            .map(Signature)
46            .map_err(|_| "Signing failed")
47    }
48}
49
50/// Hybrid public key (Ed25519 + Falcon-512)
51pub struct VerifyingKey(FalconVerifyingKey);
52
53impl VerifyingKey {
54    /// Create a public key from fixed-size byte array
55    pub fn from_bytes(bytes: &[u8; VERIFYING_KEY_SIZE]) -> Result<Self, &'static str> {
56        FalconVerifyingKey::from_bytes(bytes)
57            .map(Self)
58            .map_err(|_| "Invalid public key bytes")
59    }
60
61    /// Export key as byte array
62    pub fn to_bytes(&self) -> [u8; VERIFYING_KEY_SIZE] {
63        self.0.to_bytes()
64    }
65
66    /// Verify a signature against a message
67    pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), &'static str> {
68        self.0.verify(message, &signature.0)
69            .map_err(|_| "Invalid signature")
70    }
71}
72
73/// Hybrid signature (Ed25519 + Falcon-512)
74pub struct Signature(FalconSignature);
75
76impl Signature {
77    /// Create a signature from fixed-size byte array
78    pub fn from_bytes(bytes: &[u8; SIGNATURE_SIZE]) -> Result<Self, &'static str> {
79        FalconSignature::from_bytes(bytes)
80            .map(Self)
81            .map_err(|_| "Invalid signature bytes")
82    }
83
84    /// Export signature as byte array
85    pub fn to_bytes(&self) -> [u8; SIGNATURE_SIZE] {
86        self.0.to_bytes()
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_constants() {
96        assert_eq!(SIGNING_KEY_SIZE, 1313);
97        assert_eq!(VERIFYING_KEY_SIZE, 929);
98        assert_eq!(SIGNATURE_SIZE, 730);
99    }
100
101    #[test]
102    fn test_sign_and_verify() {
103        let sk = SigningKey::generate();
104        let pk = sk.verifying_key();
105        let msg = b"Test message";
106        let sig = sk.sign(msg).unwrap();
107        assert!(pk.verify(msg, &sig).is_ok());
108    }
109
110    #[test]
111    fn test_wrong_signature_fails() {
112        let sk1 = SigningKey::generate();
113        let pk1 = sk1.verifying_key();
114        let sk2 = SigningKey::generate();
115        let msg = b"Secret";
116        let sig = sk2.sign(msg).unwrap();
117        assert!(pk1.verify(msg, &sig).is_err());
118    }
119}