AnyLearn
All lessons
Programmingadvanced

Symmetric Ciphers and Modes of Operation

AES and block ciphers are primitive building blocks, not complete encryption schemes. Learn how ECB leaks structure, why CBC and CTR modes work differently, and why GCM is the modern default — including the catastrophic consequences of nonce reuse.

Not signed in — your progress and quiz score won't be saved.
Lesson progress1 / 9

Block ciphers vs stream ciphers

A block cipher (AES, 3DES) transforms a fixed-size chunk of plaintext into ciphertext using a key. AES operates on 128-bit blocks with 128-, 192-, or 256-bit keys. The block cipher itself is a permutation — given the same block and key, you always get the same output. That's a problem, not a feature.

A stream cipher (ChaCha20, RC4) generates a keystream from a key and a nonce, then XORs it with the plaintext byte-by-byte. Stream ciphers are faster on hardware without AES-NI and have no block-alignment issues. CTR mode turns AES into a stream cipher. The distinction blurs in practice — what matters is the mode wrapping the primitive.

Full lesson text

All 9 steps on one page — for reading, reference, and search.

Show

1. Block ciphers vs stream ciphers

A block cipher (AES, 3DES) transforms a fixed-size chunk of plaintext into ciphertext using a key. AES operates on 128-bit blocks with 128-, 192-, or 256-bit keys. The block cipher itself is a permutation — given the same block and key, you always get the same output. That's a problem, not a feature.

A stream cipher (ChaCha20, RC4) generates a keystream from a key and a nonce, then XORs it with the plaintext byte-by-byte. Stream ciphers are faster on hardware without AES-NI and have no block-alignment issues. CTR mode turns AES into a stream cipher. The distinction blurs in practice — what matters is the mode wrapping the primitive.

2. ECB mode: why it leaks everything

Electronic Codebook (ECB) encrypts each block independently: Ci=EK(Pi)C_i = E_K(P_i). This looks simple and parallelizable — it's also broken for any real data.

The penguin attack: encrypt a bitmap image with AES-ECB and the block boundaries in the image become visible, because identical 16-byte plaintext blocks produce identical ciphertext blocks. No attacker needs the key; they just observe that Ci=CjC_i = C_j implies Pi=PjP_i = P_j.

ECB also enables cut-and-paste attacks: rearranging ciphertext blocks rearranges the corresponding plaintext blocks. Never use ECB for anything except a single isolated block (e.g., wrapping another key with AES-KW, which adds its own integrity check).

3. CBC mode: chaining and its costs

Cipher Block Chaining (CBC) XORs each plaintext block with the previous ciphertext block before encrypting:

Ci=EK(PiCi1),C0=IVC_i = E_K(P_i \oplus C_{i-1}), \quad C_0 = \text{IV}

The IV must be unpredictable (random) per message — not secret, but random. If an attacker can predict the IV before choosing plaintext, they can mount chosen-plaintext attacks (as in BEAST against TLS 1.0).

