1 //! The ChaCha20 stream cipher ([RFC 8439])
2 //!
3 //! ChaCha20 is a lightweight stream cipher which is amenable to fast,
4 //! constant-time implementations in software. It improves upon the previous
5 //! [Salsa20] stream cipher, providing increased per-round diffusion
6 //! with no cost to performance.
7 //!
8 //! Cipher functionality is accessed using traits from re-exported
9 //! [`cipher`](https://docs.rs/cipher) crate.
10 //!
11 //! This crate contains the following variants of the ChaCha20 core algorithm:
12 //!
13 //! - [`ChaCha20`]: standard IETF variant with 96-bit nonce
14 //! - [`ChaCha20Legacy`]: (gated under the `legacy` feature) "djb" variant with 64-bit nonce
15 //! - [`ChaCha8`] / [`ChaCha12`]: reduced round variants of ChaCha20
16 //! - [`XChaCha20`]: (gated under the `xchacha20` feature) 192-bit extended nonce variant
17 //!
18 //! # ⚠️ Security Warning: [Hazmat!]
19 //!
20 //! This crate does not ensure ciphertexts are authentic, which can lead to
21 //! serious vulnerabilities if used incorrectly!
22 //!
23 //! If in doubt, use the [`chacha20poly1305`](https://docs.rs/chacha20poly1305)
24 //! crate instead, which provides an authenticated mode on top of ChaCha20.
25 //!
26 //! **USE AT YOUR OWN RISK!**
27 //!
28 //! # Diagram
29 //!
30 //! This diagram illustrates the ChaCha quarter round function.
31 //! Each round consists of four quarter-rounds:
32 //!
33 //! <img src="https://raw.githubusercontent.com/RustCrypto/meta/master/img/stream-ciphers/chacha20.png" width="300px">
34 //!
35 //! Legend:
36 //!
37 //! - ⊞ add
38 //! - ‹‹‹ rotate
39 //! - ⊕ xor
40 //!
41 //! # Usage
42 //!
43 //! ```
44 //! use chacha20::{ChaCha20, Key, Nonce};
45 //! use chacha20::cipher::{NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
46 //!
47 //! let mut data = [1, 2, 3, 4, 5, 6, 7];
48 //!
49 //! let key = Key::from_slice(b"an example very very secret key.");
50 //! let nonce = Nonce::from_slice(b"secret nonce");
51 //!
52 //! // create cipher instance
53 //! let mut cipher = ChaCha20::new(&key, &nonce);
54 //!
55 //! // apply keystream (encrypt)
56 //! cipher.apply_keystream(&mut data);
57 //! assert_eq!(data, [73, 98, 234, 202, 73, 143, 0]);
58 //!
59 //! // seek to the keystream beginning and apply it again to the `data` (decrypt)
60 //! cipher.seek(0);
61 //! cipher.apply_keystream(&mut data);
62 //! assert_eq!(data, [1, 2, 3, 4, 5, 6, 7]);
63 //! ```
64 //!
65 //! [RFC 8439]: https://tools.ietf.org/html/rfc8439
66 //! [Salsa20]: https://docs.rs/salsa20
67 //! [Hazmat!]: https://github.com/RustCrypto/meta/blob/master/HAZMAT.md
68 
69 #![no_std]
70 #![doc(
71     html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
72     html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
73 )]
74 #![cfg_attr(docsrs, feature(doc_cfg))]
75 #![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)]
76 
77 mod block;
78 #[cfg(feature = "cipher")]
79 mod chacha;
80 #[cfg(feature = "legacy")]
81 mod legacy;
82 #[cfg(feature = "rng")]
83 mod rng;
84 mod rounds;
85 #[cfg(feature = "xchacha20")]
86 mod xchacha;
87 
88 #[cfg(feature = "cipher")]
89 pub use cipher;
90 
91 #[cfg(feature = "cipher")]
92 pub use self::chacha::{ChaCha, ChaCha12, ChaCha20, ChaCha8, Key, Nonce};
93 
94 #[cfg(feature = "legacy")]
95 pub use self::legacy::{ChaCha20Legacy, LegacyNonce};
96 
97 #[cfg(feature = "rng")]
98 pub use rng::{
99     ChaCha12Rng, ChaCha12RngCore, ChaCha20Rng, ChaCha20RngCore, ChaCha8Rng, ChaCha8RngCore,
100 };
101 
102 #[cfg(feature = "xchacha20")]
103 pub use self::xchacha::{XChaCha20, XNonce};
104 
105 /// Size of a ChaCha20 block in bytes
106 pub const BLOCK_SIZE: usize = 64;
107 
108 /// Size of a ChaCha20 key in bytes
109 pub const KEY_SIZE: usize = 32;
110 
111 /// Maximum number of blocks that can be encrypted with ChaCha20 before the
112 /// counter overflows.
113 pub const MAX_BLOCKS: usize = core::u32::MAX as usize;
114 
115 /// Number of bytes in the core (non-extended) ChaCha20 IV
116 const IV_SIZE: usize = 8;
117 
118 /// Number of 32-bit words in the ChaCha20 state
119 const STATE_WORDS: usize = 16;
120 
121 /// State initialization constant ("expand 32-byte k")
122 const CONSTANTS: [u32; 4] = [0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574];
123