Chapter 2 · Practice 1 of 4
Default to an AEAD: AES-GCM, ChaCha20-Poly1305 or XChaCha20-Poly1305
Why it matters
An AEAD (authenticated encryption with associated data) encrypts the plaintext and produces a tag that fails verification if a single bit of the ciphertext, the nonce or the associated data changes. OWASP's Cryptographic Storage Cheat Sheet recommends:
- AES with a key of at least 128 bits, ideally 256 bits
- authenticated modes first: GCM or CCM
- only if those are unavailable, CTR or CBC with separate authentication (Encrypt-then-MAC)
- ECB should not be used outside very specific circumstances, because identical plaintext blocks produce identical ciphertext blocks
libsodium's AEAD documentation adds a practical choice: on CPUs with hardware AES support, AEGIS-256 is its safest pick; otherwise XChaCha20-Poly1305, which is portable to every architecture. Its AES256-GCM implementation needs hardware support (AES-NI or the ARM crypto extensions).
| Construction | Key | Nonce | Where it fits |
|---|---|---|---|
| AES-256-GCM | 256 bits | 96 bits | wide support, Web Crypto, cloud KMS |
| ChaCha20-Poly1305 (IETF) | 256 bits | 96 bits | TLS 1.3, devices without AES hardware |
| XChaCha20-Poly1305 | 256 bits | 192 bits | random nonces with no practical message limit |
Always decrypt with the library's single call and treat a failed tag check as "this data is not yours". Never return partial plaintext from a failed decryption.
Do
- Use AES-256-GCM, ChaCha20-Poly1305 or XChaCha20-Poly1305
- Treat any authentication failure as a hard error
- Store algorithm and key ID beside each ciphertext
Avoid
- AES-ECB for anything
- CBC or CTR without a MAC
- Decrypting before checking the tag in a streaming loop