Skip to main content

cryptography/
lib.rs

1//! Classical and modern block ciphers, stream ciphers, and DRBGs
2//! implemented in pure, safe, portable Rust directly from their published
3//! specifications.
4//!
5//! Public-key primitives are variable-time and intentionally live under
6//! [`crate::vt`] to make that side-channel property explicit.
7//!
8//! Entropy warning:
9//! - This crate does not provide an operating-system entropy source.
10//! - [`CtrDrbgAes256`] is a deterministic DRBG, not a seed generator.
11//! - Callers must provide high-entropy external seed material for all
12//!   randomness-dependent operations.
13
14mod ct;
15#[cfg(test)]
16mod test_utils;
17
18pub use ct::zeroize_slice;
19
20#[cfg(feature = "ct_profile")]
21pub use ct::{
22    ct_profile_measure_helper_costs, ct_profile_reset, ct_profile_snapshot, CtAnfHelperCostsNs,
23    CtAnfProfile,
24};
25
26pub mod ciphers;
27pub mod cprng;
28pub mod hash;
29pub mod modes;
30pub mod public_key;
31
32pub use ciphers::{
33    aes, camellia, cast128, chacha20, des, grasshopper, magma, present, rabbit, salsa20, seed,
34    serpent, simon, sm4, snow3g, speck, twofish, zuc,
35};
36
37/// Common interface for block ciphers.
38///
39/// Every cipher exposes in-place `encrypt` / `decrypt` operating on a byte
40/// slice whose length must equal `Self::BLOCK_LEN`.
41pub trait BlockCipher {
42    /// Block length in bytes.
43    const BLOCK_LEN: usize;
44    /// Encrypt one block in-place. Panics if `block.len() != BLOCK_LEN`.
45    fn encrypt(&self, block: &mut [u8]);
46    /// Decrypt one block in-place. Panics if `block.len() != BLOCK_LEN`.
47    fn decrypt(&self, block: &mut [u8]);
48}
49
50/// Common interface for stream ciphers.
51///
52/// Stream ciphers encrypt and decrypt by XORing keystream bytes into a mutable
53/// buffer. The same operation is used in both directions.
54pub trait StreamCipher {
55    /// XOR keystream bytes into `buf` in place.
56    fn fill(&mut self, buf: &mut [u8]);
57
58    /// Alias for [`Self::fill`] for callers that prefer this terminology.
59    fn apply_keystream(&mut self, buf: &mut [u8]) {
60        self.fill(buf);
61    }
62}
63
64/// Common interface for AEAD constructions with detached tags.
65pub trait Aead {
66    /// Detached authentication tag type.
67    type Tag;
68
69    /// Encrypt `data` in place and return its authentication tag.
70    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag;
71
72    /// Decrypt `data` in place after authenticating `tag`.
73    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool;
74
75    /// Encrypt `plaintext` and return `(ciphertext, tag)`.
76    fn encrypt(&self, nonce: &[u8], aad: &[u8], plaintext: &[u8]) -> (Vec<u8>, Self::Tag) {
77        let mut out = plaintext.to_vec();
78        let tag = self.encrypt_in_place(nonce, aad, &mut out);
79        (out, tag)
80    }
81
82    /// Decrypt `ciphertext` and return plaintext on successful authentication.
83    fn decrypt(
84        &self,
85        nonce: &[u8],
86        aad: &[u8],
87        ciphertext: &[u8],
88        tag: &Self::Tag,
89    ) -> Option<Vec<u8>> {
90        let mut out = ciphertext.to_vec();
91        if !self.decrypt_in_place(nonce, aad, &mut out, tag) {
92            return None;
93        }
94        Some(out)
95    }
96}
97
98/// Common interface for byte-oriented CSPRNG/DRBG outputs.
99pub trait Csprng {
100    /// Fill `out` with pseudorandom bytes.
101    fn fill_bytes(&mut self, out: &mut [u8]);
102
103    /// Convenience helper for consumers that want one machine word at a time.
104    fn next_u64(&mut self) -> u64 {
105        let mut out = [0u8; 8];
106        self.fill_bytes(&mut out);
107        u64::from_be_bytes(out)
108    }
109}
110
111pub use ciphers::aes::{Aes128, Aes128Ct, Aes192, Aes192Ct, Aes256, Aes256Ct};
112pub use ciphers::camellia::{
113    Camellia, Camellia128, Camellia128Ct, Camellia192, Camellia192Ct, Camellia256, Camellia256Ct,
114    CamelliaCt,
115};
116pub use ciphers::cast128::{Cast128, Cast128Ct, Cast5, Cast5Ct};
117pub use ciphers::chacha20::{ChaCha20, XChaCha20};
118pub use ciphers::des::{key_schedule, Des, DesCt, KeySchedule, TDesMode, TripleDes};
119pub use ciphers::grasshopper::{Grasshopper, GrasshopperCt};
120pub use ciphers::magma::{Magma, MagmaCt};
121pub use ciphers::present::{Present, Present128, Present128Ct, Present80, Present80Ct, PresentCt};
122pub use ciphers::rabbit::Rabbit;
123pub use ciphers::salsa20::Salsa20;
124pub use ciphers::seed::{Seed, SeedCt};
125pub use ciphers::serpent::{
126    Serpent, Serpent128, Serpent128Ct, Serpent192, Serpent192Ct, Serpent256, Serpent256Ct,
127    SerpentCt,
128};
129pub use ciphers::simon::{
130    Simon128_128, Simon128_192, Simon128_256, Simon32_64, Simon48_72, Simon48_96, Simon64_128,
131    Simon64_96, Simon96_144, Simon96_96,
132};
133pub use ciphers::sm4::{Sm4, Sm4Ct, Sms4, Sms4Ct};
134pub use ciphers::snow3g::{Snow3g, Snow3gCt};
135pub use ciphers::speck::{
136    Speck128_128, Speck128_192, Speck128_256, Speck32_64, Speck48_72, Speck48_96, Speck64_128,
137    Speck64_96, Speck96_144, Speck96_96,
138};
139pub use ciphers::twofish::{
140    Twofish, Twofish128, Twofish128Ct, Twofish192, Twofish192Ct, Twofish256, Twofish256Ct,
141    TwofishCt,
142};
143pub use ciphers::zuc::{Zuc128, Zuc128Ct};
144
145pub use cprng::ctr_drbg::CtrDrbgAes256;
146pub use hash::hkdf::Hkdf;
147pub use hash::hmac::Hmac;
148pub use hash::md5::Md5;
149pub use hash::ripemd160::Ripemd160;
150pub use hash::sha1::Sha1;
151pub use hash::sha2::{Sha224, Sha256, Sha384, Sha512, Sha512_224, Sha512_256};
152pub use hash::sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
153pub use hash::{Digest, Xof};
154pub use modes::{
155    Aes128GcmSiv, Aes256GcmSiv, AesKeyWrap, Cbc, Ccm, Cfb, Cfb8, ChaCha20Poly1305, Cmac, Ctr, Eax,
156    Ecb, Gcm, GcmVt, Gmac, GmacVt, Ocb, Ofb, Poly1305, Siv, Xts,
157};
158
159impl StreamCipher for ChaCha20 {
160    fn fill(&mut self, buf: &mut [u8]) {
161        self.fill(buf);
162    }
163}
164
165impl StreamCipher for XChaCha20 {
166    fn fill(&mut self, buf: &mut [u8]) {
167        self.fill(buf);
168    }
169}
170
171impl StreamCipher for Salsa20 {
172    fn fill(&mut self, buf: &mut [u8]) {
173        self.fill(buf);
174    }
175}
176
177impl StreamCipher for Rabbit {
178    fn fill(&mut self, buf: &mut [u8]) {
179        self.fill(buf);
180    }
181}
182
183impl StreamCipher for Snow3g {
184    fn fill(&mut self, buf: &mut [u8]) {
185        self.fill(buf);
186    }
187}
188
189impl StreamCipher for Snow3gCt {
190    fn fill(&mut self, buf: &mut [u8]) {
191        self.fill(buf);
192    }
193}
194
195impl StreamCipher for Zuc128 {
196    fn fill(&mut self, buf: &mut [u8]) {
197        self.fill(buf);
198    }
199}
200
201impl StreamCipher for Zuc128Ct {
202    fn fill(&mut self, buf: &mut [u8]) {
203        self.fill(buf);
204    }
205}
206
207impl<C: BlockCipher> Aead for Gcm<C> {
208    type Tag = [u8; 16];
209
210    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
211        self.encrypt(nonce, aad, data)
212    }
213
214    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
215        self.decrypt(nonce, aad, data, tag)
216    }
217}
218
219impl<C: BlockCipher> Aead for GcmVt<C> {
220    type Tag = [u8; 16];
221
222    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
223        self.encrypt(nonce, aad, data)
224    }
225
226    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
227        self.decrypt(nonce, aad, data, tag)
228    }
229}
230
231impl<C: BlockCipher, const TAG_LEN: usize> Aead for Ccm<C, TAG_LEN> {
232    type Tag = [u8; TAG_LEN];
233
234    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
235        self.encrypt(nonce, aad, data)
236    }
237
238    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
239        self.decrypt(nonce, aad, data, tag)
240    }
241}
242
243impl Aead for ChaCha20Poly1305 {
244    type Tag = [u8; 16];
245
246    /// Panics if `nonce.len() != 12`.
247    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
248        let nonce: &[u8; 12] = nonce
249            .try_into()
250            .expect("ChaCha20-Poly1305 nonce must be 12 bytes");
251        self.encrypt_in_place(nonce, aad, data)
252    }
253
254    /// Panics if `nonce.len() != 12`.
255    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
256        let nonce: &[u8; 12] = nonce
257            .try_into()
258            .expect("ChaCha20-Poly1305 nonce must be 12 bytes");
259        self.decrypt_in_place(nonce, aad, data, tag)
260    }
261}
262
263impl<C: BlockCipher> Aead for Siv<C> {
264    type Tag = [u8; 16];
265
266    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
267        let (ciphertext, tag) = self.encrypt(nonce, aad, data);
268        data.copy_from_slice(&ciphertext);
269        tag
270    }
271
272    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
273        self.decrypt(nonce, aad, data, tag)
274    }
275}
276
277impl<C: BlockCipher> Aead for Eax<C> {
278    type Tag = [u8; 16];
279
280    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
281        self.encrypt(nonce, aad, data)
282    }
283
284    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
285        self.decrypt(nonce, aad, data, tag)
286    }
287}
288
289impl<C: BlockCipher> Aead for Ocb<C> {
290    type Tag = [u8; 16];
291
292    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
293        self.encrypt(nonce, aad, data)
294    }
295
296    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
297        self.decrypt(nonce, aad, data, tag)
298    }
299}
300
301impl Aead for Aes128GcmSiv {
302    type Tag = [u8; 16];
303
304    /// Panics if `nonce.len() != 12`.
305    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
306        let nonce: &[u8; 12] = nonce
307            .try_into()
308            .expect("AES-GCM-SIV nonce must be 12 bytes");
309        self.encrypt(nonce, aad, data)
310    }
311
312    /// Panics if `nonce.len() != 12`.
313    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
314        let nonce: &[u8; 12] = nonce
315            .try_into()
316            .expect("AES-GCM-SIV nonce must be 12 bytes");
317        self.decrypt(nonce, aad, data, tag)
318    }
319}
320
321impl Aead for Aes256GcmSiv {
322    type Tag = [u8; 16];
323
324    /// Panics if `nonce.len() != 12`.
325    fn encrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> Self::Tag {
326        let nonce: &[u8; 12] = nonce
327            .try_into()
328            .expect("AES-GCM-SIV nonce must be 12 bytes");
329        self.encrypt(nonce, aad, data)
330    }
331
332    /// Panics if `nonce.len() != 12`.
333    fn decrypt_in_place(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &Self::Tag) -> bool {
334        let nonce: &[u8; 12] = nonce
335            .try_into()
336            .expect("AES-GCM-SIV nonce must be 12 bytes");
337        self.decrypt(nonce, aad, data, tag)
338    }
339}
340
341/// Explicit variable-time public-key surface.
342///
343/// Most items in this namespace use variable-time big-integer and ECC arithmetic
344/// and are unsuitable for side-channel exposed production signing/decryption.
345///
346/// Exception: `X25519` and `X448` (RFC 7748) are constant-time. They live
347/// here because they share serialization conventions with the rest of the
348/// public-key surface, but the scalar-mult primitive itself is hardened
349/// against timing side channels on the secret scalar.
350pub mod vt {
351    pub use crate::public_key::bigint::{BigInt, BigUint, MontgomeryCtx, Sign};
352    pub use crate::public_key::cocks::{Cocks, CocksPrivateKey, CocksPublicKey};
353    pub use crate::public_key::dh::{Dh, DhParams, DhPrivateKey, DhPublicKey};
354    pub use crate::public_key::dsa::{Dsa, DsaPrivateKey, DsaPublicKey, DsaSignature};
355    pub use crate::public_key::ec::{
356        b163, b233, b283, b409, b571, k163, k233, k283, k409, k571, p192, p224, p256, p384, p521,
357        secp256k1, AffinePoint, CurveParams,
358    };
359    pub use crate::public_key::ec_elgamal::{
360        EcElGamal, EcElGamalCiphertext, EcElGamalPrivateKey, EcElGamalPublicKey,
361    };
362    pub use crate::public_key::ecdh::{Ecdh, EcdhPrivateKey, EcdhPublicKey};
363    pub use crate::public_key::ecdsa::{Ecdsa, EcdsaPrivateKey, EcdsaPublicKey, EcdsaSignature};
364    pub use crate::public_key::ecies::{Ecies, EciesPrivateKey, EciesPublicKey};
365    pub use crate::public_key::ed25519::{
366        Ed25519, Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature,
367    };
368    pub use crate::public_key::eddsa::{EdDsa, EdDsaPrivateKey, EdDsaPublicKey, EdDsaSignature};
369    pub use crate::public_key::edwards_dh::{EdwardsDh, EdwardsDhPrivateKey, EdwardsDhPublicKey};
370    pub use crate::public_key::edwards_elgamal::{
371        EdwardsElGamal, EdwardsElGamalCiphertext, EdwardsElGamalPrivateKey, EdwardsElGamalPublicKey,
372    };
373    pub use crate::public_key::elgamal::{
374        ElGamal, ElGamalCiphertext, ElGamalPrivateKey, ElGamalPublicKey,
375    };
376    pub use crate::public_key::ml_dsa::{
377        MlDsa, MlDsaParameterSet, MlDsaPrivateKey, MlDsaPublicKey, MlDsaSignature,
378    };
379    pub use crate::public_key::ml_kem::{
380        MlKem, MlKemCiphertext, MlKemParameterSet, MlKemPrivateKey, MlKemPublicKey,
381        MlKemSharedSecret,
382    };
383    pub use crate::public_key::ntru_hps509::{
384        NtruHps509, NtruHps509Ciphertext, NtruHps509PrivateKey, NtruHps509PublicKey,
385        NtruHps509SharedSecret,
386    };
387    pub use crate::public_key::ntru_hps677::{
388        NtruHps677, NtruHps677Ciphertext, NtruHps677PrivateKey, NtruHps677PublicKey,
389        NtruHps677SharedSecret,
390    };
391    pub use crate::public_key::ntru_hps821::{
392        NtruHps821, NtruHps821Ciphertext, NtruHps821PrivateKey, NtruHps821PublicKey,
393        NtruHps821SharedSecret,
394    };
395    pub use crate::public_key::ntru_ees401ep1::{
396        NtruEes401Ep1, NtruEes401Ep1Ciphertext, NtruEes401Ep1PrivateKey, NtruEes401Ep1PublicKey,
397    };
398    pub use crate::public_key::ntru_ees443ep1::{
399        NtruEes443Ep1, NtruEes443Ep1Ciphertext, NtruEes443Ep1PrivateKey, NtruEes443Ep1PublicKey,
400    };
401    pub use crate::public_key::ntru_ees449ep1::{
402        NtruEes449Ep1, NtruEes449Ep1Ciphertext, NtruEes449Ep1PrivateKey, NtruEes449Ep1PublicKey,
403    };
404    pub use crate::public_key::ntru_ees541ep1::{
405        NtruEes541Ep1, NtruEes541Ep1Ciphertext, NtruEes541Ep1PrivateKey, NtruEes541Ep1PublicKey,
406    };
407    pub use crate::public_key::ntru_ees677ep1::{
408        NtruEes677Ep1, NtruEes677Ep1Ciphertext, NtruEes677Ep1PrivateKey, NtruEes677Ep1PublicKey,
409    };
410    pub use crate::public_key::ntru_ees1087ep1::{
411        NtruEes1087Ep1, NtruEes1087Ep1Ciphertext, NtruEes1087Ep1PrivateKey,
412        NtruEes1087Ep1PublicKey,
413    };
414    pub use crate::public_key::ntru_ees1087ep2::{
415        NtruEes1087Ep2, NtruEes1087Ep2Ciphertext, NtruEes1087Ep2PrivateKey,
416        NtruEes1087Ep2PublicKey,
417    };
418    pub use crate::public_key::ntru_ees1171ep1::{
419        NtruEes1171Ep1, NtruEes1171Ep1Ciphertext, NtruEes1171Ep1PrivateKey,
420        NtruEes1171Ep1PublicKey,
421    };
422    pub use crate::public_key::ntru_ees1499ep1::{
423        NtruEes1499Ep1, NtruEes1499Ep1Ciphertext, NtruEes1499Ep1PrivateKey,
424        NtruEes1499Ep1PublicKey,
425    };
426    pub use crate::public_key::ntru_ees_core::NtruEesError;
427    pub use crate::public_key::ntru_hrss701::{
428        NtruHrss701, NtruHrss701Ciphertext, NtruHrss701PrivateKey, NtruHrss701PublicKey,
429        NtruHrss701SharedSecret,
430    };
431    pub use crate::public_key::paillier::{Paillier, PaillierPrivateKey, PaillierPublicKey};
432    pub use crate::public_key::rabin::{Rabin, RabinPrivateKey, RabinPublicKey};
433    pub use crate::public_key::rsa::{Rsa, RsaPrivateKey, RsaPublicKey};
434    pub use crate::public_key::rsa_pkcs1::{RsaOaep, RsaPss};
435    pub use crate::public_key::schmidt_samoa::{
436        SchmidtSamoa, SchmidtSamoaPrivateKey, SchmidtSamoaPublicKey,
437    };
438    pub use crate::public_key::x25519::{X25519, X25519PrivateKey, X25519PublicKey};
439    pub use crate::public_key::x448::{X448, X448PrivateKey, X448PublicKey};
440}
441
442#[cfg(test)]
443mod scrub;