symmetric · level 2

Block Cipher Modes

ECB vs CBC vs CTR vs GCM — and why IVs matter.

180 XP

Block Cipher Modes

AES only encrypts 16 bytes at a time. To encrypt a whole file, email, or TCP stream, you need a mode that describes how to chain blocks together. The choice of mode is as important as the choice of cipher — most real-world AES failures are mode failures, not AES failures.

Analogy

Picture a warehouse whose only packing machine can wrap one small 16-kilo box at a time. To ship an entire truckload, a supervisor must decide how to feed the boxes through: wrap each box individually (anyone walking past can spot which boxes are identical), tie each new box to the previous one with a numbered tag so they must be unpacked in order, stamp each one with a running counter, or — best — wrap everything and slap a tamper-evident foil strip across the whole pallet. The packing machine (AES) is fine; the mode is the warehouse's shipping procedure, and picking a lazy one is how whole shipments get leaked at the loading dock.

The four modes you need to know

ECB — Electronic Codebook (the one you don't use)

Each block encrypted independently. Same plaintext block always maps to the same ciphertext block. Never use ECB for real data. See the previous lesson.

CBC — Cipher Block Chaining

Each plaintext block is XOR-ed with the previous ciphertext block before encryption. Block 0 is XOR-ed with an IV (initialisation vector) provided at encryption time.

C[0] = AES(K, P[0] XOR IV)
C[i] = AES(K, P[i] XOR C[i-1])
  • Requires padding (plaintext must be a multiple of 16 bytes — PKCS#7, next lesson).
  • Sequential: decryption needs the previous ciphertext block, so you can't seek.
  • No integrity: an attacker can flip bits to cause specific changes in the plaintext (this is the foundation of the padding oracle attack).

CTR — Counter mode

Turns AES into a stream cipher. For each block position i, build a unique input nonce ∥ i, encrypt that, and XOR the result into the plaintext.

keystream[i] = AES(K, nonce ∥ counter+i)
C[i] = P[i] XOR keystream[i]
  • No padding — the output is exactly as long as the input.
  • Random access: each block is independent, you can seek anywhere.
  • Parallelisable for speed.
  • Still no integrity — an attacker flipping a bit flips the same bit in the plaintext.

GCM — Galois/Counter Mode (the one you default to)

CTR mode plus an authentication tag over both the ciphertext and an optional "additional authenticated data" (AAD) header. If anyone tampers with the ciphertext, decryption fails.

(ciphertext, tag) = AES-GCM-Enc(K, nonce, plaintext, AAD)
  • AEAD: Authenticated Encryption with Associated Data.
  • 96-bit nonce is standard. Never reuse a nonce with the same key — this destroys both confidentiality and authenticity.
  • Supported natively in TLS 1.2/1.3, JWE, and Web Crypto.

IVs and nonces — the rules

Mode Name Must be unique? Must be unpredictable?
CBC IV yes, per message yes, random
CTR nonce yes, per message no (counter is fine)
GCM nonce yes, per (key, message) no

Nonce reuse in CTR or GCM is catastrophic: the keystream repeats, and XOR-ing two ciphertexts cancels the key entirely. Any pair of messages encrypted with the same (key, nonce) can be recovered up to their XOR.

IVs and nonces are not secrets. You can store or transmit them alongside the ciphertext. Most libraries prepend the IV to the ciphertext by convention.

Which one should I use?

Default to AES-GCM. It's fast, authenticated, and supported everywhere. Use CTR only when you need raw stream semantics without integrity (rare). Use CBC only when you're forced to by a legacy protocol. Never use ECB.

If you need random access into a large encrypted file (full-disk encryption, encrypted databases), look at AES-XTS — a specialised mode for that use case.

Takeaways

  1. ECB leaks, CBC chains, CTR seeks, GCM authenticates.
  2. IV/nonce = unique per message. Never reuse with the same key.
  3. When in doubt, AES-GCM.