chie_crypto/
kyber.rs

1//! Post-Quantum Key Encapsulation with CRYSTALS-Kyber.
2//!
3//! This module implements CRYSTALS-Kyber, a NIST-standardized post-quantum
4//! Key Encapsulation Mechanism (KEM) designed to be secure against attacks
5//! by quantum computers.
6//!
7//! # Security Levels
8//! - Kyber512: Security level 1 (AES-128 equivalent)
9//! - Kyber768: Security level 3 (AES-192 equivalent) - **Recommended**
10//! - Kyber1024: Security level 5 (AES-256 equivalent)
11//!
12//! # Use Cases for CHIE Protocol
13//! - Future-proof key exchange resistant to quantum attacks
14//! - Hybrid encryption with classical algorithms during transition
15//! - Long-term secure communication channels
16//! - Drop-in replacement for X25519 key exchange
17//!
18//! # Example
19//! ```
20//! use chie_crypto::kyber::*;
21//!
22//! // Alice generates a keypair
23//! let (alice_pk, alice_sk) = Kyber768::keypair();
24//!
25//! // Bob encapsulates a shared secret to Alice's public key
26//! let (ciphertext, bob_shared_secret) = Kyber768::encapsulate(&alice_pk).unwrap();
27//!
28//! // Alice decapsulates to recover the same shared secret
29//! let alice_shared_secret = Kyber768::decapsulate(&ciphertext, &alice_sk).unwrap();
30//!
31//! // Both parties now have the same shared secret
32//! assert_eq!(bob_shared_secret.as_bytes(), alice_shared_secret.as_bytes());
33//! ```
34
35use pqcrypto_kyber::{kyber512, kyber768, kyber1024};
36use pqcrypto_traits::kem::{Ciphertext as _, PublicKey as _, SecretKey as _, SharedSecret as _};
37use serde::{Deserialize, Serialize};
38use zeroize::Zeroizing;
39
40/// Errors that can occur during Kyber operations.
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub enum KyberError {
43    /// Invalid public key length
44    InvalidPublicKey,
45    /// Invalid secret key length
46    InvalidSecretKey,
47    /// Invalid ciphertext length
48    InvalidCiphertext,
49    /// Encapsulation failed
50    EncapsulationFailed,
51    /// Decapsulation failed
52    DecapsulationFailed,
53    /// Serialization/deserialization error
54    SerializationError,
55}
56
57impl std::fmt::Display for KyberError {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        match self {
60            KyberError::InvalidPublicKey => write!(f, "Invalid public key length"),
61            KyberError::InvalidSecretKey => write!(f, "Invalid secret key length"),
62            KyberError::InvalidCiphertext => write!(f, "Invalid ciphertext length"),
63            KyberError::EncapsulationFailed => write!(f, "Encapsulation failed"),
64            KyberError::DecapsulationFailed => write!(f, "Decapsulation failed"),
65            KyberError::SerializationError => write!(f, "Serialization/deserialization error"),
66        }
67    }
68}
69
70impl std::error::Error for KyberError {}
71
72/// Result type for Kyber operations.
73pub type KyberResult<T> = Result<T, KyberError>;
74
75/// Kyber512 public key (security level 1).
76#[derive(Clone, Serialize, Deserialize)]
77pub struct Kyber512PublicKey(Vec<u8>);
78
79/// Kyber512 secret key (security level 1).
80#[derive(Clone)]
81pub struct Kyber512SecretKey(Zeroizing<Vec<u8>>);
82
83impl Serialize for Kyber512SecretKey {
84    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85    where
86        S: serde::Serializer,
87    {
88        self.0.as_slice().serialize(serializer)
89    }
90}
91
92impl<'de> Deserialize<'de> for Kyber512SecretKey {
93    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
94    where
95        D: serde::Deserializer<'de>,
96    {
97        let bytes = Vec::<u8>::deserialize(deserializer)?;
98        Ok(Kyber512SecretKey(Zeroizing::new(bytes)))
99    }
100}
101
102/// Kyber512 ciphertext.
103#[derive(Clone, Serialize, Deserialize)]
104pub struct Kyber512Ciphertext(Vec<u8>);
105
106/// Kyber512 shared secret.
107#[derive(Clone)]
108pub struct Kyber512SharedSecret(Zeroizing<Vec<u8>>);
109
110/// Kyber768 public key (security level 3) - Recommended.
111#[derive(Clone, Serialize, Deserialize)]
112pub struct Kyber768PublicKey(Vec<u8>);
113
114/// Kyber768 secret key (security level 3) - Recommended.
115#[derive(Clone)]
116pub struct Kyber768SecretKey(Zeroizing<Vec<u8>>);
117
118impl Serialize for Kyber768SecretKey {
119    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
120    where
121        S: serde::Serializer,
122    {
123        self.0.as_slice().serialize(serializer)
124    }
125}
126
127impl<'de> Deserialize<'de> for Kyber768SecretKey {
128    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
129    where
130        D: serde::Deserializer<'de>,
131    {
132        let bytes = Vec::<u8>::deserialize(deserializer)?;
133        Ok(Kyber768SecretKey(Zeroizing::new(bytes)))
134    }
135}
136
137/// Kyber768 ciphertext.
138#[derive(Clone, Serialize, Deserialize)]
139pub struct Kyber768Ciphertext(Vec<u8>);
140
141/// Kyber768 shared secret.
142#[derive(Clone)]
143pub struct Kyber768SharedSecret(Zeroizing<Vec<u8>>);
144
145/// Kyber1024 public key (security level 5).
146#[derive(Clone, Serialize, Deserialize)]
147pub struct Kyber1024PublicKey(Vec<u8>);
148
149/// Kyber1024 secret key (security level 5).
150#[derive(Clone)]
151pub struct Kyber1024SecretKey(Zeroizing<Vec<u8>>);
152
153impl Serialize for Kyber1024SecretKey {
154    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155    where
156        S: serde::Serializer,
157    {
158        self.0.as_slice().serialize(serializer)
159    }
160}
161
162impl<'de> Deserialize<'de> for Kyber1024SecretKey {
163    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
164    where
165        D: serde::Deserializer<'de>,
166    {
167        let bytes = Vec::<u8>::deserialize(deserializer)?;
168        Ok(Kyber1024SecretKey(Zeroizing::new(bytes)))
169    }
170}
171
172/// Kyber1024 ciphertext.
173#[derive(Clone, Serialize, Deserialize)]
174pub struct Kyber1024Ciphertext(Vec<u8>);
175
176/// Kyber1024 shared secret.
177#[derive(Clone)]
178pub struct Kyber1024SharedSecret(Zeroizing<Vec<u8>>);
179
180/// Kyber512 - Security level 1 (AES-128 equivalent).
181pub struct Kyber512;
182
183impl Kyber512 {
184    /// Generate a new keypair.
185    pub fn keypair() -> (Kyber512PublicKey, Kyber512SecretKey) {
186        let (pk, sk) = kyber512::keypair();
187        (
188            Kyber512PublicKey(pk.as_bytes().to_vec()),
189            Kyber512SecretKey(Zeroizing::new(sk.as_bytes().to_vec())),
190        )
191    }
192
193    /// Encapsulate a shared secret to a public key.
194    pub fn encapsulate(
195        pk: &Kyber512PublicKey,
196    ) -> KyberResult<(Kyber512Ciphertext, Kyber512SharedSecret)> {
197        let public_key =
198            kyber512::PublicKey::from_bytes(&pk.0).map_err(|_| KyberError::InvalidPublicKey)?;
199
200        let (ss, ct) = kyber512::encapsulate(&public_key);
201
202        Ok((
203            Kyber512Ciphertext(ct.as_bytes().to_vec()),
204            Kyber512SharedSecret(Zeroizing::new(ss.as_bytes().to_vec())),
205        ))
206    }
207
208    /// Decapsulate a ciphertext to recover the shared secret.
209    pub fn decapsulate(
210        ct: &Kyber512Ciphertext,
211        sk: &Kyber512SecretKey,
212    ) -> KyberResult<Kyber512SharedSecret> {
213        let secret_key =
214            kyber512::SecretKey::from_bytes(&sk.0).map_err(|_| KyberError::InvalidSecretKey)?;
215        let ciphertext =
216            kyber512::Ciphertext::from_bytes(&ct.0).map_err(|_| KyberError::InvalidCiphertext)?;
217
218        let ss = kyber512::decapsulate(&ciphertext, &secret_key);
219
220        Ok(Kyber512SharedSecret(Zeroizing::new(ss.as_bytes().to_vec())))
221    }
222}
223
224/// Kyber768 - Security level 3 (AES-192 equivalent) - **Recommended**.
225pub struct Kyber768;
226
227impl Kyber768 {
228    /// Generate a new keypair.
229    pub fn keypair() -> (Kyber768PublicKey, Kyber768SecretKey) {
230        let (pk, sk) = kyber768::keypair();
231        (
232            Kyber768PublicKey(pk.as_bytes().to_vec()),
233            Kyber768SecretKey(Zeroizing::new(sk.as_bytes().to_vec())),
234        )
235    }
236
237    /// Encapsulate a shared secret to a public key.
238    pub fn encapsulate(
239        pk: &Kyber768PublicKey,
240    ) -> KyberResult<(Kyber768Ciphertext, Kyber768SharedSecret)> {
241        let public_key =
242            kyber768::PublicKey::from_bytes(&pk.0).map_err(|_| KyberError::InvalidPublicKey)?;
243
244        let (ss, ct) = kyber768::encapsulate(&public_key);
245
246        Ok((
247            Kyber768Ciphertext(ct.as_bytes().to_vec()),
248            Kyber768SharedSecret(Zeroizing::new(ss.as_bytes().to_vec())),
249        ))
250    }
251
252    /// Decapsulate a ciphertext to recover the shared secret.
253    pub fn decapsulate(
254        ct: &Kyber768Ciphertext,
255        sk: &Kyber768SecretKey,
256    ) -> KyberResult<Kyber768SharedSecret> {
257        let secret_key =
258            kyber768::SecretKey::from_bytes(&sk.0).map_err(|_| KyberError::InvalidSecretKey)?;
259        let ciphertext =
260            kyber768::Ciphertext::from_bytes(&ct.0).map_err(|_| KyberError::InvalidCiphertext)?;
261
262        let ss = kyber768::decapsulate(&ciphertext, &secret_key);
263
264        Ok(Kyber768SharedSecret(Zeroizing::new(ss.as_bytes().to_vec())))
265    }
266}
267
268/// Kyber1024 - Security level 5 (AES-256 equivalent).
269pub struct Kyber1024;
270
271impl Kyber1024 {
272    /// Generate a new keypair.
273    pub fn keypair() -> (Kyber1024PublicKey, Kyber1024SecretKey) {
274        let (pk, sk) = kyber1024::keypair();
275        (
276            Kyber1024PublicKey(pk.as_bytes().to_vec()),
277            Kyber1024SecretKey(Zeroizing::new(sk.as_bytes().to_vec())),
278        )
279    }
280
281    /// Encapsulate a shared secret to a public key.
282    pub fn encapsulate(
283        pk: &Kyber1024PublicKey,
284    ) -> KyberResult<(Kyber1024Ciphertext, Kyber1024SharedSecret)> {
285        let public_key =
286            kyber1024::PublicKey::from_bytes(&pk.0).map_err(|_| KyberError::InvalidPublicKey)?;
287
288        let (ss, ct) = kyber1024::encapsulate(&public_key);
289
290        Ok((
291            Kyber1024Ciphertext(ct.as_bytes().to_vec()),
292            Kyber1024SharedSecret(Zeroizing::new(ss.as_bytes().to_vec())),
293        ))
294    }
295
296    /// Decapsulate a ciphertext to recover the shared secret.
297    pub fn decapsulate(
298        ct: &Kyber1024Ciphertext,
299        sk: &Kyber1024SecretKey,
300    ) -> KyberResult<Kyber1024SharedSecret> {
301        let secret_key =
302            kyber1024::SecretKey::from_bytes(&sk.0).map_err(|_| KyberError::InvalidSecretKey)?;
303        let ciphertext =
304            kyber1024::Ciphertext::from_bytes(&ct.0).map_err(|_| KyberError::InvalidCiphertext)?;
305
306        let ss = kyber1024::decapsulate(&ciphertext, &secret_key);
307
308        Ok(Kyber1024SharedSecret(Zeroizing::new(
309            ss.as_bytes().to_vec(),
310        )))
311    }
312}
313
314// Implement as_bytes() for SharedSecret types
315impl Kyber512SharedSecret {
316    /// Get the shared secret as bytes.
317    pub fn as_bytes(&self) -> &[u8] {
318        &self.0
319    }
320}
321
322impl Kyber768SharedSecret {
323    /// Get the shared secret as bytes.
324    pub fn as_bytes(&self) -> &[u8] {
325        &self.0
326    }
327}
328
329impl Kyber1024SharedSecret {
330    /// Get the shared secret as bytes.
331    pub fn as_bytes(&self) -> &[u8] {
332        &self.0
333    }
334}
335
336#[cfg(test)]
337mod tests {
338    use super::*;
339
340    #[test]
341    fn test_kyber512_keypair_generation() {
342        let (_pk, _sk) = Kyber512::keypair();
343        // Just verify it doesn't panic
344    }
345
346    #[test]
347    fn test_kyber512_encapsulation_decapsulation() {
348        let (pk, sk) = Kyber512::keypair();
349        let (ct, ss1) = Kyber512::encapsulate(&pk).unwrap();
350        let ss2 = Kyber512::decapsulate(&ct, &sk).unwrap();
351
352        assert_eq!(ss1.as_bytes(), ss2.as_bytes());
353    }
354
355    #[test]
356    fn test_kyber512_different_shared_secrets() {
357        let (pk, _sk) = Kyber512::keypair();
358        let (_ct1, ss1) = Kyber512::encapsulate(&pk).unwrap();
359        let (_ct2, ss2) = Kyber512::encapsulate(&pk).unwrap();
360
361        // Different encapsulations should produce different shared secrets
362        assert_ne!(ss1.as_bytes(), ss2.as_bytes());
363    }
364
365    #[test]
366    fn test_kyber768_keypair_generation() {
367        let (_pk, _sk) = Kyber768::keypair();
368        // Just verify it doesn't panic
369    }
370
371    #[test]
372    fn test_kyber768_encapsulation_decapsulation() {
373        let (pk, sk) = Kyber768::keypair();
374        let (ct, ss1) = Kyber768::encapsulate(&pk).unwrap();
375        let ss2 = Kyber768::decapsulate(&ct, &sk).unwrap();
376
377        assert_eq!(ss1.as_bytes(), ss2.as_bytes());
378    }
379
380    #[test]
381    fn test_kyber768_different_shared_secrets() {
382        let (pk, _sk) = Kyber768::keypair();
383        let (_ct1, ss1) = Kyber768::encapsulate(&pk).unwrap();
384        let (_ct2, ss2) = Kyber768::encapsulate(&pk).unwrap();
385
386        // Different encapsulations should produce different shared secrets
387        assert_ne!(ss1.as_bytes(), ss2.as_bytes());
388    }
389
390    #[test]
391    fn test_kyber1024_keypair_generation() {
392        let (_pk, _sk) = Kyber1024::keypair();
393        // Just verify it doesn't panic
394    }
395
396    #[test]
397    fn test_kyber1024_encapsulation_decapsulation() {
398        let (pk, sk) = Kyber1024::keypair();
399        let (ct, ss1) = Kyber1024::encapsulate(&pk).unwrap();
400        let ss2 = Kyber1024::decapsulate(&ct, &sk).unwrap();
401
402        assert_eq!(ss1.as_bytes(), ss2.as_bytes());
403    }
404
405    #[test]
406    fn test_kyber1024_different_shared_secrets() {
407        let (pk, _sk) = Kyber1024::keypair();
408        let (_ct1, ss1) = Kyber1024::encapsulate(&pk).unwrap();
409        let (_ct2, ss2) = Kyber1024::encapsulate(&pk).unwrap();
410
411        // Different encapsulations should produce different shared secrets
412        assert_ne!(ss1.as_bytes(), ss2.as_bytes());
413    }
414
415    #[test]
416    fn test_kyber768_wrong_key_decapsulation() {
417        let (pk1, _sk1) = Kyber768::keypair();
418        let (_pk2, sk2) = Kyber768::keypair();
419
420        let (ct, ss1) = Kyber768::encapsulate(&pk1).unwrap();
421        let ss2 = Kyber768::decapsulate(&ct, &sk2).unwrap();
422
423        // Wrong key should produce different shared secret
424        assert_ne!(ss1.as_bytes(), ss2.as_bytes());
425    }
426
427    #[test]
428    fn test_kyber768_serialization() {
429        let (pk, sk) = Kyber768::keypair();
430
431        let pk_serialized = crate::codec::encode(&pk).unwrap();
432        let sk_serialized = crate::codec::encode(&sk).unwrap();
433
434        let pk_deserialized: Kyber768PublicKey = crate::codec::decode(&pk_serialized).unwrap();
435        let sk_deserialized: Kyber768SecretKey = crate::codec::decode(&sk_serialized).unwrap();
436
437        // Verify deserialized keys work
438        let (ct, ss1) = Kyber768::encapsulate(&pk_deserialized).unwrap();
439        let ss2 = Kyber768::decapsulate(&ct, &sk_deserialized).unwrap();
440
441        assert_eq!(ss1.as_bytes(), ss2.as_bytes());
442    }
443
444    #[test]
445    fn test_kyber768_ciphertext_serialization() {
446        let (pk, sk) = Kyber768::keypair();
447        let (ct, ss1) = Kyber768::encapsulate(&pk).unwrap();
448
449        let ct_serialized = crate::codec::encode(&ct).unwrap();
450        let ct_deserialized: Kyber768Ciphertext = crate::codec::decode(&ct_serialized).unwrap();
451
452        let ss2 = Kyber768::decapsulate(&ct_deserialized, &sk).unwrap();
453
454        assert_eq!(ss1.as_bytes(), ss2.as_bytes());
455    }
456
457    #[test]
458    fn test_kyber_all_levels_independent() {
459        let (pk512, sk512) = Kyber512::keypair();
460        let (pk768, sk768) = Kyber768::keypair();
461        let (pk1024, sk1024) = Kyber1024::keypair();
462
463        let (ct512, ss512) = Kyber512::encapsulate(&pk512).unwrap();
464        let (ct768, ss768) = Kyber768::encapsulate(&pk768).unwrap();
465        let (ct1024, ss1024) = Kyber1024::encapsulate(&pk1024).unwrap();
466
467        let ss512_dec = Kyber512::decapsulate(&ct512, &sk512).unwrap();
468        let ss768_dec = Kyber768::decapsulate(&ct768, &sk768).unwrap();
469        let ss1024_dec = Kyber1024::decapsulate(&ct1024, &sk1024).unwrap();
470
471        assert_eq!(ss512.as_bytes(), ss512_dec.as_bytes());
472        assert_eq!(ss768.as_bytes(), ss768_dec.as_bytes());
473        assert_eq!(ss1024.as_bytes(), ss1024_dec.as_bytes());
474    }
475}