CBC encryption is sequential (can't parallelize), but decryption is parallelizable. It also requires PKCS#7 padding to fill the last block — and padding oracles (Vaudenay 2002, POODLE) have broken countless CBC-MAC schemes. If you use CBC, always pair it with a separate MAC (Encrypt-then-MAC, not MAC-then-Encrypt).

4. CTR mode: turning AES into a stream cipher

Counter (CTR) mode generates keystream blocks by encrypting a counter:

Ci=PiEK(noncei)C_i = P_i \oplus E_K(\text{nonce} \| i)

The nonce (number used once) plus counter fills a 128-bit block. Encryption and decryption are identical, both are fully parallelizable, and there's no padding needed. CTR is fast and simple.

The catastrophic gotcha: reuse a nonce with the same key and you have C1C2=P1P2C_1 \oplus C_2 = P_1 \oplus P_2, which destroys confidentiality completely. Attackers can recover both plaintexts from known plaintext fragments. This is the "two-time pad" problem — CTR is a stream cipher and stream ciphers must never reuse key+nonce pairs. No exceptions.

5. GCM: authenticated encryption built in

Galois/Counter Mode (GCM) = CTR confidentiality + GHASH authentication tag. It is the canonical AEAD (Authenticated Encryption with Associated Data) mode for AES.

GCM produces a 128-bit authentication tag alongside the ciphertext. It also authenticates associated data (AAD) — headers, nonces, packet metadata — that travel in plaintext but must not be tampered with. Any bit flip in ciphertext or AAD causes tag verification to fail before any plaintext is returned.

Nonce reuse in GCM is worse than in CTR: an attacker who sees two ciphertexts under the same key+nonce can recover the authentication key (the GHASH key), allowing them to forge arbitrary messages forever. Use a 96-bit random nonce; at 2^32 messages, birthday collision probability exceeds 1%.

6. Comparison: CBC vs CTR vs GCM

PropertyCBCCTRGCM
ConfidentialityYes (with random IV)Yes (with unique nonce)Yes
Integrity/AuthNo (needs separate MAC)NoYes (built-in tag)
Parallel encryptNoYesYes
Padding requiredYes (PKCS#7)NoNo
Nonce/IV typeRandom (unpredictable)Unique (can be counter)Unique, 96-bit preferred
Nonce reuse impactBad (CBC-R attacks)Catastrophic (XOR leak)Catastrophic (key recovery)
Recommended todayOnly with HMACPrefer GCMYes — first choice

For modern systems, AES-256-GCM is the answer unless you have a specific hardware constraint.

7. AEAD: the right abstraction

AEAD is an interface, not an algorithm. The contract: seal(key, nonce, plaintext, aad)(ciphertext, tag), and open(key, nonce, ciphertext, tag, aad)plaintext or error. The critical rule: never release plaintext until the tag passes. MAC-then-decrypt implementations that return partial plaintext before verifying the tag are the padding oracle of AEAD.

Alternatives to AES-GCM worth knowing:

  • ChaCha20-Poly1305: Preferred when hardware AES acceleration isn't available (mobile, IoT). Used in TLS 1.3.
  • AES-SIV (RFC 5297): Nonce-misuse-resistant — nonce reuse leaks only whether plaintexts are equal, not the plaintext itself.
  • AES-GCM-SIV: Combines AES-GCM performance with SIV's nonce-misuse resistance.

8. AEAD encrypt/decrypt in Python

Using cryptography (pyca) — the right library for Python:

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

key = AESGCM.generate_key(bit_length=256)  # 32 bytes, from /dev/urandom
aead = AESGCM(key)

nonce = os.urandom(12)          # 96-bit nonce, never reuse with same key
aad = b"user_id=42,version=1"  # authenticated but not encrypted
plaintext = b"transfer $1000 to Alice"

ciphertext = aead.encrypt(nonce, plaintext, aad)
# ciphertext includes the 16-byte GCM tag appended

recovered = aead.decrypt(nonce, ciphertext, aad)
# raises InvalidTag if anything was tampered with
assert recovered == plaintext

Send (nonce, ciphertext) together; nonce is not secret. Store key separately — in a KMS or HSM, not next to the ciphertext.

9. Nonce generation strategies

Getting nonces right is the hardest part of symmetric encryption in practice:

  • Random 96-bit nonce: Simple, works well up to ~2^32 messages per key (birthday bound). Use os.urandom(12) or equivalent CSPRNG.
  • Counter + synchronized state: Eliminates birthday collision risk, but requires durable state across crashes and distributed nodes. Fencing tokens or sequence numbers in a DB work.
  • Random 192-bit nonce (XSalsa20, XChaCha20): Extended nonces make random-per-message safe for far more messages — ~2^96 messages before 1% collision risk.

Key rotation is the backstop: rotate keys well before hitting birthday bounds. A key used for 2^32 GCM messages has ~1% chance of nonce collision — at that point, the encryption scheme's security guarantees are gone regardless of how random your nonces are.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. Why does ECB mode leak information even when the key is secret?
    • ECB uses a weak key schedule that can be reversed.
    • Identical plaintext blocks produce identical ciphertext blocks, revealing structure.
    • ECB skips the final round of AES, making it vulnerable to brute force.
    • ECB requires a predictable IV that exposes the first block.
  2. You encrypt two different messages with AES-CTR using the same key and the same nonce. What can an attacker immediately recover?
    • The key, via the GHASH polynomial.
    • The XOR of the two plaintexts, enabling recovery of both if one is partially known.
    • The nonce, by solving the discrete log over GF(2^128).
    • Nothing — CTR mode is unconditionally secure as long as the key is secret.
  3. GCM nonce reuse is considered worse than CTR nonce reuse because:
    • GCM uses a shorter nonce, so collisions are more likely.
    • An attacker can recover the GHASH authentication key, enabling arbitrary message forgery.
    • GCM falls back to ECB mode when nonces repeat.
    • The GHASH tag doubles in size on reuse, leaking key bits directly.
  4. What is the role of Associated Data (AAD) in AEAD?
    • AAD is encrypted alongside the plaintext to extend the keystream.
    • AAD is authenticated but not encrypted — tampering with it causes decryption to fail.
    • AAD replaces the nonce when the nonce is omitted.
    • AAD is a secondary plaintext that is encrypted with a derived key.
  5. Which property makes AES-GCM-SIV preferable to AES-GCM in some deployments?
    • GCM-SIV uses a 256-bit tag instead of 128-bit, providing stronger authentication.
    • GCM-SIV is nonce-misuse resistant — nonce reuse leaks only whether plaintexts are equal, not the plaintexts themselves.
    • GCM-SIV is faster because it skips the GHASH computation entirely.
    • GCM-SIV supports arbitrary-length nonces, eliminating the birthday collision problem.

Related lessons