chie_crypto/
sphincs.rs

1//! Stateless Hash-Based Signatures with SPHINCS+.
2//!
3//! This module implements SPHINCS+, a stateless hash-based post-quantum
4//! signature scheme with minimal security assumptions. Unlike lattice-based
5//! schemes, SPHINCS+ only relies on the security of hash functions.
6//!
7//! # Security Levels
8//! - SPHINCS+-SHAKE-128f: Fast variant, security level 1 (AES-128 equivalent)
9//! - SPHINCS+-SHAKE-192f: Fast variant, security level 3 (AES-192 equivalent)
10//! - SPHINCS+-SHAKE-256f: Fast variant, security level 5 (AES-256 equivalent) - **Recommended**
11//!
12//! # Characteristics
13//! - **Minimal assumptions**: Security relies only on hash functions
14//! - **No quantum vulnerability**: Secure against quantum attacks
15//! - **Larger signatures**: Trade-off for stronger security guarantees
16//! - **Stateless**: No state management required (unlike XMSS)
17//!
18//! # Use Cases for CHIE Protocol
19//! - Long-term archival signatures (decades of security)
20//! - Maximum security for critical content
21//! - Conservative post-quantum approach
22//! - When signature size is less critical than security
23//!
24//! # Example
25//! ```
26//! use chie_crypto::sphincs::*;
27//!
28//! // Generate a keypair
29//! let (pk, sk) = SphincsSHAKE256f::keypair();
30//!
31//! // Sign a message
32//! let message = b"Critical archival content";
33//! let signature = SphincsSHAKE256f::sign(message, &sk);
34//!
35//! // Verify the signature
36//! assert!(SphincsSHAKE256f::verify(message, &signature, &pk).is_ok());
37//!
38//! // Invalid message should fail verification
39//! let wrong_message = b"Different content";
40//! assert!(SphincsSHAKE256f::verify(wrong_message, &signature, &pk).is_err());
41//! ```
42
43use pqcrypto_sphincsplus::{
44    sphincsshake128fsimple, sphincsshake192fsimple, sphincsshake256fsimple,
45};
46use pqcrypto_traits::sign::{DetachedSignature as _, PublicKey as _, SecretKey as _};
47use serde::{Deserialize, Serialize};
48use zeroize::Zeroizing;
49
50/// Errors that can occur during SPHINCS+ operations.
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub enum SphincsError {
53    /// Invalid public key length
54    InvalidPublicKey,
55    /// Invalid secret key length
56    InvalidSecretKey,
57    /// Invalid signature length
58    InvalidSignature,
59    /// Signature verification failed
60    VerificationFailed,
61    /// Signing failed
62    SigningFailed,
63    /// Serialization/deserialization error
64    SerializationError,
65}
66
67impl std::fmt::Display for SphincsError {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        match self {
70            SphincsError::InvalidPublicKey => write!(f, "Invalid public key length"),
71            SphincsError::InvalidSecretKey => write!(f, "Invalid secret key length"),
72            SphincsError::InvalidSignature => write!(f, "Invalid signature length"),
73            SphincsError::VerificationFailed => write!(f, "Signature verification failed"),
74            SphincsError::SigningFailed => write!(f, "Signing failed"),
75            SphincsError::SerializationError => write!(f, "Serialization/deserialization error"),
76        }
77    }
78}
79
80impl std::error::Error for SphincsError {}
81
82/// Result type for SPHINCS+ operations.
83pub type SphincsResult<T> = Result<T, SphincsError>;
84
85/// SPHINCS+-SHAKE-128f public key (security level 1).
86#[derive(Clone, Serialize, Deserialize)]
87pub struct SphincsSHAKE128fPublicKey(Vec<u8>);
88
89/// SPHINCS+-SHAKE-128f secret key (security level 1).
90#[derive(Clone)]
91pub struct SphincsSHAKE128fSecretKey(Zeroizing<Vec<u8>>);
92
93impl Serialize for SphincsSHAKE128fSecretKey {
94    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
95    where
96        S: serde::Serializer,
97    {
98        self.0.as_slice().serialize(serializer)
99    }
100}
101
102impl<'de> Deserialize<'de> for SphincsSHAKE128fSecretKey {
103    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
104    where
105        D: serde::Deserializer<'de>,
106    {
107        let bytes = Vec::<u8>::deserialize(deserializer)?;
108        Ok(SphincsSHAKE128fSecretKey(Zeroizing::new(bytes)))
109    }
110}
111
112/// SPHINCS+-SHAKE-128f signature.
113#[derive(Clone, Serialize, Deserialize)]
114pub struct SphincsSHAKE128fSignature(Vec<u8>);
115
116/// SPHINCS+-SHAKE-192f public key (security level 3).
117#[derive(Clone, Serialize, Deserialize)]
118pub struct SphincsSHAKE192fPublicKey(Vec<u8>);
119
120/// SPHINCS+-SHAKE-192f secret key (security level 3).
121#[derive(Clone)]
122pub struct SphincsSHAKE192fSecretKey(Zeroizing<Vec<u8>>);
123
124impl Serialize for SphincsSHAKE192fSecretKey {
125    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
126    where
127        S: serde::Serializer,
128    {
129        self.0.as_slice().serialize(serializer)
130    }
131}
132
133impl<'de> Deserialize<'de> for SphincsSHAKE192fSecretKey {
134    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
135    where
136        D: serde::Deserializer<'de>,
137    {
138        let bytes = Vec::<u8>::deserialize(deserializer)?;
139        Ok(SphincsSHAKE192fSecretKey(Zeroizing::new(bytes)))
140    }
141}
142
143/// SPHINCS+-SHAKE-192f signature.
144#[derive(Clone, Serialize, Deserialize)]
145pub struct SphincsSHAKE192fSignature(Vec<u8>);
146
147/// SPHINCS+-SHAKE-256f public key (security level 5) - Recommended.
148#[derive(Clone, Serialize, Deserialize)]
149pub struct SphincsSHAKE256fPublicKey(Vec<u8>);
150
151/// SPHINCS+-SHAKE-256f secret key (security level 5) - Recommended.
152#[derive(Clone)]
153pub struct SphincsSHAKE256fSecretKey(Zeroizing<Vec<u8>>);
154
155impl Serialize for SphincsSHAKE256fSecretKey {
156    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
157    where
158        S: serde::Serializer,
159    {
160        self.0.as_slice().serialize(serializer)
161    }
162}
163
164impl<'de> Deserialize<'de> for SphincsSHAKE256fSecretKey {
165    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
166    where
167        D: serde::Deserializer<'de>,
168    {
169        let bytes = Vec::<u8>::deserialize(deserializer)?;
170        Ok(SphincsSHAKE256fSecretKey(Zeroizing::new(bytes)))
171    }
172}
173
174/// SPHINCS+-SHAKE-256f signature.
175#[derive(Clone, Serialize, Deserialize)]
176pub struct SphincsSHAKE256fSignature(Vec<u8>);
177
178/// SPHINCS+-SHAKE-128f - Fast variant, security level 1 (AES-128 equivalent).
179pub struct SphincsSHAKE128f;
180
181impl SphincsSHAKE128f {
182    /// Generate a new keypair.
183    pub fn keypair() -> (SphincsSHAKE128fPublicKey, SphincsSHAKE128fSecretKey) {
184        let (pk, sk) = sphincsshake128fsimple::keypair();
185        (
186            SphincsSHAKE128fPublicKey(pk.as_bytes().to_vec()),
187            SphincsSHAKE128fSecretKey(Zeroizing::new(sk.as_bytes().to_vec())),
188        )
189    }
190
191    /// Sign a message.
192    pub fn sign(message: &[u8], sk: &SphincsSHAKE128fSecretKey) -> SphincsSHAKE128fSignature {
193        let secret_key = sphincsshake128fsimple::SecretKey::from_bytes(&sk.0).unwrap();
194        let sig = sphincsshake128fsimple::detached_sign(message, &secret_key);
195        SphincsSHAKE128fSignature(sig.as_bytes().to_vec())
196    }
197
198    /// Verify a signature.
199    pub fn verify(
200        message: &[u8],
201        signature: &SphincsSHAKE128fSignature,
202        pk: &SphincsSHAKE128fPublicKey,
203    ) -> SphincsResult<()> {
204        let public_key = sphincsshake128fsimple::PublicKey::from_bytes(&pk.0)
205            .map_err(|_| SphincsError::InvalidPublicKey)?;
206        let sig = sphincsshake128fsimple::DetachedSignature::from_bytes(&signature.0)
207            .map_err(|_| SphincsError::InvalidSignature)?;
208
209        sphincsshake128fsimple::verify_detached_signature(&sig, message, &public_key)
210            .map_err(|_| SphincsError::VerificationFailed)
211    }
212}
213
214/// SPHINCS+-SHAKE-192f - Fast variant, security level 3 (AES-192 equivalent).
215pub struct SphincsSHAKE192f;
216
217impl SphincsSHAKE192f {
218    /// Generate a new keypair.
219    pub fn keypair() -> (SphincsSHAKE192fPublicKey, SphincsSHAKE192fSecretKey) {
220        let (pk, sk) = sphincsshake192fsimple::keypair();
221        (
222            SphincsSHAKE192fPublicKey(pk.as_bytes().to_vec()),
223            SphincsSHAKE192fSecretKey(Zeroizing::new(sk.as_bytes().to_vec())),
224        )
225    }
226
227    /// Sign a message.
228    pub fn sign(message: &[u8], sk: &SphincsSHAKE192fSecretKey) -> SphincsSHAKE192fSignature {
229        let secret_key = sphincsshake192fsimple::SecretKey::from_bytes(&sk.0).unwrap();
230        let sig = sphincsshake192fsimple::detached_sign(message, &secret_key);
231        SphincsSHAKE192fSignature(sig.as_bytes().to_vec())
232    }
233
234    /// Verify a signature.
235    pub fn verify(
236        message: &[u8],
237        signature: &SphincsSHAKE192fSignature,
238        pk: &SphincsSHAKE192fPublicKey,
239    ) -> SphincsResult<()> {
240        let public_key = sphincsshake192fsimple::PublicKey::from_bytes(&pk.0)
241            .map_err(|_| SphincsError::InvalidPublicKey)?;
242        let sig = sphincsshake192fsimple::DetachedSignature::from_bytes(&signature.0)
243            .map_err(|_| SphincsError::InvalidSignature)?;
244
245        sphincsshake192fsimple::verify_detached_signature(&sig, message, &public_key)
246            .map_err(|_| SphincsError::VerificationFailed)
247    }
248}
249
250/// SPHINCS+-SHAKE-256f - Fast variant, security level 5 (AES-256 equivalent) - **Recommended**.
251pub struct SphincsSHAKE256f;
252
253impl SphincsSHAKE256f {
254    /// Generate a new keypair.
255    pub fn keypair() -> (SphincsSHAKE256fPublicKey, SphincsSHAKE256fSecretKey) {
256        let (pk, sk) = sphincsshake256fsimple::keypair();
257        (
258            SphincsSHAKE256fPublicKey(pk.as_bytes().to_vec()),
259            SphincsSHAKE256fSecretKey(Zeroizing::new(sk.as_bytes().to_vec())),
260        )
261    }
262
263    /// Sign a message.
264    pub fn sign(message: &[u8], sk: &SphincsSHAKE256fSecretKey) -> SphincsSHAKE256fSignature {
265        let secret_key = sphincsshake256fsimple::SecretKey::from_bytes(&sk.0).unwrap();
266        let sig = sphincsshake256fsimple::detached_sign(message, &secret_key);
267        SphincsSHAKE256fSignature(sig.as_bytes().to_vec())
268    }
269
270    /// Verify a signature.
271    pub fn verify(
272        message: &[u8],
273        signature: &SphincsSHAKE256fSignature,
274        pk: &SphincsSHAKE256fPublicKey,
275    ) -> SphincsResult<()> {
276        let public_key = sphincsshake256fsimple::PublicKey::from_bytes(&pk.0)
277            .map_err(|_| SphincsError::InvalidPublicKey)?;
278        let sig = sphincsshake256fsimple::DetachedSignature::from_bytes(&signature.0)
279            .map_err(|_| SphincsError::InvalidSignature)?;
280
281        sphincsshake256fsimple::verify_detached_signature(&sig, message, &public_key)
282            .map_err(|_| SphincsError::VerificationFailed)
283    }
284}
285
286#[cfg(test)]
287mod tests {
288    use super::*;
289
290    #[test]
291    fn test_sphincs128_keypair_generation() {
292        let (_pk, _sk) = SphincsSHAKE128f::keypair();
293        // Just verify it doesn't panic
294    }
295
296    #[test]
297    fn test_sphincs128_sign_verify() {
298        let (pk, sk) = SphincsSHAKE128f::keypair();
299        let message = b"Test message";
300
301        let signature = SphincsSHAKE128f::sign(message, &sk);
302        assert!(SphincsSHAKE128f::verify(message, &signature, &pk).is_ok());
303    }
304
305    #[test]
306    fn test_sphincs128_wrong_message_fails() {
307        let (pk, sk) = SphincsSHAKE128f::keypair();
308        let message = b"Original message";
309        let wrong_message = b"Wrong message";
310
311        let signature = SphincsSHAKE128f::sign(message, &sk);
312        assert!(SphincsSHAKE128f::verify(wrong_message, &signature, &pk).is_err());
313    }
314
315    #[test]
316    fn test_sphincs128_wrong_public_key_fails() {
317        let (_pk1, sk1) = SphincsSHAKE128f::keypair();
318        let (pk2, _sk2) = SphincsSHAKE128f::keypair();
319        let message = b"Test message";
320
321        let signature = SphincsSHAKE128f::sign(message, &sk1);
322        assert!(SphincsSHAKE128f::verify(message, &signature, &pk2).is_err());
323    }
324
325    #[test]
326    fn test_sphincs192_keypair_generation() {
327        let (_pk, _sk) = SphincsSHAKE192f::keypair();
328        // Just verify it doesn't panic
329    }
330
331    #[test]
332    fn test_sphincs192_sign_verify() {
333        let (pk, sk) = SphincsSHAKE192f::keypair();
334        let message = b"Test message";
335
336        let signature = SphincsSHAKE192f::sign(message, &sk);
337        assert!(SphincsSHAKE192f::verify(message, &signature, &pk).is_ok());
338    }
339
340    #[test]
341    fn test_sphincs256_keypair_generation() {
342        let (_pk, _sk) = SphincsSHAKE256f::keypair();
343        // Just verify it doesn't panic
344    }
345
346    #[test]
347    fn test_sphincs256_sign_verify() {
348        let (pk, sk) = SphincsSHAKE256f::keypair();
349        let message = b"Test message";
350
351        let signature = SphincsSHAKE256f::sign(message, &sk);
352        assert!(SphincsSHAKE256f::verify(message, &signature, &pk).is_ok());
353    }
354
355    #[test]
356    fn test_sphincs256_wrong_message_fails() {
357        let (pk, sk) = SphincsSHAKE256f::keypair();
358        let message = b"Original message";
359        let wrong_message = b"Wrong message";
360
361        let signature = SphincsSHAKE256f::sign(message, &sk);
362        assert!(SphincsSHAKE256f::verify(wrong_message, &signature, &pk).is_err());
363    }
364
365    #[test]
366    fn test_sphincs256_wrong_public_key_fails() {
367        let (_pk1, sk1) = SphincsSHAKE256f::keypair();
368        let (pk2, _sk2) = SphincsSHAKE256f::keypair();
369        let message = b"Test message";
370
371        let signature = SphincsSHAKE256f::sign(message, &sk1);
372        assert!(SphincsSHAKE256f::verify(message, &signature, &pk2).is_err());
373    }
374
375    #[test]
376    fn test_sphincs256_serialization() {
377        let (pk, sk) = SphincsSHAKE256f::keypair();
378
379        let pk_serialized = crate::codec::encode(&pk).unwrap();
380        let sk_serialized = crate::codec::encode(&sk).unwrap();
381
382        let pk_deserialized: SphincsSHAKE256fPublicKey =
383            crate::codec::decode(&pk_serialized).unwrap();
384        let sk_deserialized: SphincsSHAKE256fSecretKey =
385            crate::codec::decode(&sk_serialized).unwrap();
386
387        let message = b"Test message";
388        let signature = SphincsSHAKE256f::sign(message, &sk_deserialized);
389        assert!(SphincsSHAKE256f::verify(message, &signature, &pk_deserialized).is_ok());
390    }
391
392    #[test]
393    fn test_sphincs256_signature_serialization() {
394        let (pk, sk) = SphincsSHAKE256f::keypair();
395        let message = b"Test message";
396        let signature = SphincsSHAKE256f::sign(message, &sk);
397
398        let sig_serialized = crate::codec::encode(&signature).unwrap();
399        let sig_deserialized: SphincsSHAKE256fSignature =
400            crate::codec::decode(&sig_serialized).unwrap();
401
402        assert!(SphincsSHAKE256f::verify(message, &sig_deserialized, &pk).is_ok());
403    }
404
405    #[test]
406    fn test_sphincs_all_levels_independent() {
407        let (pk128, sk128) = SphincsSHAKE128f::keypair();
408        let (pk192, sk192) = SphincsSHAKE192f::keypair();
409        let (pk256, sk256) = SphincsSHAKE256f::keypair();
410
411        let message = b"Test message";
412
413        let sig128 = SphincsSHAKE128f::sign(message, &sk128);
414        let sig192 = SphincsSHAKE192f::sign(message, &sk192);
415        let sig256 = SphincsSHAKE256f::sign(message, &sk256);
416
417        assert!(SphincsSHAKE128f::verify(message, &sig128, &pk128).is_ok());
418        assert!(SphincsSHAKE192f::verify(message, &sig192, &pk192).is_ok());
419        assert!(SphincsSHAKE256f::verify(message, &sig256, &pk256).is_ok());
420    }
421
422    #[test]
423    fn test_sphincs256_empty_message() {
424        let (pk, sk) = SphincsSHAKE256f::keypair();
425        let message = b"";
426
427        let signature = SphincsSHAKE256f::sign(message, &sk);
428        assert!(SphincsSHAKE256f::verify(message, &signature, &pk).is_ok());
429    }
430
431    #[test]
432    fn test_sphincs256_large_message() {
433        let (pk, sk) = SphincsSHAKE256f::keypair();
434        let message = vec![42u8; 10_000];
435
436        let signature = SphincsSHAKE256f::sign(&message, &sk);
437        assert!(SphincsSHAKE256f::verify(&message, &signature, &pk).is_ok());
438    }
439
440    #[test]
441    fn test_sphincs256_multiple_signatures() {
442        let (pk, sk) = SphincsSHAKE256f::keypair();
443        let message = b"Test message";
444
445        let sig1 = SphincsSHAKE256f::sign(message, &sk);
446        let sig2 = SphincsSHAKE256f::sign(message, &sk);
447
448        // SPHINCS+ may use randomization, so signatures might differ
449        // But both should be valid
450        assert!(SphincsSHAKE256f::verify(message, &sig1, &pk).is_ok());
451        assert!(SphincsSHAKE256f::verify(message, &sig2, &pk).is_ok());
452    }
453}