CS 161, Lesson 21, in 56 slides. It explains why CBC needs PKCS#7 padding while CTR does not, works the parallelization trade-offs between CBC and CTR, and shows why reusing an IV is catastrophic for CTR but merely contained for CBC. This is where IND-CPA is won or lost in practice. It is anchored to textbook sections 6.7 to 6.9.
Subject: Computer Security · 84 slides · applied lesson
Open the interactive version of this deck · Homework for this lesson
Title
CS 161 · Lesson 21 of 45
PKCS#7 padding · the CBC-vs-CTR trade-off · why IV reuse can be catastrophic
Objectives
Warm-up
Discussion prompt
Before we open L21 · Padding (PKCS#7), Parallelization Trade-offs & IV Reuse: without looking back, what was the main idea of L20 · Block Ciphers, PRPs & Modes of Operation (ECB/CBC/CTR), and what could you do by the end of it that you could not do before?
Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.
Answer:
CS 161, Lesson 20, in 52 slides. It explains what a block cipher is - a keyed permutation - why AES on its own is not IND-CPA even though it is a strong PRP, and how the modes of operation ECB, CBC, and CTR, together with parallelization, turn the primitive into a usable scheme. It is anchored to textbook sections 6.4 to 6.7.
Concept
L20 built CBC and CTR and proved they can be IND-CPA. This lesson closes the three engineering gaps that decide whether they actually are, in practice.
Matching
Match the pairs
From Three loose ends from the modes lecture — match each one to what it actually does. The descriptions have been shuffled.
Why: What if it doesn't fit?, Which mode is faster?, What if the IV repeats? are easy to tell apart while they are sitting next to their descriptions and much harder afterwards, which is what this checks.
Concept
Throughout, the block size is 128 bits = 16 bytes — the AES block size. Every padding count, table, and edge case below is measured against that one number.
\[ \text{block size} = 128\ \text{bits} = 16\ \text{bytes} \]
Section
Part 1 · §6.8 the short-block problem
Concept
A block cipher is a fixed-width gadget: it takes exactly 128 bits in and gives exactly 128 bits out. It has no notion of a 'partial' input.
CBC chains by feeding each plaintext block, ⊕'d with the previous ciphertext block, into that 128-bit gadget. So every plaintext block must be a full 128 bits.
Counterexample
Discussion prompt
A block cipher is a fixed-width gadget: it takes exactly 128 bits in and gives exactly 128 bits out. It has no notion of a 'partial' input.
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Answer:
CBC chains by feeding each plaintext block, ⊕'d with the previous ciphertext block, into that 128-bit gadget. So every plaintext block must be a full 128 bits.
Concept
If the plaintext length isn't a multiple of 128 bits, the last CBC block comes up short. Say the final block is only 100 bits long.
\[ C_i = \mathrm{Enc}(K,\; M_i \oplus C_{i-1}) \]
To form that block, CBC wants to compute M_last ⊕ C_prev. But M_last is 100 bits and C_prev is 128 bits — and ⊕ needs two equal-length operands.
Analogy
Discussion prompt
Explain §6.8 The problem: a short last block by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
If the plaintext length isn't a multiple of 128 bits, the last CBC block comes up short. Say the final block is only 100 bits long.
Intuition
⊕ is bitwise: it pairs up bit 1 with bit 1, bit 2 with bit 2, and so on. With 100 bits on one side and 128 on the other, 28 bits have no partner. There's simply nothing to XOR them against.
Even if you forced the 100-bit result through somehow, the block cipher wouldn't accept it — its input port is exactly 128 bits wide. The short block can't be fed in.
Ask yourself: what's the cheapest way to make a 100-bit block into a 128-bit block? (Add 28 more bits — that's all padding is.)
Explain it
Discussion prompt
Explain §6.8 Why the short block is genuinely stuck to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
Even if you forced the 100-bit result through somehow, the block cipher wouldn't accept it — its input port is exactly 128 bits wide. The short block can't be fed in.
Ranking
Put in order
Put the moves of §6.8 Trace the failure on a 100-bit tail into the order they have to happen.
Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. This is the generic 'length not a multiple of 128' case — most real messages land here.
Worked example
Take a message whose last block has only 100 bits, with C_prev a full 128-bit ciphertext block
Why: This is the generic 'length not a multiple of 128' case — most real messages land here.
Attempt M_last ⊕ C_prev
Why: ⊕ is defined only on equal-length operands; 100 vs 128 leaves 28 bits unpaired, so the operation is undefined.
Attempt to feed the result into Enc(K, ·) anyway
Why: The block cipher's input is fixed at 128 bits, so even a well-formed 100-bit string can't enter it.
Conclude: pad M_last up to 128 bits BEFORE the ⊕
Why: Padding to a multiple of the block size is the only fix that makes both the ⊕ and the block cipher well-defined — so CBC must pad.
Blank canvas
Draw it
Draw what §6.8 Trace the failure on a 100-bit tail just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'The last block is 100 bits — just XOR it with the first 100 bits of C_prev and drop the other 28. No padding needed.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Now you have a 100-bit value, but the block cipher Enc(K, ·) still demands a 128-bit input — that input is undefined for the block cipher, so CBC can't continue.
A student: how do we make the last CBC block valid?
Why: Now you have a 100-bit value, but the block cipher Enc(K, ·) still demands a 128-bit input — that input is undefined for the block cipher, so CBC can't continue.
Trap
A student: 'The last block is 100 bits — just XOR it with the first 100 bits of C_prev and drop the other 28. No padding needed.'
Truncate C_prev to 100 bits and XOR
Why: Now you have a 100-bit value, but the block cipher Enc(K, ·) still demands a 128-bit input — that input is undefined for the block cipher, so CBC can't continue.
A student: how do we make the last CBC block valid?
Pad M_last out to a full 128 bits, THEN XOR with the 128-bit C_prev and encrypt
Why: §6.8: only a full-width block can pass through both ⊕ and the block cipher. Truncating is undefined; padding is the defined fix.
Section
Part 2 · §6.8 the right scheme
Concept
Padding only works if the receiver can strip exactly the bytes you added — no more, no less. So the rule isn't just 'fill to a multiple of 128'; it must be unambiguous on the way back.
The depadder sees only the decrypted bytes. From those bytes alone it has to know where the real message ends.
Step zero
Discussion prompt
§6.8 Depad must undo padding exactly — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.
Hint: It starts with: The sender pads, encrypts, and transmits; the receiver decrypts and…
Answer:
Worked example
The sender pads, encrypts, and transmits; the receiver decrypts and gets padded plaintext
Why: Decryption recovers M plus whatever bytes were appended — the receiver must now find and remove exactly those bytes.
If the receiver strips too few bytes, junk pad bytes stay in M
Why: The message is corrupted with trailing garbage that was never part of it.
If the receiver strips too many bytes, real message bytes are lost
Why: Now genuine data is gone. Either error means the padding scheme failed its one job.
Verify: the scheme must let the receiver compute the EXACT pad length from the bytes alone
Why: §6.8: padding is correct only if depadding is unambiguous — this is precisely what PKCS#7 guarantees and 'all 1s' does not.
Intuition
Tempting idea: fill the tail with 1 bits. Quick, simple. But now decrypt and look at the last byte: 0000000010111111. How many of those trailing 1s were padding?
You can't tell. Maybe the message ended in real 1 bits; maybe they were all padding. The scheme is ambiguous, so depadding is impossible. We need padding that encodes its own length.
Ask yourself: what's the smallest thing you could write into the pad so the receiver always knows how much to remove? (The count itself.)
Concept
PKCS#7 padding — To pad a message, compute N = the number of padding bytes needed to reach a multiple of the block size, then append N bytes, each holding the value N. To depad, read the last byte to get N and strip that many bytes.
The padding literally writes down its own length, repeated. The final byte always tells the receiver exactly how many bytes to remove.
Step zero
Discussion prompt
§6.8 Pad and depad a 3-short message — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.
Hint: It starts with: Suppose the message is 3 bytes short of a 16-byte block, so N = 3
Answer:
Worked example
Suppose the message is 3 bytes short of a 16-byte block, so N = 3
Why: N is whatever it takes to reach the next multiple of the block size — here, 3 bytes.
Append three bytes, each equal to 0x03: … 03 03 03
Why: PKCS#7 rule: append N bytes each of value N. The pad encodes its own length three times over.
\[ M \;\Vert\; \texttt{03}\ \texttt{03}\ \texttt{03} \]
To depad: decrypt, read the last byte (0x03), strip 3 bytes
Why: The last byte names N unambiguously, so the receiver removes exactly the 3 bytes that were added — recovering M exactly.
Notation
Annotate
From §6.8 Pad and depad a 3-short message — read this one piece at a time. What is each part doing?
On: \( M \;\Vert\; \texttt{03}\ \texttt{03}\ \texttt{03} \)
Concept
What if the plaintext is already an exact multiple of the block size? Then N = 0 padding bytes 'needed' — but appending nothing breaks the rule that the last byte always names the pad length.
PKCS#7's fix: append a whole new block of padding — 16 bytes, each 0x10 (decimal 16). There is now always exactly one unambiguous padding pattern, even for aligned messages.
Ranking
Put in order
Put the moves of §6.8 Why the aligned case must add a full block into the order they have to happen.
Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. It already fits the block cipher, so adding nothing seems harmless.
Worked example
Suppose M is exactly 32 bytes — two full blocks — and we add NO padding
Why: It already fits the block cipher, so adding nothing seems harmless.
Now imagine a DIFFERENT message that genuinely ended in the byte 0x10 by coincidence
Why: The depadder, seeing a final 0x10, would strip 16 real message bytes — corrupting a legitimate message.
Fix: when aligned, append a full 16-byte block of 0x10
Why: Now the receiver ALWAYS reads the last byte as a pad count and ALWAYS strips that many — there is never a case with no padding to interpret.
Verify: depad reads 0x10 = 16, strips exactly 16 bytes, recovers the original 32-byte M
Why: §6.8: a single, always-present padding pattern is what keeps depadding unambiguous in every case.
Intuition
PKCS#7 could in principle write the count once. Repeating it N times is what makes depadding robust and self-describing: the very last byte — wherever it lands — names the length, every time.
And the values 1 through 16 fit in a single byte, which is exactly the range of possible pad lengths for a 16-byte block. The count and the byte width line up perfectly.
Ask yourself: for a 16-byte block, what's the largest pad length you'd ever write — and does it fit in one byte? (16 = 0x10, yes.)
Concept
One table covers every case. Read it as: how short the message is → what you append → how the receiver reads it back.
| Padding bytes needed (N) | Bytes appended | How depad reads it |
|---|---|---|
| 3 | 03 03 03 | Last byte = 3 → strip 3 bytes |
| 1 | 01 | Last byte = 1 → strip 1 byte |
| 7 | 07 07 07 07 07 07 07 | Last byte = 7 → strip 7 bytes |
| 0 (already aligned) | a full block: 10 × (0x10) | Last byte = 16 → strip 16 bytes |
Note the bottom row: 'needs 0' still appends a whole 16-byte block. That is the non-negotiable part of PKCS#7.
Comparison
Comparison matrix
From §6.8 The PKCS#7 reference table: refill the Bytes appended column from what you know. The rest of the table is as it appeared.
| Padding bytes needed (N) | Bytes appended | How depad reads it |
|---|---|---|
| 3 | 03 03 03 | Last byte = 3 → strip 3 bytes |
| 1 | 01 | Last byte = 1 → strip 1 byte |
| 7 | 07 07 07 07 07 07 07 | Last byte = 7 → strip 7 bytes |
| 0 (already aligned) | a full block: 10 × (0x10) | Last byte = 16 → strip 16 bytes |
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'My plaintext is exactly 48 bytes — three whole blocks. It fits the cipher perfectly, so PKCS#7 adds nothing.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Now depadding is ambiguous: if the real last byte happens to be a small value, the receiver can't tell message bytes from pad bytes.
A student: what does PKCS#7 do to a block-aligned message?
Why: Now depadding is ambiguous: if the real last byte happens to be a small value, the receiver can't tell message bytes from pad bytes. The scheme breaks.
Trap
A student: 'My plaintext is exactly 48 bytes — three whole blocks. It fits the cipher perfectly, so PKCS#7 adds nothing.'
Append zero padding to the aligned message
Why: Now depadding is ambiguous: if the real last byte happens to be a small value, the receiver can't tell message bytes from pad bytes. The scheme breaks.
A student: what does PKCS#7 do to a block-aligned message?
Append a FULL extra block of 16 bytes, each 0x10
Why: §6.8 / RFC 5652: PKCS#7 always adds 1–16 bytes, never 0. The aligned case gets a whole block so the last byte always names a valid pad length.
Section
Part 3 · §6.8 stream-like modes
Concept
CTR runs the block cipher on a counter, not on the plaintext. It produces a keystream and ⊕s the plaintext with it — the plaintext is never an input to Enc.
\[ C_i = M_i \oplus \mathrm{Enc}(K,\; \text{IV} \Vert i) \]
Because the ciphertext is never fed back into the block cipher, a short final block creates no width mismatch at the cipher's input. CTR is essentially a stream cipher.
Intuition
Think of CTR as manufacturing a long pseudorandom pad — one block of keystream per counter value — and XORing the message onto it, exactly like a one-time pad.
If the message is shorter than the pad, you just throw away the extra pad bits. A 100-bit tail XORs against the first 100 keystream bits; the remaining 28 keystream bits are discarded. The last ciphertext block is simply 100 bits.
Ask yourself: with a one-time pad, does it matter that you generated more pad than message? (No — extra pad is harmless, you just don't use it.)
Step zero
Discussion prompt
§6.8 Encrypt and decrypt a 100-bit tail in CTR — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.
Hint: It starts with: Generate the keystream block for the final counter: K_last = Enc(K…
Answer:
Worked example
Generate the keystream block for the final counter: K_last = Enc(K, IV ‖ i), a full 128 bits
Why: CTR always produces full 128-bit keystream blocks — the cipher input is the counter, which is always full width.
XOR the 100-bit plaintext tail with the FIRST 100 bits of K_last; discard the remaining 28
Why: Only as much keystream as there is plaintext is used; the surplus pad bits are thrown away, OTP-style.
Emit a 100-bit final ciphertext block — no padding added
Why: The ciphertext tail is the same length as the plaintext tail, so the message length is preserved with zero overhead.
Verify decryption mirrors it: regenerate K_last, XOR the first 100 bits with the 100-bit ciphertext tail
Why: M ⊕ K ⊕ K = M. The receiver recreates the same keystream and truncates identically — recovering the exact 100-bit tail.
Sorting
Sort into buckets
These are the pieces of L21 · Padding (PKCS#7), Parallelization Trade-offs & IV Reuse, out of order. Put each one back under the part of the lesson it belongs to.
Concept
The whole §6.8 story collapses into one contrast: feedback into the block cipher forces padding; a keystream you can trim does not.
| Short last block | CBC | CTR |
|---|---|---|
| Plaintext enters Enc? | Yes (via ⊕ with C_prev) | No — only the counter does |
| Width mismatch? | Yes — undefined ⊕ / cipher input | No — XOR only the bits you have |
| Fix | Pad to a full block (PKCS#7) | Truncate the keystream |
| Ciphertext length | Rounded up to a block multiple | Same length as the plaintext |
Trade off
Comparison matrix
From §6.8 Side by side: CBC must pad, CTR truncates: every row here is a choice with a cost. Fill the CBC column, then say which row you would actually pick and what you give up for it.
| Short last block | CBC | CTR |
|---|---|---|
| Plaintext enters Enc? | Yes (via ⊕ with C_prev) | No — only the counter does |
| Width mismatch? | Yes — undefined ⊕ / cipher input | No — XOR only the bits you have |
| Fix | Pad to a full block (PKCS#7) | Truncate the keystream |
| Ciphertext length | Rounded up to a block multiple | Same length as the plaintext |
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'Block ciphers work on 128-bit blocks, so EVERY mode has to pad short messages — CTR included.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Unnecessary, and it changes the ciphertext length for no reason.
A student: which modes actually need padding?
Why: Unnecessary, and it changes the ciphertext length for no reason. CTR feeds the counter — not the plaintext — into the cipher, so a short tail is never a problem.
Trap
A student: 'Block ciphers work on 128-bit blocks, so EVERY mode has to pad short messages — CTR included.'
Add PKCS#7 padding to a CTR message
Why: Unnecessary, and it changes the ciphertext length for no reason. CTR feeds the counter — not the plaintext — into the cipher, so a short tail is never a problem.
A student: which modes actually need padding?
Only block-feedback modes like CBC pad; stream-like modes like CTR truncate the keystream instead
Why: §6.8: padding is required when the plaintext is fed into the block cipher. CTR never does that, so it needs no padding at all.
Section
Part 4 · §6.9 fresh IVs are mandatory
Intuition
The real question for any mode is simple: does the plaintext ever get fed INTO the block cipher? If yes, every input must be exactly 128 bits — so you must pad.
CBC feeds M ⊕ C_prev into Enc, so it pads. CTR feeds only the counter into Enc and XORs the plaintext outside the cipher, so it doesn't. One structural question decides padding for the whole mode.
Ask yourself: for a brand-new mode you've never seen, how would you predict whether it needs padding? (Check whether plaintext enters the block cipher.)
Concept
ECB is deterministic — the same plaintext block always gives the same ciphertext block, which leaks (L20). Every secure mode adds a random IV so that encrypting the same plaintext twice gives different ciphertext.
So the rule is absolute: always use a fresh, random, unpredictable IV for every encryption. The IV is what makes the scheme randomized — and randomization is what buys IND-CPA.
Concept
Reusing an IV throws away the one thing the IV was for. With a fixed IV, encrypting the same plaintext twice gives the same ciphertext again — the scheme is deterministic again.
And from L18 we know determinism breaks IND-CPA. So IV reuse is not a minor slip; it is a return to a leaking scheme. But HOW badly it leaks depends on the mode.
Intuition
CTR's keystream depends only on the key and the IV/nonce. Reuse the IV, and you reuse the exact same keystream for a second message — the textbook two-time pad mistake from L19.
With a two-time pad, XOR the two ciphertexts and the keystream cancels, handing the attacker M ⊕ M′ — the bitwise XOR of the two plaintexts. That's catastrophic: known structure in one message peels the other open.
Ask yourself: in C = M ⊕ K and C′ = M′ ⊕ K with the SAME K, what is C ⊕ C′? (The K's cancel: M ⊕ M′.)
Step zero
Discussion prompt
§6.9 Compute the CTR two-time-pad leak — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.
Hint: It starts with: Encrypt M under nonce IV: C = M ⊕ K, where K = the CTR keystream from…
Answer:
Worked example
Encrypt M under nonce IV: C = M ⊕ K, where K = the CTR keystream from (key, IV)
Why: CTR is a one-time pad whose pad K is fixed once the key and IV are fixed.
Reuse the SAME IV to encrypt M′: C′ = M′ ⊕ K
Why: Same key, same IV ⇒ identical keystream K. This is the forbidden reuse.
\[ C \oplus C' = (M \oplus K) \oplus (M' \oplus K) = M \oplus M' \]
The attacker, seeing C and C′, computes C ⊕ C′ and obtains M ⊕ M′
Why: The keystream cancels entirely. Eve never needs the key — she gets the XOR of the two plaintexts directly.
Verify the damage: any guessed/known bytes of M reveal the same bytes of M′, and vice versa
Why: §6.9: this is exactly the L19 two-time pad. CTR IV reuse is catastrophic — it leaks plaintext relationships outright.
Notation
Annotate
From §6.9 Compute the CTR two-time-pad leak — read this one piece at a time. What is each part doing?
On: \( C \oplus C' = (M \oplus K) \oplus (M' \oplus K) = M \oplus M' \)
Concept
CBC also becomes deterministic under a reused IV, but the leak is contained. It only reveals whether two messages start with the same blocks — up to the first block where they differ.
Because each CBC block is chained through the unpredictable previous ciphertext, the moment the two plaintexts differ, their ciphertext streams diverge and stay divergent. Eve learns the shared prefix length, nothing more.
Ranking
Put in order
Put the moves of §6.9 Trace the CBC shared-prefix leak into the order they have to happen.
Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. The two messages share their first two blocks and differ only in the third.
Worked example
Encrypt M = [P1, P2, P3] and M′ = [P1, P2, Q3] under the SAME IV
Why: The two messages share their first two blocks and differ only in the third.
Block 1: both compute Enc(K, P1 ⊕ IV) → the SAME C1
Why: Same IV, same P1 ⇒ identical first ciphertext block. Eve sees C1 = C1′ and learns the first blocks match.
Block 2: both compute Enc(K, P2 ⊕ C1) → the SAME C2
Why: The chaining input is identical (same P2, same C1), so C2 = C2′. Eve learns the second blocks match too.
Block 3: P3 ⊕ C2 ≠ Q3 ⊕ C2, so C3 ≠ C3′ — and everything after diverges
Why: The first differing block breaks the chain; from here the ciphertexts share nothing. Eve learns only the shared-prefix length — not M ⊕ M′.
Verify the contrast: CBC leaked a prefix, CTR leaked M ⊕ M′ entirely
Why: §6.9: CBC reuse is contained (a structural prefix hint); CTR reuse is catastrophic (full plaintext-XOR). Same mistake, very different blast radius.
Blank canvas
Draw it
Draw what §6.9 Trace the CBC shared-prefix leak just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Intuition
Knowing M ⊕ M′ sounds abstract, but it's a crowbar. Wherever you can guess bytes of one message — a fixed header, a known greeting, a protocol field — you XOR them out and read the same bytes of the OTHER message for free.
With three or more messages under one reused nonce, natural-language redundancy alone is often enough to recover all of them. This is why CTR nonce reuse is treated as a total break.
Ask yourself: if you know M starts with 'GET /' and you hold M ⊕ M′, what do you immediately learn about M′? (Its first five bytes.)
Explain it
Discussion prompt
Explain §6.9 Reading the M ⊕ M′ leak like an attacker to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
With three or more messages under one reused nonce, natural-language redundancy alone is often enough to recover all of them. This is why CTR nonce reuse is treated as a total break.
Concept
| Mode | Effect of IV reuse | What the attacker learns |
|---|---|---|
| CTR | Catastrophic — two-time pad | M ⊕ M′ for the whole message (keystream cancels) |
| CBC | Contained | Whether two messages share leading blocks, up to the first difference |
Same root cause (lost randomness, scheme goes deterministic), wildly different consequences. Never reuse an IV — but understand that CTR is the one where reuse is an instant disaster.
Comparison
Comparison matrix
From §6.9 The severity table: refill the Effect of IV reuse column from what you know. The rest of the table is as it appeared.
| Mode | Effect of IV reuse | What the attacker learns |
|---|---|---|
| CTR | Catastrophic — two-time pad | M ⊕ M′ for the whole message (keystream cancels) |
| CBC | Contained | Whether two messages share leading blocks, up to the first difference |
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'IV reuse is bad, sure, but it's equally bad in CBC and CTR — it's the same mistake either way.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: False. In CTR the keystream cancels and the attacker recovers M ⊕ M′ for the ENTIRE message — full plaintext relationships.
A student: how does IV-reuse severity differ by mode?
Why: False. In CTR the keystream cancels and the attacker recovers M ⊕ M′ for the ENTIRE message — full plaintext relationships. That's far worse than CBC's leak.
Trap
A student: 'IV reuse is bad, sure, but it's equally bad in CBC and CTR — it's the same mistake either way.'
Treat the two leaks as interchangeable
Why: False. In CTR the keystream cancels and the attacker recovers M ⊕ M′ for the ENTIRE message — full plaintext relationships. That's far worse than CBC's leak.
A student: how does IV-reuse severity differ by mode?
CTR reuse = two-time pad ⇒ M ⊕ M′ leaks (catastrophic). CBC reuse ⇒ only a shared-prefix hint (contained)
Why: §6.9: CTR's keystream depends only on (key, IV), so reuse repeats the whole pad. CBC's chaining limits the leak to the matching prefix.
Anomaly
Predict first
A student writes this, and it looks reasonable:
A student: 'I'll just use a counter 0, 1, 2… as my IV, or even a constant — as long as it's there, the scheme is randomized.'
It is wrong. Say what breaks — and say it before you turn the page.
Correct: A constant IV is reuse (instant determinism).
A student: what must an IV actually be?
Why: A constant IV is reuse (instant determinism). A predictable IV lets the attacker influence what gets ⊕'d in — the chosen-IV/chosen-plaintext setting that breaks CBC's IND-CPA.
Trap
A student: 'I'll just use a counter 0, 1, 2… as my IV, or even a constant — as long as it's there, the scheme is randomized.'
Use a predictable or constant IV
Why: A constant IV is reuse (instant determinism). A predictable IV lets the attacker influence what gets ⊕'d in — the chosen-IV/chosen-plaintext setting that breaks CBC's IND-CPA.
A student: what must an IV actually be?
Use a FRESH, RANDOM, UNPREDICTABLE IV for every single encryption
Why: §6.9 / NIST SP 800-38A: CBC needs an unpredictable IV and CTR needs unique counter blocks. 'Present' isn't enough — it must be fresh and unguessable.
Two truths and a lie
Sort into buckets
Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.
Intuition
In CTR the keystream is the WHOLE story: it depends only on key and IV, so repeating the IV repeats the entire pad — the messages cancel completely under XOR. There's no per-block structure to limit the damage.
In CBC each block is re-randomized by the previous CIPHERTEXT block. The instant two plaintexts differ, their ciphertext chains diverge and never realign — so the leak self-limits to the matching prefix.
Ask yourself: why doesn't the CBC leak spread past the first difference? (The differing block changes C, which changes every chaining input after it.)
Analogy
Discussion prompt
Explain §6.9 Why CBC contains what CTR cannot by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
Ask yourself: why doesn't the CBC leak spread past the first difference? (The differing block changes C, which changes every chaining input after it.)
Section
Part 5 · §6.7 the master trade-off
Concept
From §6.7: CBC encryption is sequential — each block's ⊕ input is the previous ciphertext block, so you can't start block i until block i−1 is done. CTR has no such chain: every keystream block depends only on its counter.
So CTR encryption parallelizes; CBC encryption does not. Decryption is friendlier: CBC decryption parallelizes (each plaintext block needs only its own and the previous ciphertext block, both already known), and CTR decryption parallelizes too.
Concept
Everything from this lesson, consolidated. This is the table you actually use when picking a mode.
| Property | CBC | CTR |
|---|---|---|
| Padding required? | Yes (PKCS#7) | No (truncate keystream) |
| Encryption parallelizable? | No (sequential chain) | Yes (per-counter) |
| Decryption parallelizable? | Yes | Yes |
| IV-reuse severity | Contained (shared prefix) | Catastrophic (M ⊕ M′) |
| Uses the decryption function D_K? | Yes (to decrypt) | No — only E_K, both ways |
Comparison
Comparison matrix
From §6.7 The master CBC-vs-CTR table: refill the CTR column from what you know. The rest of the table is as it appeared.
| Property | CBC | CTR |
|---|---|---|
| Padding required? | Yes (PKCS#7) | No (truncate keystream) |
| Encryption parallelizable? | No (sequential chain) | Yes (per-counter) |
| Decryption parallelizable? | Yes | Yes |
| IV-reuse severity | Contained (shared prefix) | Catastrophic (M ⊕ M′) |
| Uses the decryption function D_K? | Yes (to decrypt) | No — only E_K, both ways |
Intuition
High-performance systems lean toward CTR: encryption parallelizes, there's no padding overhead, and you only ever need the forward block-cipher function E_K. The price is strict: you MUST guarantee nonce uniqueness, because reuse is catastrophic.
CBC tolerates an IV slip more gracefully (a contained leak), and needs no separate guarantee beyond an unpredictable IV — but it can't parallelize encryption and requires padding plus the decryption function.
Ask yourself: if you can't be certain your nonces are unique, which mode is the safer default? (CBC — its reuse failure is contained, not catastrophic.)
Counterexample
Discussion prompt
Ask yourself: if you can't be certain your nonces are unique, which mode is the safer default? (CBC — its reuse failure is contained, not catastrophic.)
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Constraint
Discussion prompt
Run The padding & IV checklist with this step confiscated:
Use a fresh, random, unpredictable IV every time. 'Present' is not enough — predictable or constant IVs break security.
Is it still possible? If it is, say what takes its place and what it costs you. If it is not, say exactly what that step was providing that nothing else does.
Hint: A step you can drop for free was never load-bearing. If you cannot drop it, name the thing that goes wrong the moment it is gone.
Answer:
Pattern
Edge cases
Discussion prompt
The padding & IV checklist works on the cases you have just seen. Push it to the edge: what is the most degenerate input it still handles — empty, zero, one item, everything equal — and what is the first case where it stops being true? Name the case, not just "it breaks".
Hint: Try the smallest legal input, then the largest, then the one where two things collide. Methods are specified at their edges; the middle takes care of itself.
Answer:
Elimination
Eliminate the wrong options
Using PKCS#7 with a 16-byte block size, how much padding does a 32-byte (block-aligned) message get?
3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.
Survives elimination: B
Why: §6.8 / RFC 5652: PKCS#7 always appends 1–16 bytes, never 0. When the message is already block-aligned, it appends a WHOLE new block — 16 bytes each holding the value 16 (0x10) — so the receiver always reads the last byte as the pad count and strips exactly that many. Depad here reads 0x10 = 16 and removes 16 bytes, recovering the original 32.
Check
An engineer is CBC-encrypting a message that is exactly 32 bytes long — two full 16-byte blocks. They ask how many bytes of PKCS#7 padding to append.
Check your understanding
Using PKCS#7 with a 16-byte block size, how much padding does a 32-byte (block-aligned) message get?
Answer: B
Why: §6.8 / RFC 5652: PKCS#7 always appends 1–16 bytes, never 0. When the message is already block-aligned, it appends a WHOLE new block — 16 bytes each holding the value 16 (0x10) — so the receiver always reads the last byte as the pad count and strips exactly that many. Depad here reads 0x10 = 16 and removes 16 bytes, recovering the original 32.
Concept
Concept
Concept
Connect it up
Draw it
One page, no notation unless you need it: draw how these connect — Why CBC Needs Padding · PKCS#7: Unambiguous Padding · Why CTR Needs No Padding · The Danger of IV Reuse · Choosing a Mode: CBC vs CTR. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.
Recap
You can now explain why CBC needs padding and CTR doesn't, apply PKCS#7 (including the block-aligned full-block case), rank IV-reuse severity across CTR and CBC, and read the CBC-vs-CTR table to choose a mode.
| Idea | § | The one-line version |
|---|---|---|
| CBC needs padding | 6.8 | Short last block ⇒ ⊕ and cipher input undefined |
| PKCS#7 | 6.8 | Append N bytes of value N; depad reads the last byte |
| Aligned edge case | 6.8 | Already aligned ⇒ append a full 16-byte 0x10 block |
| CTR needs no padding | 6.8 | Keystream is trimmable; ciphertext = plaintext length |
| CTR IV reuse | 6.9 | Two-time pad: C ⊕ C′ = M ⊕ M′ (catastrophic) |
| CBC IV reuse | 6.9 | Only a shared-prefix leak (contained) |
| Fresh IV rule | 6.9 | Always fresh, random, unpredictable — never constant |
| CBC vs CTR | 6.7 | CTR: parallel + no pad but needs unique nonces |
Want this taught 1-on-1? Alexander tutors Computer Security — $55/session, free consultation.