Cryptography · Modes and Authentication
What a Block Cipher Mode Adds to a Block Cipher
How chaining turns a single-block permutation into a construction for arbitrary-length data, why the initialization vector must be unpredictable rather than merely unique, and what error propagation costs.
A block cipher is a family of permutations indexed by a key. AES with a 128-bit key is a map from 128-bit strings to 128-bit strings, and for each key that map is a bijection with an inverse. This is the entire primitive. It says nothing about how to encrypt a file, a TLS record, or a database page, all of which have lengths that are not 16 bytes and are not even fixed. A mode of operation is the answer to that gap: a rule for applying the primitive repeatedly so that the result is still invertible and still hides the plaintext.
The word “mode” suggests a configuration option. It is closer to a construction with its own security definition. Two modes built on the same cipher can differ by orders of magnitude in what they resist, and the failures are structural rather than incidental — they survive correct key management, correct random number generation, and a correctly implemented cipher.
Independent blocks and what they leak
The simplest rule encrypts each 16-byte block on its own, with the same key, at every position. This is electronic codebook mode. It is invertible, it is parallel in both directions, and it is unusable for most data because the ciphertext block is a deterministic function of the plaintext block and nothing else.
Two consequences follow immediately. Identical plaintext blocks at different offsets produce identical ciphertext blocks, so the ciphertext preserves the plaintext’s equality pattern. A 16-byte-aligned region of a bitmap with a uniform colour, or a file of fixed-format records whose first field is often zero, becomes visible in the ciphertext as a repeating pattern. The mode has, in effect, published a codebook: a dictionary from plaintext block to ciphertext block that an attacker can query by getting known plaintext encrypted, and then look up.
The second consequence is subtler and matters more for protocols. Because the block is independent, an attacker who can move ciphertext blocks around can move plaintext blocks around. Blocks can be deleted, duplicated, reordered, or spliced between two messages encrypted under the same key, and decryption still succeeds and produces exactly the correspondingly rearranged plaintext. Nothing in the ciphertext binds a block to its position. ECB offers no integrity of any kind, but neither do the chaining modes below; that separation is the subject of the authenticated modes later in this cluster.
Chaining, and the cost of dependence
Cipher block chaining removes the position-independence by feeding the previous ciphertext block into the next encryption. With plaintext blocks $P_1 \dots P_n$, a key $K$, and an initial value $C_0 = \mathrm{IV}$:
$$C_i = E_K(P_i \oplus C_{i-1}), \qquad P_i = D_K(C_i) \oplus C_{i-1}$$
Each plaintext block is masked by the previous ciphertext block before encryption, so an attacker cannot predict the input to $E_K$ for any block beyond the first, and two identical plaintext blocks at different positions produce different ciphertext because their masks differ.
The direction of the dependency sets the performance envelope. Decryption of block $i$ needs $C_i$ and $C_{i-1}$, both of which are available as soon as the ciphertext is, so decryption is fully parallel and can be pipelined across all blocks. Encryption of block $i$ needs $C_{i-1}$, which does not exist until block $i-1$ has been encrypted. The chain is serial. On a processor with AES instructions, a single AES-128 encryption has a latency in the range of a few tens of cycles, and that latency — not the width of the execution pipeline — bounds CBC encryption throughput. The same hardware in counter mode, where every block is independent, can sustain multiple blocks per latency period. This is one of the reasons protocols moved away from CBC once authenticated modes became available: the serial chain was costing throughput even before the padding and integrity problems were counted.
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
)
func main() {
key := make([]byte, 16)
rand.Read(key)
block, _ := aes.NewCipher(key)
// 16 bytes of unpredictable state; not a secret, but the attacker
// must not be able to choose or predict it.
iv := make([]byte, aes.BlockSize)
rand.Read(iv)
plaintext := make([]byte, 3*aes.BlockSize) // block-aligned by construction
out := make([]byte, len(plaintext))
cipher.NewCBCEncrypter(block, iv).CryptBlocks(out, plaintext)
back := make([]byte, len(out))
cipher.NewCBCDecrypter(block, iv).CryptBlocks(back, out)
fmt.Println(len(out), len(back))
}
Why the IV must be unpredictable, not just unique
The initialization vector is often described as “random”, and that phrasing hides the actual requirement. For CBC it must be unpredictable to the attacker before the message is encrypted. It need not be secret: sending it in the clear alongside the ciphertext is standard, and the security analysis assumes the attacker sees it.
Uniqueness alone is not sufficient, and the historical counterexample is instructive. Early TLS used the last ciphertext block of the previous record as the IV of the next, which is unique per record and entirely predictable from data the attacker has already seen. Under a chosen-plaintext attack the attacker can then test a guess about the first plaintext block. Let the attacker know the current IV, want to test a guess $G$ for $P_1$, and know a ciphertext block $C_1$ that resulted from some earlier encryption with IV $V$. The attacker asks for a new encryption with IV $V’ = V \oplus G \oplus X$ for a chosen $X$; if the guess is right, the new first ciphertext block equals $E_K(V \oplus G \oplus X \oplus G) = E_K(V \oplus X)$, which the attacker can compare against a value it can compute or has observed. Guessing succeeds or fails with certainty, one block per query. Chaining the IV to previous ciphertext is exactly the predictability that makes this work.
The fix is to generate the IV from a source the attacker cannot predict, or to derive it from a per-message value the attacker cannot control. The same requirement, stated more generally, is that no IV may repeat under a given key across messages whose plaintexts an attacker might compare, because a repeated IV makes the first blocks of two messages XOR-comparable: $C_1 \oplus C_1’ = E_K(P_1 \oplus \mathrm{IV}) \oplus E_K(P_1’ \oplus \mathrm{IV})$, which for equal first blocks is zero.
Error propagation, length, and padding
CBC’s dependence also determines how damage spreads. A single bit flipped in ciphertext block $C_i$ produces a pseudorandom-looking corruption across the whole of $P_i$ — every bit of the block is affected, because the block goes through $D_K$ — and exactly one flipped bit in $P_{i+1}$, at the same offset, because $C_i$ is also the mask for the next block. From $P_{i+2}$ onward the plaintext is correct again. A lost or inserted block, by contrast, shifts the block boundaries and corrupts everything after it, since the mask for each subsequent block is wrong.
Length handling is the other structural cost. CBC requires each plaintext to be a whole number of blocks. The common solution appends padding: a byte value $b$ repeated $b$ times, with a full block of padding when the plaintext is already aligned, so that the padding is always present and unambiguous. This is the scheme specified for CMS and inherited by many libraries. It means the ciphertext is between one and sixteen bytes longer than the plaintext, and, more importantly, that the ciphertext length reveals the plaintext length rounded up to a multiple of sixteen. For a password field of 9 bytes and one of 20 bytes, the ciphertexts are 16 and 32 bytes.
That padding is also where CBC’s worst practical failure lives, because the receiver must distinguish valid from invalid padding before it can return a plaintext, and that distinction is observable. The next article in this cluster, on padding oracles in CBC, works through the byte-at-a-time recovery that follows from a single bit of that signal. Counter mode, described in CTR mode and the nonce space, removes padding entirely by turning the block cipher into a stream, at the price of a much stricter uniqueness requirement on its per-message value.
What the mode does not provide
Every mode discussed here is unauthenticated. CBC with a random IV hides plaintext from a passive observer and, under the standard definitions, from a chosen-plaintext attacker; it does not prevent modification. An attacker who can rewrite ciphertext can flip chosen bits of plaintext with certainty, as the error-propagation analysis above shows, and can splice blocks within a message. Encryption alone cannot distinguish a message the sender wrote from one an attacker edited, because both decrypt to something.
The historical pattern is worth naming because it recurred: a protocol uses CBC for confidentiality, adds a MAC computed over the plaintext, and then gets the composition order wrong. MAC-then-encrypt, where the tag is computed over plaintext and then encrypted along with it, permits attacks that use the decryption oracle’s padding behaviour without ever forging a tag. Encrypt-then-MAC, where the tag covers the ciphertext and the associated data, does not. This ordering question is treated in the article on padding oracles, and the constructions that fold authentication into the mode itself begin with GHASH in GCM.
A mode, then, is a contract with three parts: how state is initialized, how blocks depend on each other, and what the receiver must check before trusting output. CBC specifies the first two and leaves the third to whatever the protocol layers on top. The modes that followed were designed with the third part included, and the design pressure that produced them came from exactly the failures described above.
References
- NIST SP 800-38A: Recommendation for Block Cipher Modes of Operation — Methods and Techniques — NIST
- FIPS 197: Advanced Encryption Standard (AES) — NIST
- Evaluation of Some Blockcipher Modes of Operation — Phillip Rogaway, CRYPTREC report, 2011
- Nonce-Based Symmetric Encryption — Phillip Rogaway, FSE 2004