blob: 98f8d2b5b4d8521ff1b4fd50cda5a3165181db17 [file] [log] [blame]
//! The ChaCha20 stream cipher ([RFC 8439])
//!
//! ChaCha20 is a lightweight stream cipher which is amenable to fast,
//! constant-time implementations in software. It improves upon the previous
//! [Salsa20] stream cipher, providing increased per-round diffusion
//! with no cost to performance.
//!
//! Cipher functionality is accessed using traits from re-exported
//! [`cipher`](https://docs.rs/cipher) crate.
//!
//! This crate contains the following variants of the ChaCha20 core algorithm:
//!
//! - [`ChaCha20`]: standard IETF variant with 96-bit nonce
//! - [`ChaCha20Legacy`]: (gated under the `legacy` feature) "djb" variant with 64-bit nonce
//! - [`ChaCha8`] / [`ChaCha12`]: reduced round variants of ChaCha20
//! - [`XChaCha20`]: 192-bit extended nonce variant
//! - [`XChaCha8`] / [`XChaCha12`]: reduced round variants of XChaCha20
//!
//! # ⚠️ Security Warning: [Hazmat!]
//!
//! This crate does not ensure ciphertexts are authentic, which can lead to
//! serious vulnerabilities if used incorrectly!
//!
//! If in doubt, use the [`chacha20poly1305`](https://docs.rs/chacha20poly1305)
//! crate instead, which provides an authenticated mode on top of ChaCha20.
//!
//! **USE AT YOUR OWN RISK!**
//!
//! # Diagram
//!
//! This diagram illustrates the ChaCha quarter round function.
//! Each round consists of four quarter-rounds:
//!
//! <img src="https://raw.githubusercontent.com/RustCrypto/meta/master/img/stream-ciphers/chacha20.png" width="300px">
//!
//! Legend:
//!
//! - ⊞ add
//! - ‹‹‹ rotate
//! - ⊕ xor
//!
//! # Usage
//!
//! ```
//! # #[cfg(feature = "cipher")]
//! # {
//! use chacha20::{ChaCha20, Key, Nonce};
//! use chacha20::cipher::{NewCipher, StreamCipher, StreamCipherSeek};
//!
//! let mut data = [1, 2, 3, 4, 5, 6, 7];
//!
//! let key = Key::from_slice(b"an example very very secret key.");
//! let nonce = Nonce::from_slice(b"secret nonce");
//!
//! // create cipher instance
//! let mut cipher = ChaCha20::new(&key, &nonce);
//!
//! // apply keystream (encrypt)
//! cipher.apply_keystream(&mut data);
//! assert_eq!(data, [73, 98, 234, 202, 73, 143, 0]);
//!
//! // seek to the keystream beginning and apply it again to the `data` (decrypt)
//! cipher.seek(0);
//! cipher.apply_keystream(&mut data);
//! assert_eq!(data, [1, 2, 3, 4, 5, 6, 7]);
//! # }
//! ```
//!
//! [RFC 8439]: https://tools.ietf.org/html/rfc8439
//! [Salsa20]: https://docs.rs/salsa20
//! [Hazmat!]: https://github.com/RustCrypto/meta/blob/master/HAZMAT.md
#![no_std]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_root_url = "https://docs.rs/chacha20/0.8.1"
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(
all(feature = "neon", target_arch = "aarch64", target_feature = "neon"),
feature(stdsimd, aarch64_target_feature)
)]
#![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)]
mod backend;
#[cfg(feature = "cipher")]
mod chacha;
#[cfg(feature = "legacy")]
mod legacy;
mod max_blocks;
#[cfg(feature = "rng")]
mod rng;
mod rounds;
#[cfg(feature = "cipher")]
mod xchacha;
#[cfg(feature = "cipher")]
pub use cipher;
#[cfg(feature = "cipher")]
pub use crate::{
chacha::{ChaCha, ChaCha12, ChaCha20, ChaCha8, Key, Nonce},
xchacha::{XChaCha, XChaCha12, XChaCha20, XChaCha8, XNonce},
};
#[cfg(feature = "expose-core")]
pub use crate::{
backend::Core,
rounds::{R12, R20, R8},
};
#[cfg(feature = "hchacha")]
pub use crate::xchacha::hchacha;
#[cfg(feature = "legacy")]
pub use crate::legacy::{ChaCha20Legacy, LegacyNonce};
#[cfg(feature = "rng")]
pub use rng::{
ChaCha12Rng, ChaCha12RngCore, ChaCha20Rng, ChaCha20RngCore, ChaCha8Rng, ChaCha8RngCore,
};
/// Size of a ChaCha20 block in bytes
pub const BLOCK_SIZE: usize = 64;
/// Size of a ChaCha20 key in bytes
pub const KEY_SIZE: usize = 32;
/// Number of bytes in the core (non-extended) ChaCha20 IV
const IV_SIZE: usize = 8;
/// State initialization constant ("expand 32-byte k")
const CONSTANTS: [u32; 4] = [0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574];