Symmetric Encryption
AES-256-GCM for most use cases, ChaCha20-Poly1305 when hardware AES is unavailable --
always use authenticated encryption, never roll your own
When to Use
- Encrypting data at rest (database fields, file storage, backups)
- Encrypting data in application-layer protocols (beyond TLS)
- Choosing between AES and ChaCha20 for a specific deployment target
- Selecting a mode of operation (GCM, CBC, CTR) for a symmetric cipher
- Reviewing code that performs encryption for correctness
- Designing a key management scheme for encrypted data
Threat Context
Symmetric encryption defends against confidentiality breaches when an attacker gains
access to stored data (stolen database dumps, compromised backups, unauthorized file
system access) or intercepts data in transit. Without authenticated encryption (AEAD),
an attacker can also tamper with ciphertext without detection -- the padding oracle
attack against AES-CBC (CVE-2014-3566, POODLE) demonstrated this at scale, enabling
plaintext recovery through ciphertext manipulation. Key theft and nonce misuse represent
the two remaining catastrophic failure modes even when a correct algorithm is chosen.
Instructions
Default to AES-256-GCM. AES (Advanced Encryption Standard, Rijndael) with
256-bit keys in GCM (Galois/Counter Mode) provides both confidentiality and integrity
through authenticated encryption with associated data (AEAD). GCM produces a 128-bit
authentication tag that detects any ciphertext modification. AES-256-GCM is
NIST-approved, FIPS 140-2 compliant, and hardware-accelerated on all modern x86
(AES-NI) and ARM (ARMv8 Crypto Extensions) processors. On hardware with AES-NI,
AES-256-GCM achieves throughput exceeding 1 GB/s per core.
Use ChaCha20-Poly1305 when AES hardware acceleration is unavailable. ChaCha20
is a stream cipher designed by Daniel Bernstein as a refinement of Salsa20, using a
256-bit key and a 96-bit nonce. Combined with Poly1305 MAC, it provides AEAD
equivalent in security to AES-GCM. ChaCha20-Poly1305 is faster in software on
devices without AES-NI (IoT devices, older mobile chipsets, embedded systems). TLS 1.3
includes both AES-256-GCM and ChaCha20-Poly1305 as mandatory cipher suites. Google
adopted ChaCha20-Poly1305 in Chrome for Android specifically because most ARM
processors at the time lacked AES hardware acceleration.
Never use unauthenticated modes in new systems. AES-CBC (Cipher Block Chaining)
without a separate HMAC is vulnerable to padding oracle attacks -- an attacker who can
submit ciphertexts and observe whether decryption produces a padding error can recover
the full plaintext byte-by-byte. AES-ECB (Electronic Codebook) is structurally broken:
identical plaintext blocks produce identical ciphertext blocks, leaking patterns in the
data. AES-CTR (Counter Mode) without a MAC provides confidentiality but allows
undetected ciphertext bit-flipping -- an attacker who knows the plaintext at a given
position can flip the corresponding ciphertext bit to produce any desired plaintext
byte.
Generate IVs/nonces correctly. GCM requires a unique 96-bit nonce per encryption
operation under the same key. Nonce reuse under GCM is catastrophic: it reveals the
XOR of two plaintexts and exposes the GHASH authentication key, allowing forgery of
authentication tags for arbitrary messages. Use a cryptographically secure pseudorandom
number generator (CSPRNG) for random nonces. For systems encrypting more than 2^32
messages under a single key (where random nonce collision probability becomes
non-negligible by the birthday bound), use a deterministic construction such as
AES-GCM-SIV, which provides nonce-misuse resistance at a modest performance cost.
Key sizes: 256-bit for future-proofing. AES-128 is not broken and provides
128-bit security against classical computers, which is sufficient for current threats.
AES-256 provides margin against theoretical quantum attacks -- Grover's algorithm
reduces the effective key strength by half (256-bit becomes 128-bit effective), keeping
AES-256 secure even in a post-quantum scenario. For all new systems, default to
256-bit keys. The performance difference between AES-128 and AES-256 is approximately
40% more rounds (14 vs 10) but negligible in practice with hardware acceleration.
Key derivation from passwords. Never use a password directly as an encryption key.
Human-chosen passwords have far less entropy than required for cryptographic keys.
Derive keys using Argon2id (preferred), scrypt, or PBKDF2-HMAC-SHA256 with a unique
random salt (at least 128 bits) and sufficient cost parameters. The derived key must be
exactly the length required by the cipher: 32 bytes for AES-256. Store the salt
alongside the ciphertext (the salt is not secret). If deriving multiple keys from one
password (e.g., one for encryption, one for MAC), use distinct info/context parameters
in an HKDF-Expand step, never truncate or split a single derived key.
Encrypt-then-MAC if forced to use CBC. If a legacy system requires AES-CBC, apply
HMAC-SHA256 to the ciphertext (not the plaintext) after encryption. Verify the MAC
before decrypting -- reject any message with an invalid MAC without attempting
decryption. This is the encrypt-then-MAC construction and is provably secure under
standard assumptions. The two alternative compositions -- MAC-then-encrypt (used in
TLS < 1.3, enabling BEAST and Lucky Thirteen) and encrypt-and-MAC (used in SSH,
theoretically weaker) -- are both vulnerable to specific attack classes. Always use
encrypt-then-MAC.
Details
Modes of Operation Comparison
| Mode |
Type |
Parallelizable |
Nonce-Sensitive |
Notes |
| GCM |
AEAD |
Yes (encrypt + decrypt) |
Catastrophic on reuse |
Default choice for new systems |
| CBC |
Confidentiality only |
Decrypt only |
IV must be unpredictable |
Padding oracle risk; needs separate MAC |
| CTR |
Confidentiality only |
Yes (encrypt + decrypt) |
Catastrophic on reuse |
Needs separate MAC; basis for GCM |
| GCM-SIV |
AEAD |
Yes |
Nonce-misuse resistant |
Slight performance penalty; safe when nonce uniqueness cannot be guaranteed |
| XTS |
Tweakable block cipher |
Yes |
N/A (uses tweak) |
Designed for disk/sector encryption (LUKS, BitLocker); not for general use |
The Nonce Reuse Catastrophe
When nonce N is reused with key K for two different plaintexts P1 and P2 under AES-GCM:
- The keystream is identical for both encryptions (since CTR mode generates the keystream
from the nonce).
- C1 XOR C2 = P1 XOR P2, revealing the XOR of the two plaintexts. With known or
guessable plaintext fragments, this recovers both messages.
- The GHASH authentication key H is exposed through algebraic analysis of the two
authentication tags. With H, the attacker can forge valid authentication tags for
arbitrary ciphertexts under the same key -- a complete authenticity break.
- This is not theoretical: nonce reuse vulnerabilities have been discovered in production
TLS implementations, and the GHASH key recovery attack has been demonstrated
practically.
Associated Data (the "AD" in AEAD)
GCM and ChaCha20-Poly1305 support additional authenticated data (AAD) -- data that is
integrity-protected but not encrypted. The authentication tag covers both the ciphertext
and the AAD, so any modification to either is detected.
Use AAD for metadata that must not be modified but does not need confidentiality:
- The database row ID or primary key (prevents ciphertext from being moved between rows)
- The encryption algorithm identifier (prevents downgrade attacks)
- The key version identifier (prevents ciphertext from being decrypted with the wrong
key version)
- Any routing or addressing information that must remain in plaintext for the system to
function
Key Rotation
Encrypted data must remain decryptable after key rotation. The standard pattern:
- Encrypt with the current active key. Store the key version/ID alongside the ciphertext
(in the AAD or as a plaintext prefix).
- On decryption, look up the key by version ID and decrypt with the correct key.
- Re-encrypt data under the new key during a migration window (background job, lazy
re-encryption on read, or bulk migration).
- Never delete old keys until all data encrypted under them has been verified as
re-encrypted. Maintain a key inventory that tracks which ciphertexts reference which
key versions.
Anti-Patterns
ECB mode for anything. ECB encrypts each block independently -- identical
plaintext blocks produce identical ciphertext blocks. The famous "ECB penguin"
demonstrates this visually: encrypting a bitmap image in ECB mode preserves the
image's visual pattern in the ciphertext. ECB leaks structural information about the
plaintext and must never be used for any purpose.
Nonce reuse with GCM or CTR. Reusing a nonce under the same key with GCM or CTR
modes completely breaks confidentiality and (for GCM) authenticity. Use random nonces
from a CSPRNG for each encryption operation, enforce nonce uniqueness through counters
or database constraints for high-volume systems, or switch to AES-GCM-SIV for
nonce-misuse resistance if uniqueness cannot be guaranteed architecturally.
Using encryption without authentication. AES-CBC or AES-CTR without a MAC allows
an attacker to flip bits in the ciphertext, producing modified plaintext that decrypts
without any error. The Efail attack (2018) exploited this in PGP and S/MIME email
encryption to exfiltrate plaintext through ciphertext manipulation. Always use AEAD
(GCM, ChaCha20-Poly1305) or the encrypt-then-MAC construction.
Hardcoded encryption keys. Embedding keys in source code, configuration files
committed to version control, environment variables baked into container images, or
client-side code. Keys must be stored in a dedicated secrets manager (HashiCorp Vault,
AWS KMS, GCP Cloud KMS, Azure Key Vault) and injected at runtime through secure
channels. Rotate keys on any suspicion of exposure.
Custom encryption schemes. Inventing novel cipher combinations, custom padding
schemes, "double encryption" with two algorithms, or "encryption" via XOR with a
static or repeated key. Use well-vetted, peer-reviewed library implementations of
standard algorithms (libsodium, OpenSSL, Web Crypto API, Go crypto/aes).
Cryptography is the one engineering discipline where cleverness consistently makes
things worse -- the attack surface of a custom scheme is unknown and unknowable
without years of public cryptanalysis.
1---2name: security-symmetric-encryption3description: Symmetric Encryption4---5# Symmetric Encryption67> AES-256-GCM for most use cases, ChaCha20-Poly1305 when hardware AES is unavailable --8> always use authenticated encryption, never roll your own910## When to Use1112- Encrypting data at rest (database fields, file storage, backups)13- Encrypting data in application-layer protocols (beyond TLS)14- Choosing between AES and ChaCha20 for a specific deployment target15- Selecting a mode of operation (GCM, CBC, CTR) for a symmetric cipher16- Reviewing code that performs encryption for correctness17- Designing a key management scheme for encrypted data1819## Threat Context2021Symmetric encryption defends against confidentiality breaches when an attacker gains22access to stored data (stolen database dumps, compromised backups, unauthorized file23system access) or intercepts data in transit. Without authenticated encryption (AEAD),24an attacker can also tamper with ciphertext without detection -- the padding oracle25attack against AES-CBC (CVE-2014-3566, POODLE) demonstrated this at scale, enabling26plaintext recovery through ciphertext manipulation. Key theft and nonce misuse represent27the two remaining catastrophic failure modes even when a correct algorithm is chosen.2829## Instructions30311. **Default to AES-256-GCM.** AES (Advanced Encryption Standard, Rijndael) with32 256-bit keys in GCM (Galois/Counter Mode) provides both confidentiality and integrity33 through authenticated encryption with associated data (AEAD). GCM produces a 128-bit34 authentication tag that detects any ciphertext modification. AES-256-GCM is35 NIST-approved, FIPS 140-2 compliant, and hardware-accelerated on all modern x8636 (AES-NI) and ARM (ARMv8 Crypto Extensions) processors. On hardware with AES-NI,37 AES-256-GCM achieves throughput exceeding 1 GB/s per core.38392. **Use ChaCha20-Poly1305 when AES hardware acceleration is unavailable.** ChaCha2040 is a stream cipher designed by Daniel Bernstein as a refinement of Salsa20, using a41 256-bit key and a 96-bit nonce. Combined with Poly1305 MAC, it provides AEAD42 equivalent in security to AES-GCM. ChaCha20-Poly1305 is faster in software on43 devices without AES-NI (IoT devices, older mobile chipsets, embedded systems). TLS 1.344 includes both AES-256-GCM and ChaCha20-Poly1305 as mandatory cipher suites. Google45 adopted ChaCha20-Poly1305 in Chrome for Android specifically because most ARM46 processors at the time lacked AES hardware acceleration.47483. **Never use unauthenticated modes in new systems.** AES-CBC (Cipher Block Chaining)49 without a separate HMAC is vulnerable to padding oracle attacks -- an attacker who can50 submit ciphertexts and observe whether decryption produces a padding error can recover51 the full plaintext byte-by-byte. AES-ECB (Electronic Codebook) is structurally broken:52 identical plaintext blocks produce identical ciphertext blocks, leaking patterns in the53 data. AES-CTR (Counter Mode) without a MAC provides confidentiality but allows54 undetected ciphertext bit-flipping -- an attacker who knows the plaintext at a given55 position can flip the corresponding ciphertext bit to produce any desired plaintext56 byte.57584. **Generate IVs/nonces correctly.** GCM requires a unique 96-bit nonce per encryption59 operation under the same key. Nonce reuse under GCM is catastrophic: it reveals the60 XOR of two plaintexts and exposes the GHASH authentication key, allowing forgery of61 authentication tags for arbitrary messages. Use a cryptographically secure pseudorandom62 number generator (CSPRNG) for random nonces. For systems encrypting more than 2^3263 messages under a single key (where random nonce collision probability becomes64 non-negligible by the birthday bound), use a deterministic construction such as65 AES-GCM-SIV, which provides nonce-misuse resistance at a modest performance cost.66675. **Key sizes: 256-bit for future-proofing.** AES-128 is not broken and provides68 128-bit security against classical computers, which is sufficient for current threats.69 AES-256 provides margin against theoretical quantum attacks -- Grover's algorithm70 reduces the effective key strength by half (256-bit becomes 128-bit effective), keeping71 AES-256 secure even in a post-quantum scenario. For all new systems, default to72 256-bit keys. The performance difference between AES-128 and AES-256 is approximately73 40% more rounds (14 vs 10) but negligible in practice with hardware acceleration.74756. **Key derivation from passwords.** Never use a password directly as an encryption key.76 Human-chosen passwords have far less entropy than required for cryptographic keys.77 Derive keys using Argon2id (preferred), scrypt, or PBKDF2-HMAC-SHA256 with a unique78 random salt (at least 128 bits) and sufficient cost parameters. The derived key must be79 exactly the length required by the cipher: 32 bytes for AES-256. Store the salt80 alongside the ciphertext (the salt is not secret). If deriving multiple keys from one81 password (e.g., one for encryption, one for MAC), use distinct info/context parameters82 in an HKDF-Expand step, never truncate or split a single derived key.83847. **Encrypt-then-MAC if forced to use CBC.** If a legacy system requires AES-CBC, apply85 HMAC-SHA256 to the ciphertext (not the plaintext) after encryption. Verify the MAC86 before decrypting -- reject any message with an invalid MAC without attempting87 decryption. This is the encrypt-then-MAC construction and is provably secure under88 standard assumptions. The two alternative compositions -- MAC-then-encrypt (used in89 TLS < 1.3, enabling BEAST and Lucky Thirteen) and encrypt-and-MAC (used in SSH,90 theoretically weaker) -- are both vulnerable to specific attack classes. Always use91 encrypt-then-MAC.9293## Details9495### Modes of Operation Comparison9697| Mode | Type | Parallelizable | Nonce-Sensitive | Notes |98| ------- | ---------------------- | ----------------------- | ------------------------ | --------------------------------------------------------------------------- |99| GCM | AEAD | Yes (encrypt + decrypt) | Catastrophic on reuse | Default choice for new systems |100| CBC | Confidentiality only | Decrypt only | IV must be unpredictable | Padding oracle risk; needs separate MAC |101| CTR | Confidentiality only | Yes (encrypt + decrypt) | Catastrophic on reuse | Needs separate MAC; basis for GCM |102| GCM-SIV | AEAD | Yes | Nonce-misuse resistant | Slight performance penalty; safe when nonce uniqueness cannot be guaranteed |103| XTS | Tweakable block cipher | Yes | N/A (uses tweak) | Designed for disk/sector encryption (LUKS, BitLocker); not for general use |104105### The Nonce Reuse Catastrophe106107When nonce N is reused with key K for two different plaintexts P1 and P2 under AES-GCM:108109- The keystream is identical for both encryptions (since CTR mode generates the keystream110 from the nonce).111- C1 XOR C2 = P1 XOR P2, revealing the XOR of the two plaintexts. With known or112 guessable plaintext fragments, this recovers both messages.113- The GHASH authentication key H is exposed through algebraic analysis of the two114 authentication tags. With H, the attacker can forge valid authentication tags for115 arbitrary ciphertexts under the same key -- a complete authenticity break.116- This is not theoretical: nonce reuse vulnerabilities have been discovered in production117 TLS implementations, and the GHASH key recovery attack has been demonstrated118 practically.119120### Associated Data (the "AD" in AEAD)121122GCM and ChaCha20-Poly1305 support additional authenticated data (AAD) -- data that is123integrity-protected but not encrypted. The authentication tag covers both the ciphertext124and the AAD, so any modification to either is detected.125126Use AAD for metadata that must not be modified but does not need confidentiality:127128- The database row ID or primary key (prevents ciphertext from being moved between rows)129- The encryption algorithm identifier (prevents downgrade attacks)130- The key version identifier (prevents ciphertext from being decrypted with the wrong131 key version)132- Any routing or addressing information that must remain in plaintext for the system to133 function134135### Key Rotation136137Encrypted data must remain decryptable after key rotation. The standard pattern:138139- Encrypt with the current active key. Store the key version/ID alongside the ciphertext140 (in the AAD or as a plaintext prefix).141- On decryption, look up the key by version ID and decrypt with the correct key.142- Re-encrypt data under the new key during a migration window (background job, lazy143 re-encryption on read, or bulk migration).144- Never delete old keys until all data encrypted under them has been verified as145 re-encrypted. Maintain a key inventory that tracks which ciphertexts reference which146 key versions.147148## Anti-Patterns1491501. **ECB mode for anything.** ECB encrypts each block independently -- identical151 plaintext blocks produce identical ciphertext blocks. The famous "ECB penguin"152 demonstrates this visually: encrypting a bitmap image in ECB mode preserves the153 image's visual pattern in the ciphertext. ECB leaks structural information about the154 plaintext and must never be used for any purpose.1551562. **Nonce reuse with GCM or CTR.** Reusing a nonce under the same key with GCM or CTR157 modes completely breaks confidentiality and (for GCM) authenticity. Use random nonces158 from a CSPRNG for each encryption operation, enforce nonce uniqueness through counters159 or database constraints for high-volume systems, or switch to AES-GCM-SIV for160 nonce-misuse resistance if uniqueness cannot be guaranteed architecturally.1611623. **Using encryption without authentication.** AES-CBC or AES-CTR without a MAC allows163 an attacker to flip bits in the ciphertext, producing modified plaintext that decrypts164 without any error. The Efail attack (2018) exploited this in PGP and S/MIME email165 encryption to exfiltrate plaintext through ciphertext manipulation. Always use AEAD166 (GCM, ChaCha20-Poly1305) or the encrypt-then-MAC construction.1671684. **Hardcoded encryption keys.** Embedding keys in source code, configuration files169 committed to version control, environment variables baked into container images, or170 client-side code. Keys must be stored in a dedicated secrets manager (HashiCorp Vault,171 AWS KMS, GCP Cloud KMS, Azure Key Vault) and injected at runtime through secure172 channels. Rotate keys on any suspicion of exposure.1731745. **Custom encryption schemes.** Inventing novel cipher combinations, custom padding175 schemes, "double encryption" with two algorithms, or "encryption" via XOR with a176 static or repeated key. Use well-vetted, peer-reviewed library implementations of177 standard algorithms (libsodium, OpenSSL, Web Crypto API, Go crypto/aes).178 Cryptography is the one engineering discipline where cleverness consistently makes179 things worse -- the attack surface of a custom scheme is unknown and unknowable180 without years of public cryptanalysis.