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