chacha20
A pure-Rust, constant-time ChaCha20 stream cipher with AVX2/SSE2/NEON acceleration and an NCC Group security audit.
Repository Health
Technical Analysis
chacha20 is the RustCrypto project’s implementation of the ChaCha family of stream ciphers, built on the shared cipher crate traits so it drops into the same KeyIvInit/StreamCipher API used by every other RustCrypto cipher. It ships ChaCha8, ChaCha12, and the standard 20-round ChaCha20 (RFC 8439) out of the box, with the extended-nonce XChaCha family and the legacy 64-bit-nonce DJB variant available behind opt-in Cargo features.
Beyond encryption, the same core state machine powers a rand_core-compatible RNG (ChaCha20Rng and friends), making this crate a common dependency wherever a fast, portable, side-channel-resistant keystream generator is needed — from AEAD constructions like chacha20poly1305 to userspace CSPRNGs. It is no_std, has hand-written SIMD backends for SSE2, AVX2, AVX-512, and NEON with automatic runtime CPU-feature detection, and is one of the few crates in the RustCrypto workspace to have completed a third-party security audit (NCC Group, no significant findings).
What You Get
- ChaCha8, ChaCha12, and RFC 8439 ChaCha20 stream ciphers implementing the standard RustCrypto
KeyIvInit/StreamCipher/StreamCipherSeektraits - Optional XChaCha8/12/20 variants with 192-bit extended nonces (
xchachafeature) and the pre-RFC 64-bit-nonce “legacy” DJB variant (legacyfeature) - A
rand_core-compatible ChaCha-based RNG family (ChaCha8Rng/ChaCha12Rng/ChaCha20Rng) behind therngfeature, with seed and state serialization - Hand-tuned SIMD backends for SSE2, AVX2, AVX-512, and ARM NEON with automatic runtime CPU-feature detection, plus a portable software fallback
no_stdsupport with zero required allocation, and optionalzeroizeintegration to wipe internal state on drop
Common Use Cases
- Building AEAD constructions (e.g. ChaCha20-Poly1305) on top of a standards-compliant, audited keystream generator
- Encrypting data streams or files where a fast, side-channel-resistant cipher without AES-NI dependency is preferred
- Generating cryptographically strong pseudo-random numbers via ChaCha20Rng in userspace RNGs, simulations, or seeded reproducible randomness
- Interoperating with other protocols and implementations that specify ChaCha20/XChaCha20 (VPN protocols, TLS cipher suites, secure messaging)
Under The Hood
Architecture The crate is built around a generic ChaChaCore<R: Rounds, V: Variant> core type parameterized by a rounds marker (R8/R12/R20, defined in lib.rs) and a Variant trait (Ietf/Legacy in variants.rs, with XChaCha layered on via hchacha) that controls counter width and nonce size. The core state is a [u32; 16] word array laid out per RFC 8439 (constants + key + counter + nonce), manipulated in place by the shared quarter_round function in lib.rs and per-architecture SIMD backends dispatched through cfg_if! in backends.rs (soft.rs, sse2.rs, avx2.rs, avx512.rs, neon.rs), with runtime CPU-feature detection via cpufeatures-generated tokens stored on the core struct. Public type aliases in chacha.rs (ChaCha8, ChaCha12, ChaCha20) wrap the core in the cipher crate’s StreamCipherCoreWrapper to implement the standard stream-cipher traits, xchacha.rs layers the HChaCha20 subkey-derivation step on top for the extended-nonce variant, legacy.rs implements the pre-RFC variant, and rng.rs implements rand_core’s BlockRng/SeedableRng/Generator traits over the same core — one state machine serving cipher, XChaCha, legacy, and RNG use cases through trait composition rather than duplicated logic.
Tech Stack Pure Rust, #![no_std] (lib.rs), edition 2024, MSRV 1.85. Runtime dependencies are minimal: cfg-if for conditional compilation, cpufeatures for x86/x86_64 runtime SIMD detection, and optional cipher 0.5 (RustCrypto’s shared block/stream-cipher trait crate, pulled in behind the default cipher feature) and rand_core 0.10 (behind rng); zeroize 1.8 is a separately optional dependency for on-drop state wiping. Feature flags (cipher default-on, legacy, rng, xchacha) let consumers compile in only what they need. Hand-written SIMD backends target SSE2/AVX2/AVX-512 on x86(_64) and NEON on aarch64, selected at compile time and, absent an explicit chacha20_backend cfg override, chosen at runtime via CPU-feature detection.
Code Quality Testing lives in tests/kats.rs (RFC 8439 known-answer vectors driven through the shared cipher::stream_cipher_test!/stream_cipher_seek_test! macros for ChaCha20, XChaCha20, and the legacy variant) and tests/rng.rs (552 lines covering RNG seeding, state serialization, and stream position against reference vectors), plus a Criterion-style bench in benches/mod.rs. The crate turns on an unusually strict clippy/rustc lint set in Cargo.toml (missing_docs, unwrap_used, undocumented_unsafe_blocks, cast_possible_truncation, etc., all set to warn), and every public item carries doc comments; the two #![allow(...)] escapes in rng.rs are honestly annotated with “needs triage”/“TODO” reasons rather than silently suppressed. unsafe blocks are load-bearing for the SIMD backends — the workspace README notes this is the only crate among the RustCrypto stream ciphers to have completed a third-party security audit (NCC Group, no significant findings), a strong signal for a crate explicitly labeled “hazmat”.
API Design The public surface is small and idiomatic: ChaCha20::new(&key.into(), &nonce.into()) plus apply_keystream/seek from the shared cipher crate traits, so anyone already using another RustCrypto cipher (e.g. aes) gets an identical call shape for free — a deliberate ecosystem-wide consistency choice. The README’s example is embedded directly into the crate’s rustdoc via #![doc = include_str!("../README.md")] and is doc-tested, exercising encrypt, seek, and decrypt in about a dozen lines. The main friction point is the number of Cargo features a new user must understand to reach non-default variants — cipher (default), legacy, xchacha, rng, plus x86 chacha20_backend/chacha20_avx512 RUSTFLAGS cfg overrides — a configuration surface that is well documented but adds a learning-curve tax relative to a single-purpose crate.