Expand description
ChaCha20-Poly1305 AEAD (RFC 8439).
Authenticated encryption with associated data, built from ChaCha20 (the stream cipher) and Poly1305 (the one-time MAC). This is the AEAD used by TLS 1.3, Noise, Signal, WireGuard, QUIC, OpenSSH, and most modern protocols where AES-GCM is not the right choice – typically because the platform lacks AES-NI and a constant-time AES would be too slow.
§Construction (RFC 8439 §2.8)
- Initialise ChaCha20 with
(key, nonce, counter = 0)and take the first 32 bytes of the resulting keystream as the one-time Poly1305 key. - Re-initialise ChaCha20 with
(key, nonce, counter = 1)and XOR the plaintext with the keystream to produce the ciphertext. - Compute the Poly1305 tag over:
AAD ‖ pad16(AAD)
ciphertext ‖ pad16(ciphertext)
len(AAD) as u64 little-endian
len(ciphertext) as u64 little-endianWhere pad16(x) is 0..(16 - len(x) mod 16) mod 16 zero bytes.
- Output
(ciphertext, tag). The tag is 16 bytes.
Decryption reverses the process and verifies the tag in constant time before returning the plaintext.
§API
use arcana::cipher::chacha20poly1305::ChaCha20Poly1305;
let key: [u8; 32] = /* shared secret */;
let nonce: [u8; 12] = /* MUST be unique per (key, message) */;
let aad = b"associated header";
let pt = b"top secret message";
let (ct, tag) = ChaCha20Poly1305::encrypt(&key, &nonce, aad, pt);
let pt_back = ChaCha20Poly1305::decrypt(&key, &nonce, aad, &ct, &tag)
.expect("authentic");
assert_eq!(pt_back, pt);§Nonce reuse warning
Reusing a nonce with the same key on a different (plaintext, aad) is catastrophic: it leaks the XOR of the two plaintexts
AND lets the attacker forge arbitrary messages under that key.
Always draw a fresh random 12-byte nonce or use a counter that
is guaranteed unique for the lifetime of the key.
§Tests
Pinned against RFC 8439 §2.8.2 (the canonical “Ladies and Gentlemen” AEAD test vector) byte-for-byte.
Structs§
- ChaCha20
Poly1305 - ChaCha20-Poly1305 AEAD per RFC 8439.