<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: cbc</title><description>Posts tagged cbc.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sat, 25 Jul 2026 08:57:57 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/cbc/rss.xml" rel="self" type="application/rss+xml"/><item><title>The Ciphertext Was Unbreakable. The Attacker Rewrote It Anyway: A Field Guide to Block Cipher Modes</title><link>https://paragmali.com/blog/the-ciphertext-was-unbreakable-the-attacker-rewrote-it-anyw/</link><guid isPermaLink="true">https://paragmali.com/blog/the-ciphertext-was-unbreakable-the-attacker-rewrote-it-anyw/</guid><description>Every block cipher mode -- ECB, CBC, CFB, OFB, CTR -- answers only confidentiality, never integrity. A field guide to why, the famous breaks, and the AEAD fix.</description><pubDate>Wed, 08 Jul 2026 21:51:08 GMT</pubDate><content:encoded>
A block cipher only enciphers one fixed-size block. A &quot;mode of operation&quot; is the wrapper that turns it into a scheme for real messages -- and every mode answers only one of two questions: can the attacker *read* it (confidentiality), or can the attacker *change* it (integrity)? The five SP 800-38A modes -- ECB, CBC, CFB, OFB, CTR -- are all malleable, so an attacker who cannot decrypt your ciphertext can still predictably edit the plaintext, and ECB additionally leaks structure outright (the penguin, Adobe&apos;s 153 million passwords). This field guide hands you one lens -- *which question did this mode answer, and was its IV/nonce contract honored?* -- and uses it to walk each mode&apos;s exact contract, a named failure catalog (Vaudenay, BEAST, Lucky Thirteen, POODLE, Sweet32, Efail, GCM nonce reuse), and the fix: authenticated encryption, whose dominant AES instances (GCM equals CTR plus GHASH, CCM equals CTR plus CBC-MAC) are literally these modes plus a MAC. It closes with the 2024-2026 state of the art (IR 8459, the ECB sunset, Ascon, nonce-misuse-resistant AES-GCM-SIV) and a decision guide for using these primitives correctly.
&lt;h2&gt;1. Two Lines of Code&lt;/h2&gt;
&lt;p&gt;A bank encrypts the message &quot;transfer $9&quot; with AES and a 256-bit key and sends the ciphertext across a network an attacker completely controls. He cannot read a single byte of it. AES is unbroken and will stay unbroken. Yet by flipping a few bits he cannot even decrypt, he turns the message into &quot;transfer $9,000,000,&quot; and the receiver accepts the change as authentic. The encryption was never broken. It simply answered the wrong question.&lt;/p&gt;
&lt;p&gt;How can a ciphertext be unreadable and freely editable at once? The trick is not a flaw in AES but a property of the &lt;em&gt;mode&lt;/em&gt; -- the wrapper that stretches a one-block cipher across a longer message. Many modes turn the cipher into a keystream generator and combine it with the plaintext by XOR, so $C = P \oplus \text{keystream}$. Rearrange the algebra: $P = C \oplus \text{keystream}$. An attacker who XORs a chosen delta into the ciphertext XORs exactly that delta into the recovered plaintext. He needs no key, reads nothing, and the receiver decrypts a perfectly well-formed forgery. That is one half of the story: the integrity question was never answered.&lt;/p&gt;
&lt;p&gt;The other half is uglier, because it fails the &lt;em&gt;first&lt;/em&gt; question too. In 2013, attackers exposed roughly 153 million Adobe account records. The passwords were not hashed. They were &lt;em&gt;encrypted&lt;/em&gt;, with 3DES in ECB mode and no salt [@troyhunt-adobe-2013]. ECB enciphers each block independently, so identical passwords produced identical ciphertext. Combined with the unencrypted password hints Adobe stored beside them, enormous numbers of passwords were reconstructed without anyone ever breaking 3DES [@troyhunt-adobe-2013]. The cipher was fine. The mode leaked the plaintext.&lt;/p&gt;
&lt;p&gt;Two stories, one shape. In each, the cipher did exactly what it promised and the attacker still won. That is because a mode of operation answers up to two independent questions, and the five most famous modes answer only one:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Can the attacker read it?&lt;/strong&gt; That is &lt;em&gt;confidentiality&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Can the attacker change it?&lt;/strong&gt; That is &lt;em&gt;integrity&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The five modes standardized for decades -- ECB, CBC, CFB, OFB, CTR -- answer only the first question. ECB answers even that one wrongly. Every named break in this field, past or future, reduces to one diagnostic sentence: &lt;em&gt;which of the two questions did this mode answer, and was its IV/nonce contract honored?&lt;/em&gt; Hold that sentence in your head and the whole subject becomes legible.&lt;/p&gt;

flowchart TD
    Mode[&quot;A block cipher mode of operation&quot;]
    Mode --&amp;gt; C[&quot;Question 1: can the attacker READ it? (confidentiality)&quot;]
    Mode --&amp;gt; I[&quot;Question 2: can the attacker CHANGE it? (integrity)&quot;]
    C --&amp;gt; Cans[&quot;Answered only if the IV or nonce contract is honored&quot;]
    I --&amp;gt; Ians[&quot;Never answered by the five SP 800-38A modes&quot;]
    Cans --&amp;gt; BreakA[&quot;Break type A: violated IV/nonce contract (BEAST, GCM nonce reuse)&quot;]
    Ians --&amp;gt; BreakB[&quot;Break type B: missing integrity answer (Efail, bit-flipping, truncation)&quot;]
&lt;p&gt;This is Part 5 of a field guide for protocol designers. It leans on two earlier parts without re-deriving them: &lt;a href=&quot;https://paragmali.com/blog/secure-against-whom-the-security-definitions-every-protocol-&quot; rel=&quot;noopener&quot;&gt;Part 1&lt;/a&gt; gave us the security definitions this article keeps invoking -- IND-CPA, IND-CCA2, INT-CTXT -- and Part 2 gave us the discipline of generating initialization vectors and nonces. Here we spend those definitions on a single primitive: the block cipher mode.&lt;/p&gt;
&lt;p&gt;If AES was never broken in either story, what actually failed? To answer, you first have to know what a block cipher can and cannot do on its own, and why a mode was mandatory from the very first day it shipped.&lt;/p&gt;
&lt;h2&gt;2. A Cipher That Only Speaks in Blocks&lt;/h2&gt;
&lt;p&gt;A block cipher is smaller than you think. DES (1977) enciphers exactly 64 bits at a time. AES (2001) enciphers exactly 128. Feed it more and it simply refuses. It is a keyed permutation on one fixed-size block and physically cannot accept a message longer than that.&lt;/p&gt;

A keyed, invertible permutation on one fixed-size block of bits, written $E_k : \{0,1\}^n \to \{0,1\}^n$ for a key $k$ and block size $n$ (64 bits for DES, 128 for AES). It maps one $n$-bit input to one $n$-bit output and back. It has no notion of a message, a length, or a stream.
&lt;p&gt;Because real messages are almost never exactly one block long, every use of a block cipher needs a wrapper: a rule for chopping the message into blocks, deciding what each block&apos;s input should be, and stitching the outputs back together. That wrapper is the mode of operation.&lt;/p&gt;

The algorithm that lifts a one-block cipher to messages of arbitrary length. It specifies how plaintext is partitioned, what feeds into each block cipher call, and how the results combine into a ciphertext. The mode -- not the cipher -- decides whether identical plaintext leaks, whether the scheme is parallel, and what the initialization-vector or nonce rule is.
&lt;p&gt;The primitive came first. Horst Feistel&apos;s work at IBM in the early 1970s produced the Feistel network that became DES, a 64-bit keyed permutation blessed as a federal standard in 1977 [@feistel-1973][@fips-46-3]. The 64-bit block chosen here is the exact quantity that dies, 39 years later, to the Sweet32 attack.&lt;/p&gt;
&lt;p&gt;The first wrapper followed almost immediately. In 1976, William Ehrsam, Carl Meyer, John Smith, and Walter Tuchman at IBM filed the patent on Cipher Block Chaining -- the idea of feeding each plaintext block the previous ciphertext block before encryption, so that identical plaintext blocks stop producing identical ciphertext (US Patent 4,074,066, granted 1978) [@cbc-patent-4074066].The patent&apos;s actual title is &quot;Message verification and transmission error detection by block chaining&quot; [@cbc-patent-4074066]. That is historically ironic: CBC as a confidentiality mode provides no message verification -- no integrity -- at all, which is the very gap this article is about.&lt;/p&gt;
&lt;p&gt;Counter mode arrived on paper three years later. Whitfield Diffie and Martin Hellman described encrypting a counter to make a keystream in their 1979 survey &quot;Privacy and Authentication,&quot; turning a block cipher into a parallelizable stream cipher [@diffie-hellman-1979][@rogaway-modes-2011].Counter mode was described &quot;just as early as the basic-four modes,&quot; in Rogaway&apos;s words, &quot;yet for some reason it was not included in the initial batch&quot; [@rogaway-modes-2011]. It waited 22 years for a federal standard. The exact page in Proc. IEEE 67(3) is gated behind IEEE Xplore, so the DOI is the stable handle and Rogaway&apos;s 2011 survey carries the attribution [@diffie-hellman-1979][@rogaway-modes-2011].&lt;/p&gt;
&lt;p&gt;Then the standard fixed the toolkit. In December 1980 the National Bureau of Standards published FIPS 81, &lt;em&gt;DES Modes of Operation&lt;/em&gt;, sanctioning four ways to stretch DES across real traffic: ECB, CBC, CFB, and OFB [@fips-81]. Counter mode was left out. It did not enter a NIST standard until Morris Dworkin&apos;s SP 800-38A re-specified all five modes for the AES era in December 2001, finally adding CTR as the fifth -- 22 years after Diffie and Hellman [@nist-sp-800-38a].&lt;/p&gt;

flowchart LR
    A[&quot;1976: CBC invented at IBM&quot;] --&amp;gt; B[&quot;1979: Counter mode, Diffie-Hellman&quot;]
    B --&amp;gt; C[&quot;1980: FIPS 81 standardizes ECB, CBC, CFB, OFB&quot;]
    C --&amp;gt; D[&quot;1997: BDJR concrete-security proofs&quot;]
    D --&amp;gt; E[&quot;2000-2001: Encrypt-then-MAC proven, SP 800-38A adds CTR&quot;]
    E --&amp;gt; F[&quot;2004-2007: GCM and CCM, CTR plus a MAC&quot;]
    F --&amp;gt; G[&quot;2011-2018: BEAST, Lucky Thirteen, POODLE, Sweet32, Efail&quot;]
    G --&amp;gt; H[&quot;2024-2025: NIST IR 8459, Ascon&quot;]
&lt;p&gt;Here is the load-bearing historical fact. Every one of these five modes is a &lt;em&gt;confidentiality&lt;/em&gt; construction. Integrity -- the second question, &quot;can the attacker change it?&quot; -- was filed under a separate heading called a message authentication code, and in practice it was usually forgotten. FIPS 81 and SP 800-38A specify no integrity mechanism for any of the five [@fips-81][@nist-sp-800-38a]. That separation of concerns, confidentiality here and integrity somewhere else, is the original sin the rest of this story pays for.&lt;/p&gt;
&lt;p&gt;So the toolkit was frozen by 1980 (four modes) and completed by 2001 (a fifth), every one a way to hide data and none a way to protect it from change. The most obvious of the four is also the most broken, and seeing exactly why is the fastest route into the whole subject.&lt;/p&gt;
&lt;h2&gt;3. ECB, and Why &quot;Just Encrypt Each Block&quot; Fails&lt;/h2&gt;
&lt;p&gt;The most obvious wrapper is to apply the one-block permutation to each block on its own: $C_i = E_k(P_i)$. This is Electronic Codebook mode, and it is the design every beginner reinvents in an afternoon. It is also broken in a way you can see with your eyes.&lt;/p&gt;
&lt;p&gt;The flaw is that ECB is &lt;em&gt;deterministic&lt;/em&gt;. It has no initialization vector, no chaining, and no state, so the same plaintext block always encrypts to the same ciphertext block: $P_i = P_j \Rightarrow C_i = C_j$. The plaintext&apos;s block-level structure survives encryption intact. Rogaway&apos;s survey states it flatly: ECB &quot;leak[s] equality of blocks across both block positions and time&quot; and &quot;does not achieve any generally desirable security goal in its own right&quot; [@rogaway-modes-2011].&lt;/p&gt;

flowchart TD
    P1[&quot;Block A: LOVE&quot;] --&amp;gt; C1[&quot;Ciphertext 7a3f&quot;]
    P2[&quot;Block B: HATE&quot;] --&amp;gt; C2[&quot;Ciphertext 9b2e&quot;]
    P3[&quot;Block C: LOVE&quot;] --&amp;gt; C3[&quot;Ciphertext 7a3f&quot;]
    C1 -.-&amp;gt;|&quot;equal blocks leak&quot;| C3
&lt;p&gt;That leak is not a metaphor.The famous &quot;ECB penguin&quot; -- an image of Tux encrypted block-by-block whose outline stays perfectly visible -- is community folklore (the Tux image is by Larry Ewing, 1996) with no research primary. The load-bearing evidence for ECB&apos;s failure is the Adobe 2013 breach and the BDJR theorem, not the meme. In 2013, roughly 153 million Adobe records showed it at scale: passwords encrypted with 3DES in ECB, no salt, so identical passwords produced identical ciphertext and the plaintext structure reconstructed itself without 3DES ever being broken [@troyhunt-adobe-2013].&lt;/p&gt;
&lt;p&gt;Underneath the meme is a theorem. ECB is not IND-CPA.&lt;/p&gt;

The baseline security goal for encryption. An adversary who may request encryptions of any plaintexts it chooses still cannot tell which of two equal-length messages a challenge ciphertext hides. Bellare, Desai, Jokipii, and Rogaway (1997) proved the consequence: any IND-CPA scheme must be randomized or stateful, so a deterministic mode like ECB cannot qualify [@bdjr-1997][@katz-lindell-2020].
&lt;p&gt;The proof is a one-line adversary. Ask the challenger to encrypt a pair of equal blocks $(X, X)$ versus an unequal pair $(X, Y)$ and simply look for a repeated ciphertext block; ECB gives itself away every time [@bdjr-1997]. This is the same reasoning &lt;a href=&quot;https://paragmali.com/blog/secure-against-whom-the-security-definitions-every-protocol-&quot; rel=&quot;noopener&quot;&gt;Part 1&lt;/a&gt; develops in general. ECB is also malleable at block granularity: because blocks are independent, an attacker can cut, paste, and reorder them undetected. It fails both questions at once.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; ECB is deterministic, so identical plaintext blocks become identical ciphertext blocks and structured or repeated data leaks through untouched -- the ECB penguin, and Adobe&apos;s roughly 153 million exposed passwords [@troyhunt-adobe-2013]. Reach for ECB only as a raw one-block building block, never to encrypt a message.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That &quot;never&quot; needs one careful qualifier -- it is easy to overstate.&lt;/p&gt;

The rule is *never ECB for messages* -- multi-block, structured, or low-entropy plaintext. The raw single-block permutation is still a legitimate building block: it is the block operation every other mode calls, and it sits at the core of NIST AES Key Wrap and of CMAC/CBC-MAC. NIST&apos;s SP 800-131A Revision 3, the initial public draft published on October 21, 2024, formalizes this by moving ECB to &quot;legacy use&quot; and disallowing it for encrypting secret data, with legacy (decrypt-only) use retained -- a demotion, not a claim that ECB has no valid use anywhere [@nist-sp-800-131a-r3].
&lt;p&gt;You can watch the determinism happen. The toy below is not a real cipher, but like ECB it transforms each block with the same deterministic function, so a repeated plaintext block produces a repeated ciphertext block:&lt;/p&gt;
&lt;p&gt;{`
// A toy deterministic block transform. Not a real cipher -- the point is
// only that the same input block always yields the same output block.
function toyBlockCipher(block) {
  return block.split(&apos;&apos;).reverse().map(function (c) {
    return String.fromCharCode((c.charCodeAt(0) + 7) % 128);
  }).join(&apos;&apos;);
}&lt;/p&gt;
&lt;p&gt;// ECB: split into 4-char blocks and transform each one independently.
function ecb(message) {
  var out = [];
  for (var i = 0; i &amp;lt; message.length; i += 4) {
    out.push(toyBlockCipher(message.slice(i, i + 4)));
  }
  return out;
}&lt;/p&gt;
&lt;p&gt;var blocks = ecb(&apos;LOVEHATELOVE&apos;); // block 1 and block 3 are identical
console.log(blocks);
console.log(&apos;Block 1 equals block 3? &apos; + (blocks[0] === blocks[2]));
// True. The repeated plaintext block leaks as a repeated ciphertext block,
// with no key required to notice the pattern.
`}&lt;/p&gt;
&lt;p&gt;One clarification before moving on.These five are the SP 800-38A &lt;em&gt;confidentiality-only&lt;/em&gt; modes, not &quot;all block cipher modes.&quot; Disk encryption (XTS-AES, SP 800-38E), authentication (CMAC, SP 800-38B), and authenticated encryption (GCM in SP 800-38D, CCM in SP 800-38C) live in separate NIST publications because they pursue different goals. ECB is the degenerate member of the family, and its failure points straight at the fix.&lt;/p&gt;
&lt;p&gt;BDJR&apos;s theorem is also the cure. To be IND-CPA, encryption must be randomized or stateful. So add an initialization vector, and make each block&apos;s encryption depend on the previous one, so that identical plaintext diverges. That is Cipher Block Chaining -- and the start of a forty-year evolution that improves everything except the one thing that matters.&lt;/p&gt;
&lt;h2&gt;4. From CBC to CTR, Generation by Generation&lt;/h2&gt;
&lt;p&gt;Four modes remain, and they line up as a sequence of fixes -- each one repairing the previous mode&apos;s &lt;em&gt;limitation&lt;/em&gt;, and none of them repairing the missing integrity answer. The field got faster, more flexible, and better specified. It stayed exactly as forgeable as the day it started.&lt;/p&gt;
&lt;h3&gt;CBC: chain the blocks&lt;/h3&gt;
&lt;p&gt;CBC seeds the chain with an initialization vector and feeds each plaintext block the previous ciphertext block before encryption: $C_i = E_k(P_i \oplus C_{i-1})$, with $C_0 = \text{IV}$. Decryption runs $P_i = D_k(C_i) \oplus C_{i-1}$. Because every ciphertext block now depends on all plaintext before it, identical plaintext blocks diverge, and ECB&apos;s pattern leak is gone. With an unpredictable IV, CBC is provably IND-CPA [@bdjr-1997].&lt;/p&gt;

The per-message starting value a mode mixes in so that encrypting the same plaintext twice yields different ciphertext. For CBC and CFB the IV must be *unpredictable* -- indistinguishable from random to an attacker -- not merely fresh, because it is the first value fed into the chain [@nist-sp-800-38a]. Part 2 of this series covers how to generate one.
&lt;p&gt;CBC answered the first question correctly and left the second blank, and even its confidentiality carries three sharp contract edges. This one mode seeded most of the Failure Catalog. It is malleable: a controlled flip in ciphertext block $C_i$ deterministically flips the corresponding bits of plaintext block $P_{i+1}$ while randomizing $P_i$ -- the &quot;flip-and-garble&quot; gadget, an attacker editing a later block without the key [@rogaway-modes-2011].&lt;/p&gt;
&lt;p&gt;The three contract edges follow. It needs padding, and a receiver that reveals whether decrypted padding is valid turns that check into a plaintext-recovering oracle. Its IV must be unpredictable, or a chosen-plaintext attacker can distinguish messages. And with a 64-bit block, its ciphertext blocks start colliding after about $2^{32}$ blocks, leaking $P_i \oplus P_j$. Rogaway&apos;s performance verdict is blunt: CBC encryption is &quot;inherently serial,&quot; and he can &quot;identify no important advantages over CTR mode&quot; [@rogaway-modes-2011].Ciphertext stealing (CBC-CS, standardized in an addendum to SP 800-38A) is the no-expansion variant that avoids padding by borrowing bits from the penultimate block. It is a useful trick, not a new security property -- CBC-CS is still malleable and still needs an unpredictable IV.&lt;/p&gt;
&lt;h3&gt;CFB: a self-synchronizing stream&lt;/h3&gt;
&lt;p&gt;CFB turns the block cipher into a stream by encrypting the &lt;em&gt;previous ciphertext&lt;/em&gt; to produce a keystream, then XORing it with the plaintext: $C_i = P_i \oplus E_k(C_{i-1})$. The cipher never touches the plaintext directly, so there is no padding, the mode can operate on sub-block segments (one byte or even one bit at a time), and it self-synchronizes after lost or inserted segments -- a genuinely useful property for noisy character-oriented links [@rogaway-modes-2011].&lt;/p&gt;
&lt;p&gt;The costs are real. Encryption is still serial, and for a segment size $s \lt n$ the mode makes many more block cipher calls per byte -- Rogaway notes $s = 8$ means &quot;16 times the number of blockcipher calls as CBC,&quot; and $s = 1$ means 128 times [@rogaway-modes-2011].Folklore (and even the loose version of this article&apos;s own scope) sometimes says CFB needs only a &lt;em&gt;unique&lt;/em&gt; IV. The primary source is stricter: SP 800-38A Section 5.3 requires the IV for both CBC and CFB to be &lt;em&gt;unpredictable&lt;/em&gt; [@nist-sp-800-38a]. Treat CFB&apos;s IV exactly like CBC&apos;s.&lt;/p&gt;
&lt;p&gt;CFB&apos;s malleability is the middle case, not a pure bit-flip. Because $P_i = C_i \oplus E_k(C_{i-1})$, flipping a ciphertext bit flips exactly the aligned plaintext bit in the &lt;em&gt;current&lt;/em&gt; block -- but that same altered block is the cipher&apos;s input for the next one, so the &lt;em&gt;following&lt;/em&gt; block decrypts to garbage. Efail (2018) weaponized precisely this: Damian Poddebniak and co-authors built malleability &quot;gadgets&quot; in CFB (OpenPGP&apos;s mode), engineered to absorb the garbled block while keeping the surgical edit, that turned an encrypted email into a plaintext-exfiltration channel with no key recovery and no padding oracle [@efail-2018][@efail-site].&lt;/p&gt;
&lt;h3&gt;OFB: a pre-computable stream&lt;/h3&gt;
&lt;p&gt;OFB makes the keystream independent of the message by feeding back the cipher&apos;s &lt;em&gt;own output&lt;/em&gt; instead of the ciphertext: $O_i = E_k(O_{i-1})$, then $C_i = P_i \oplus O_i$. Because the pad depends only on the key and IV, you can compute it before the plaintext arrives, and a single flipped ciphertext bit corrupts only the corresponding plaintext bit, with no error propagation -- attractive for satellite links and digitized voice [@rogaway-modes-2011].&lt;/p&gt;

A number used once: a value that must never repeat under a given key. OFB and CTR need their nonce only to be *unique*, not unpredictable, so a simple counter is a perfectly good nonce [@nist-sp-800-38a]. Reusing one under the same key is catastrophic for every keystream mode, because it reproduces the exact same pad. Part 2 covers how to source these values safely.
&lt;p&gt;That last point is OFB&apos;s undoing. If a $(\text{key}, \text{IV})$ pair ever repeats, the pad repeats, and $C \oplus C&apos; = P \oplus P&apos;$ leaks the XOR of two plaintexts with no key -- a two-time pad [@rogaway-modes-2011]. OFB is also serial in &lt;em&gt;both&lt;/em&gt; directions, so it cannot use hardware parallelism at all, a strictly worse profile than CTR for the same &quot;stream&quot; benefit. And the original FIPS 81 reduced-feedback variants shortened the keystream cycle dangerously, a hazard SP 800-38A removed by defining OFB with full-block feedback only [@fips-81][@nist-sp-800-38a].&lt;/p&gt;
&lt;h3&gt;CTR: the parallel stream that wins&lt;/h3&gt;
&lt;p&gt;CTR keeps OFB&apos;s &quot;encrypt something to make a pad&quot; idea but replaces the serial feedback chain with an &lt;em&gt;independent&lt;/em&gt; per-block counter: $C_i = P_i \oplus E_k(\text{nonce} ,|, i)$. Because each pad block is a standalone function of its counter, the blocks have no data dependency on one another. CTR is fully parallel on both encryption and decryption, random-access (decrypt block $i$ alone), precomputable, inverse-free, and needs no padding. Rogaway estimates it &quot;encrypting at more than 10 times the speed of CBC&quot; in hardware [@rogaway-modes-2011]. Its contract is the simplest of all: the counter must be &lt;em&gt;unique&lt;/em&gt; per key, and unpredictability is explicitly not required [@bdjr-1997][@rogaway-modes-2011].&lt;/p&gt;

Counter mode is &quot;the best and most modern way to achieve privacy-only encryption&quot; and &quot;an important building block for authenticated-encryption schemes.&quot; -- Phillip Rogaway, 2011
&lt;p&gt;And here is the cliff. CTR is the best answer to the &lt;em&gt;first&lt;/em&gt; question, which is exactly what makes its failure the point of the whole story. It is still malleable, and more transparently so than any other mode: $P = C \oplus \text{keystream}$, so flipping any ciphertext bit flips exactly the corresponding plaintext bit, with no key. The &quot;transfer $9&quot; to &quot;transfer $9,000,000&quot; edit from the opening is a single XOR, and the receiver decrypts a perfectly well-formed message. CTR removed every other excuse -- it is fast, parallel, and clean -- so the blank where integrity should be is the only thing left to see.&lt;/p&gt;

flowchart TD
    subgraph CBC[&quot;CBC: serial chaining&quot;]
        cIV[&quot;IV&quot;] --&amp;gt; cx1[&quot;XOR&quot;]
        cP1[&quot;P1&quot;] --&amp;gt; cx1
        cx1 --&amp;gt; cE1[&quot;E_k&quot;] --&amp;gt; cC1[&quot;C1&quot;]
        cC1 --&amp;gt; cx2[&quot;XOR&quot;]
        cP2[&quot;P2&quot;] --&amp;gt; cx2
        cx2 --&amp;gt; cE2[&quot;E_k&quot;] --&amp;gt; cC2[&quot;C2&quot;]
    end
    subgraph CTR[&quot;CTR: independent counters&quot;]
        tK1[&quot;E_k(nonce, 1)&quot;] --&amp;gt; tx1[&quot;XOR&quot;]
        tP1[&quot;P1&quot;] --&amp;gt; tx1
        tx1 --&amp;gt; tC1[&quot;C1&quot;]
        tK2[&quot;E_k(nonce, 2)&quot;] --&amp;gt; tx2[&quot;XOR&quot;]
        tP2[&quot;P2&quot;] --&amp;gt; tx2
        tx2 --&amp;gt; tC2[&quot;C2&quot;]
    end
&lt;p&gt;Lined up as a reference grid, the five modes and their exact contracts look like this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Relation&lt;/th&gt;
&lt;th&gt;IV / nonce contract&lt;/th&gt;
&lt;th&gt;Parallelism&lt;/th&gt;
&lt;th&gt;Malleability&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ECB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C_i = E_k(P_i)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none (the flaw)&lt;/td&gt;
&lt;td&gt;encrypt and decrypt parallel&lt;/td&gt;
&lt;td&gt;block-level: cut, paste, reorder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CBC&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C_i = E_k(P_i XOR C_{i-1})&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;unpredictable IV&lt;/td&gt;
&lt;td&gt;encrypt serial, decrypt parallel&lt;/td&gt;
&lt;td&gt;flip-and-garble (block-coupled)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CFB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C_i = P_i XOR E_k(C_{i-1})&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;unpredictable IV&lt;/td&gt;
&lt;td&gt;encrypt serial, decrypt parallel&lt;/td&gt;
&lt;td&gt;surgical bit, next block garbled (middle)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OFB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C_i = P_i XOR E_k(O_{i-1})&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;unique nonce&lt;/td&gt;
&lt;td&gt;serial both ways&lt;/td&gt;
&lt;td&gt;surgical bitwise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTR&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C_i = P_i XOR E_k(counter_i)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;unique nonce (not unpredictable)&lt;/td&gt;
&lt;td&gt;encrypt and decrypt parallel&lt;/td&gt;
&lt;td&gt;surgical bitwise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The IV and nonce contracts are SP 800-38A&apos;s; the parallelism and malleability columns follow Rogaway&apos;s summary tables [@nist-sp-800-38a][@rogaway-modes-2011].&lt;/p&gt;
&lt;p&gt;That last column deserves its own magnification, because &quot;malleable&quot; is not one behavior. It runs from surgical (edit one plaintext bit and touch nothing else), through a middle case (edit one bit, but wreck the neighboring block), to block-coupled (your controlled edit lands a block &lt;em&gt;later&lt;/em&gt;):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Malleability class&lt;/th&gt;
&lt;th&gt;What one flipped ciphertext bit does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;CTR, OFB&lt;/td&gt;
&lt;td&gt;surgical&lt;/td&gt;
&lt;td&gt;flips exactly the aligned plaintext bit, with zero collateral&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CFB&lt;/td&gt;
&lt;td&gt;middle case&lt;/td&gt;
&lt;td&gt;flips the aligned bit in the current block, and fully garbles the next block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CBC&lt;/td&gt;
&lt;td&gt;block-coupled&lt;/td&gt;
&lt;td&gt;garbles the current block, and flips the aligned bit in the next block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ECB&lt;/td&gt;
&lt;td&gt;block-level&lt;/td&gt;
&lt;td&gt;no sub-block control, but whole blocks can be cut, pasted, and reordered&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The distinction is operational, not academic: CTR&apos;s surgical malleability is what makes the opening bit-flip a one-line edit, while CFB&apos;s &quot;flip here, garble there&quot; is the exact structure Efail&apos;s exfiltration gadgets were built around [@rogaway-modes-2011][@efail-2018]. Read as an evolution, the same five tell a story of steady improvement on every axis but one:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Key idea&lt;/th&gt;
&lt;th&gt;Limitation that drove the next step&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ECB&lt;/td&gt;
&lt;td&gt;1980&lt;/td&gt;
&lt;td&gt;encrypt each block independently&lt;/td&gt;
&lt;td&gt;deterministic; leaks block equality (not IND-CPA)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CBC&lt;/td&gt;
&lt;td&gt;1976 / 1980&lt;/td&gt;
&lt;td&gt;chain each block with the previous ciphertext&lt;/td&gt;
&lt;td&gt;serial; needs padding; unpredictable IV; 64-bit birthday&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CFB&lt;/td&gt;
&lt;td&gt;1980&lt;/td&gt;
&lt;td&gt;encrypt the previous ciphertext into a keystream&lt;/td&gt;
&lt;td&gt;serial; sub-block sizes multiply cipher calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OFB&lt;/td&gt;
&lt;td&gt;1980&lt;/td&gt;
&lt;td&gt;encrypt the feedback into a message-independent pad&lt;/td&gt;
&lt;td&gt;serial both ways; reuse is a two-time pad&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTR&lt;/td&gt;
&lt;td&gt;1979 / 2001&lt;/td&gt;
&lt;td&gt;encrypt an independent counter&lt;/td&gt;
&lt;td&gt;the best confidentiality mode, yet still no integrity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Not one of the four evolutions from ECB added integrity. CBC, CFB, OFB, and CTR each improved chaining, padding, error behavior, or parallelism. Every one of them left the second question -- can the attacker change it? -- completely blank.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One honest caveat: CFB, OFB, and CTR are not a strict quality ladder. They are three parallel answers to CBC&apos;s &quot;turn the block cipher into a stream,&quot; standardized together, with CTR the clear winner [@rogaway-modes-2011]. The linear arrow is a teaching device.&lt;/p&gt;
&lt;p&gt;Line the four up and the pattern is undeniable. The bug was never &quot;which chaining?&quot; It was the blank where the second answer should be. Naming that blank correctly is the pivot the whole field turned on.&lt;/p&gt;
&lt;h2&gt;5. Malleability Is the Real Bug&lt;/h2&gt;
&lt;p&gt;Here is the reframe that organizes the entire subject: confidentiality is not security. A mode that perfectly hides your message while letting an attacker predictably rewrite it has not handed you a weaker guarantee. It has handed you a &lt;em&gt;different&lt;/em&gt; one, and mistaking the two is the single most repeated error in applied cryptography.&lt;/p&gt;

The property that an attacker can transform a ciphertext into a predictable transformation of the underlying plaintext, without knowing the key or the plaintext. A malleable scheme may be perfectly confidential and still let an attacker edit the message. All five SP 800-38A modes are malleable.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Every one of the five modes answers only confidentiality. The missing integrity answer &lt;em&gt;is&lt;/em&gt; malleability, and malleability is the real bug. The fix is authenticated encryption -- not a faster or cleverer confidentiality mode.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a provable statement, not a mood. A confidentiality-only mode is not IND-CCA2 and not non-malleable; IND-CPA says nothing about an active attacker who edits ciphertext in transit [@bdjr-1997].&lt;/p&gt;
&lt;p&gt;The mechanism differs per mode, and that difference is your diagnostic. In the pure keystream modes (CTR and OFB) the relation is $P = C \oplus \text{keystream}$, so flipping ciphertext bit $i$ flips plaintext bit $i$ exactly, with no collateral. CFB is the middle case: the flip lands surgically in the current block but garbles the &lt;em&gt;next&lt;/em&gt; one, because CFB feeds each ciphertext block back through the cipher. In CBC the coupling runs the other way -- a flip in $C_i$ predictably edits $P_{i+1}$ while randomizing $P_i$. &lt;a href=&quot;https://paragmali.com/blog/secure-against-whom-the-security-definitions-every-protocol-&quot; rel=&quot;noopener&quot;&gt;Part 1&lt;/a&gt; develops why this is a failure of the &lt;em&gt;goal&lt;/em&gt;, not the construction.&lt;/p&gt;

The stronger targets a confidentiality-only mode provably fails. IND-CCA2 (indistinguishability under adaptive chosen-ciphertext attack) hands the adversary a decryption oracle for any ciphertext but the challenge; non-malleability forbids turning one ciphertext into a predictably related one. Because all five SP 800-38A modes are malleable, none is IND-CCA2. Part 1 of this series formalizes both goals -- here they are exactly what a MAC restores.
&lt;p&gt;You can run the attack from the opening. The demo below encrypts a payment instruction with a toy keystream, then, knowing only the message format, rewrites the amount by XORing a delta into the ciphertext. No key is ever touched:&lt;/p&gt;
&lt;p&gt;{`
// Toy CTR: P = C XOR keystream. Editing C edits P, with no key. NOT real crypto.
function xorBytes(a, b) { return a.map(function (x, i) { return x ^ b[i]; }); }
function toBytes(s) { return Array.from(s).map(function (c) { return c.charCodeAt(0); }); }
function toStr(b) { return b.map(function (x) { return String.fromCharCode(x); }).join(&apos;&apos;); }&lt;/p&gt;
&lt;p&gt;var plaintext = &apos;amount:0000009&apos;;                 // the honest instruction
var keystream = toBytes(&apos;SECRETPADSECRET&apos;).slice(0, plaintext.length);&lt;/p&gt;
&lt;p&gt;// Sender encrypts. The attacker sees only C -- never the key, never the keystream.
var C = xorBytes(toBytes(plaintext), keystream);&lt;/p&gt;
&lt;p&gt;// The attacker knows the fixed message FORMAT and wants this instead:
var target = &apos;amount:9000000&apos;;                    // same length, this is the &quot;9 -&amp;gt; 9,000,000&quot; edit
var delta = xorBytes(toBytes(plaintext), toBytes(target));  // computable from the format alone&lt;/p&gt;
&lt;p&gt;// He XORs the delta straight into the ciphertext.
var forged = xorBytes(C, delta);&lt;/p&gt;
&lt;p&gt;// The receiver decrypts with the real keystream and sees the forgery.
console.log(&apos;Receiver reads: &apos; + toStr(xorBytes(forged, keystream)));  // amount:9000000
console.log(&apos;Keys or keystream used by the attacker: none.&apos;);
`}&lt;/p&gt;
&lt;p&gt;The same edit, drawn as it happens on the wire:&lt;/p&gt;

sequenceDiagram
    participant S as Sender
    participant A as Attacker
    participant R as Receiver
    S-&amp;gt;&amp;gt;A: Ciphertext of a nine-dollar transfer
    Note over A: Cannot read it, AES is unbroken
    Note over A: But P is C XOR keystream, so flipping ciphertext bit i flips plaintext bit i
    A-&amp;gt;&amp;gt;A: XOR a chosen delta into the amount bytes
    A-&amp;gt;&amp;gt;R: Modified ciphertext
    Note over R: Decrypts to a nine-million transfer, perfectly well-formed
    R-&amp;gt;&amp;gt;R: Accepts the forgery as authentic

Confidentiality without integrity is not weaker encryption. It is a different, largely illusory guarantee.
&lt;p&gt;Now turn the lens on the historical record. Every famous break of these modes is one of two diagnoses -- a missing integrity answer, or a violated IV/nonce contract:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Break&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Root cause&lt;/th&gt;
&lt;th&gt;Lesson&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Adobe [@troyhunt-adobe-2013]&lt;/td&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;ECB&lt;/td&gt;
&lt;td&gt;confidentiality answered wrongly (determinism)&lt;/td&gt;
&lt;td&gt;never ECB for messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Padding oracle, Vaudenay [@vaudenay-2002]&lt;/td&gt;
&lt;td&gt;2002&lt;/td&gt;
&lt;td&gt;CBC&lt;/td&gt;
&lt;td&gt;no integrity plus a distinguishable padding check&lt;/td&gt;
&lt;td&gt;verify before decrypting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BEAST [@bard-2004][@cve-2011-3389]&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;CBC&lt;/td&gt;
&lt;td&gt;violated IV contract (predictable IV)&lt;/td&gt;
&lt;td&gt;IVs must be unpredictable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lucky Thirteen [@lucky-thirteen-2013]&lt;/td&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;CBC&lt;/td&gt;
&lt;td&gt;wrong composition order plus a timing leak&lt;/td&gt;
&lt;td&gt;Encrypt-then-MAC, constant time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POODLE [@poodle-2014][@cve-2014-3566]&lt;/td&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;CBC (SSL 3.0)&lt;/td&gt;
&lt;td&gt;padding oracle after a downgrade&lt;/td&gt;
&lt;td&gt;retire the mode and the fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sweet32 [@sweet32-2016][@cve-2016-2183]&lt;/td&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;CBC (64-bit)&lt;/td&gt;
&lt;td&gt;block-size birthday bound&lt;/td&gt;
&lt;td&gt;no 64-bit ciphers for bulk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Efail [@efail-2018]&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;CBC / CFB&lt;/td&gt;
&lt;td&gt;missing integrity (malleability gadget)&lt;/td&gt;
&lt;td&gt;authenticate the ciphertext&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Truncation, Smyth-Pironti [@smyth-pironti-2013]&lt;/td&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;TLS record (any mode)&lt;/td&gt;
&lt;td&gt;missing integrity of length and framing (omission)&lt;/td&gt;
&lt;td&gt;authenticate the end, not just the bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GCM nonce reuse [@joux-2006][@nonce-disrespecting-2016]&lt;/td&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;CTR / GCM&lt;/td&gt;
&lt;td&gt;violated nonce contract&lt;/td&gt;
&lt;td&gt;never repeat a (key, nonce)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Most of these breaks edit or leak bytes, but the subtlest one deletes them. Ben Smyth and Alfredo Pironti showed at WOOT 2013 that silently &lt;em&gt;truncating&lt;/em&gt; a TLS stream -- cutting it short at an attacker-chosen point -- changes the meaning a web application infers from a &quot;complete&quot; response, because the record layer authenticated the bytes it carried but never the fact that the message had &lt;em&gt;ended&lt;/em&gt; [@smyth-pironti-2013]. That is an integrity failure of omission, and it is why the fix in Section 10 authenticates length and end-of-stream, not just content. Most of the rest are TLS history, which the &lt;a href=&quot;https://paragmali.com/blog/rotating-every-cipher-schannel-and-the-twenty-year-algorithm&quot; rel=&quot;noopener&quot;&gt;SChannel post&lt;/a&gt; tells from the deployment side.Precision on GCM nonce reuse: one repeated $(\text{key}, \text{nonce})$ &lt;em&gt;immediately&lt;/em&gt; leaks $P_1 \oplus P_2$, but uniquely recovering the GHASH subkey $H$ generally needs two or more collisions. Never say &quot;one reuse leaks $H$&quot; [@joux-2006].The routinely mis-cited CVE-2016-0270 actually names IBM Domino, not OpenSSL, and NVD warns it &quot;has been incorrectly used for GCM nonce reuse issues in other products.&quot; The deployed GCM-nonce forgery is the Nonce-Disrespecting Adversaries paper, whose byline is exactly five authors: Boeck, Zauner, Devlin, Somorovsky, and Jovanovic [@cve-2016-0270][@nonce-disrespecting-2016].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A bare confidentiality mode lets an attacker edit your plaintext undetected -- bit-for-bit in CTR and OFB, a surgical bit plus a garbled next block in CFB, and block-coupled in CBC. Use an AEAD, or Encrypt-then-MAC and verify the tag &lt;em&gt;before&lt;/em&gt; you decrypt a single byte.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The fix is to add the missing answer, and the order in which you add it turns out to matter. Bellare and Namprempre (2000) and Krawczyk (2001) proved that &lt;strong&gt;Encrypt-then-MAC&lt;/strong&gt; -- encrypt, then MAC the ciphertext, and verify the tag before decrypting -- generically yields both IND-CPA and INT-CTXT, a scheme that is confidential &lt;em&gt;and&lt;/em&gt; unforgeable, while MAC-then-encrypt and encrypt-and-MAC are fragile [@bellare-namprempre-2000][@krawczyk-2001].&lt;/p&gt;

A keyed tag that proves a message was not altered and came from someone holding the key. Anyone with the key can compute the tag over a message; without it, forging a valid tag is infeasible. HMAC, CMAC, and CBC-MAC are common constructions. A MAC supplies the integrity answer a confidentiality mode leaves blank.

SSL and early TLS shipped MAC-then-encrypt. The theory said Encrypt-then-MAC was the safe generic choice. That debate was not settled by proof alone -- it was settled by a decade of breaks (BEAST, Lucky Thirteen, POODLE) that all exploited the MAC-then-encrypt-plus-CBC-padding surface, until TLS 1.3 removed CBC outright and mandated authenticated encryption [@krawczyk-2001][@rfc-8446-tls13].
&lt;p&gt;Better still, fuse the two answers into one primitive.&lt;/p&gt;

A single primitive that provides confidentiality *and* integrity at once, and can also authenticate unencrypted &quot;associated data&quot; such as headers. It answers both questions in one object, so a modified ciphertext is rejected before any plaintext is released.
&lt;p&gt;The punchline binds this whole article together: the dominant &lt;em&gt;AES&lt;/em&gt; AEADs are literally these modes plus a MAC. &lt;strong&gt;GCM equals CTR plus GHASH&lt;/strong&gt;, a polynomial hash over $GF(2^{128})$ [@mcgrew-viega-2004][@nist-sp-800-38d]. &lt;strong&gt;CCM equals CTR plus CBC-MAC&lt;/strong&gt; [@rfc-3610-ccm][@nist-sp-800-38c]. The 1979 counter idea and the 1976 chaining idea, welded into a primitive that finally answers both questions -- the &lt;a href=&quot;https://paragmali.com/blog/the-connection-that-refused-to-downgrade-twenty-five-years-o&quot; rel=&quot;noopener&quot;&gt;SMB 3.1.1 post&lt;/a&gt; shows GCM and CCM running in a real protocol.&lt;/p&gt;

flowchart TD
    P[&quot;Plaintext&quot;] --&amp;gt; CTR[&quot;CTR encryption&quot;]
    CTR --&amp;gt; C[&quot;Ciphertext&quot;]
    C --&amp;gt; M[&quot;MAC over ciphertext and associated data&quot;]
    M --&amp;gt; T[&quot;Authentication tag&quot;]
    C --&amp;gt; W[&quot;Transmit ciphertext plus tag&quot;]
    T --&amp;gt; W
    W --&amp;gt; V{&quot;Tag valid?&quot;}
    V --&amp;gt;|&quot;no&quot;| X[&quot;Reject, decrypt nothing&quot;]
    V --&amp;gt;|&quot;yes&quot;| D[&quot;Decrypt and release plaintext&quot;]
&lt;p&gt;One boundary to keep honest: not every modern AEAD is built from these modes. ChaCha20-Poly1305 (a stream cipher plus Poly1305) and Ascon (a sponge permutation) are first-class AEADs that are deliberately &lt;em&gt;not&lt;/em&gt; SP 800-38A constructions [@rfc-8439-chacha20][@nist-sp-800-232]. The lineage claim is bounded to the AES AEADs.&lt;/p&gt;
&lt;p&gt;With integrity finally bolted on, every entry in the catalog retroactively dies -- a modified ciphertext fails the tag before a byte is decrypted. So the field declared victory and shipped AEAD everywhere. Then it discovered that AEAD did not repeal the IV/nonce contract. It &lt;em&gt;sharpened&lt;/em&gt; it -- which is exactly where the state of the art picks up.&lt;/p&gt;
&lt;h2&gt;6. The Field Is Retiring Confidentiality-Only Modes&lt;/h2&gt;
&lt;p&gt;The modern answer to &quot;which block cipher mode should I use?&quot; is &lt;em&gt;no bare confidentiality mode at all.&lt;/em&gt; It is a choice of AEAD, and between 2024 and 2026 that answer stopped being folklore and became written policy. The tell is what the standards bodies did &lt;em&gt;not&lt;/em&gt; do. Faced with four decades of breaks, nobody proposed a sixth confidentiality mode. Every document below reaches instead for authentication.&lt;/p&gt;
&lt;p&gt;Start with the audit. NIST IR 8459, published in September 2024 by Nicky Mouha and Morris Dworkin, is the first formal review of the entire SP 800-38 series, and it reads less like a specification than a post-mortem: it works through the family mode by mode, documenting why each keeps failing, and its recommendations point at authenticated encryption rather than a patched mode -- down to disallowing ECB for the very job it keeps losing at, encrypting secrets [@nist-ir-8459]. An audit whose answer to &quot;which new mode?&quot; is &quot;stop adding modes&quot; is this whole section in miniature.&lt;/p&gt;
&lt;p&gt;The policy machinery had already started turning. In April 2023 NIST&apos;s Crypto Publication Review Board published its decision to revise SP 800-38A itself, with goals that read like a confession: to &quot;limit the approval of the Electronic Codebook (ECB) mode,&quot; to &quot;provide guidance on the importance of incorporating authentication, where feasible,&quot; to fold in &quot;three variations of ciphertext stealing for Cipher Block Chaining mode,&quot; and -- once a stronger technique exists -- to &quot;consider deprecating the modes in SP 800-38A&quot; [@csrc-sp38a-revision-2023]. The document that defines the five modes is contemplating its own retirement, and names authenticated encryption as the successor it is waiting on.&lt;/p&gt;
&lt;p&gt;SP 800-131A Revision 3 supplies the compliance lever. Its initial public draft of October 21, 2024 disallows ECB for encrypting secret data and relegates it to legacy (decrypt-only) use; the draft&apos;s own phrase is &quot;the retirement of ECB as a confidentiality mode of operation&quot; [@nist-sp-800-131a-r3]. For a FIPS-bound product that is an effective-on-finalization change, not a suggestion.&lt;/p&gt;
&lt;p&gt;Where the field is heading is just as clear from what it &lt;em&gt;standardized&lt;/em&gt;. Ascon, finalized as NIST SP 800-232 in August 2025, is the new AEAD for the constrained, low-power class for which earlier standards specified AES-CCM -- and it is a sponge permutation, pointedly &lt;em&gt;not&lt;/em&gt; an SP 800-38A block cipher mode [@nist-sp-800-232]. &quot;Migrate to AEAD&quot; does not mean &quot;migrate to a mode.&quot; And for the one contract even AEADs still impose, AES-GCM-SIV (RFC 8452, 2019) is the standardized hedge: a nonce-misuse-resistant scheme that degrades gracefully instead of catastrophically when a nonce repeats [@rfc-8452-gcm-siv].&lt;/p&gt;

An AEAD that stays secure even when a nonce is accidentally reused, leaking at most whether two identical messages were sent under the same nonce, instead of collapsing into a two-time pad and forgery. AES-GCM-SIV reaches this by deriving its internal counter from a MAC of the whole message, so a repeat is a mild, bounded leak rather than a catastrophe [@rfc-8452-gcm-siv][@gcm-siv-spec-2017].

AES-GCM-SIV is engineered to be &quot;nonce misuse resistant -- that is, [it does] not fail catastrophically if a nonce is repeated.&quot; -- RFC 8452
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Document&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;NIST IR 8459 [@nist-ir-8459]&lt;/td&gt;
&lt;td&gt;audits the whole SP 800-38 series; steers ECB and secrets toward AEAD&lt;/td&gt;
&lt;td&gt;published, Sept 2024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decision to revise SP 800-38A [@csrc-sp38a-revision-2023]&lt;/td&gt;
&lt;td&gt;limit ECB, add CBC ciphertext stealing, urge authentication, weigh deprecation&lt;/td&gt;
&lt;td&gt;published, Apr 2023&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SP 800-131A Rev. 3 [@nist-sp-800-131a-r3]&lt;/td&gt;
&lt;td&gt;moves ECB to legacy (decrypt-only) use; disallowed for encrypting secrets on publication&lt;/td&gt;
&lt;td&gt;draft (Oct 21, 2024 IPD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ascon (SP 800-232) [@nist-sp-800-232]&lt;/td&gt;
&lt;td&gt;a permutation AEAD for constrained devices, deliberately not a 38A mode&lt;/td&gt;
&lt;td&gt;final, Aug 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-GCM-SIV (RFC 8452) [@rfc-8452-gcm-siv]&lt;/td&gt;
&lt;td&gt;a nonce-misuse-resistant AEAD hedge&lt;/td&gt;
&lt;td&gt;published, 2019&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The migration is credible &lt;em&gt;now&lt;/em&gt;, rather than merely aspirational, because the substrate already moved. TLS 1.3 (RFC 8446, 2018) removed every CBC-mode cipher suite and makes AES-GCM its mandatory-to-implement AEAD [@rfc-8446-tls13]; QUIC protects every packet with an AEAD, binding the packet number directly into the AEAD nonce, with no unauthenticated-confidentiality option at all [@rfc-9001-quic-tls].&lt;/p&gt;
&lt;p&gt;The performance objection that once favored CBC also evaporated: with AES-NI and the carry-less multiply instruction PCLMULQDQ, AES-GCM fell from roughly 3.7 cycles per byte in optimized software toward about 1, so the fast path and the safe path are now the same path [@krovetz-rogaway-ae-2011][@gcm-siv-spec-2017]. The 2024-2026 standards are simply retiring the confidentiality-only modes to match a deployment reality that migrated years earlier.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The modern &quot;which mode?&quot; question is really &quot;which AEAD?&quot; The five SP 800-38A confidentiality-only modes now survive as &lt;em&gt;internals&lt;/em&gt; of authenticated encryption and as legacy interoperability options -- not as something you deploy on purpose.&lt;/p&gt;
&lt;/blockquote&gt;

Not every SP 800-38 sibling is a confidentiality mode. SP 800-38G defines FF1 and FF3, *format-preserving* encryption that turns a 16-digit card number into another 16-digit string so it still fits a legacy database column [@nist-sp-800-38g]. Different goal, and it came with its own break: Durak and Vaudenay gave a practical total recovery of FF3 over small domains, a slide attack exploiting the design&apos;s &quot;bad domain separation&quot; in roughly $O(N^{11/6})$ chosen plaintexts [@durak-vaudenay-2017]. NIST responded with FF3-1, shrinking the tweak from 64 to 56 bits and raising the minimum domain to one million [@nist-sp-800-38g-r1]. Signposted here, not surveyed -- it is not one of the five.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Reach for a vetted AEAD -- AES-GCM or ChaCha20-Poly1305 -- give it a unique nonce per key, cap your messages under the nonce limit, and drop to a raw confidentiality mode only as an Encrypt-then-MAC building block when an AEAD is genuinely unavailable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The cross-references write themselves: the CBC-to-GCM migration is the story the &lt;a href=&quot;https://paragmali.com/blog/rotating-every-cipher-schannel-and-the-twenty-year-algorithm&quot; rel=&quot;noopener&quot;&gt;SChannel post&lt;/a&gt; tells for Windows TLS, and GCM and CCM running in a shipping protocol is what the &lt;a href=&quot;https://paragmali.com/blog/the-connection-that-refused-to-downgrade-twenty-five-years-o&quot; rel=&quot;noopener&quot;&gt;SMB 3.1.1 post&lt;/a&gt; shows. So the strategic direction is settled: move to AEAD. But &quot;AEAD&quot; is not one thing. The moment you have to &lt;em&gt;ship&lt;/em&gt;, the question sharpens from &quot;which mode?&quot; to &quot;which AEAD, with which parameters, for which platform?&quot; -- and that has a real, defensible answer.&lt;/p&gt;
&lt;h2&gt;7. When You Must Pick a Mode, and Which AEAD&lt;/h2&gt;
&lt;p&gt;Two comparisons matter in practice. The first is the intra-family one folklore gets wrong. The second is the one you actually face when you ship.&lt;/p&gt;
&lt;h3&gt;CBC versus CTR: a choice that changes nothing that matters&lt;/h3&gt;
&lt;p&gt;Both are confidentiality-only, both are malleable, and both are still everywhere. On the merits CTR is superior: fully parallel on encryption and decryption, random-access, and governed by the simplest contract (a unique nonce). CBC survives on forty years of deployment inertia, not on technical advantage -- Rogaway, having surveyed all five modes, reports &quot;no important advantages over CTR mode&quot; for CBC [@rogaway-modes-2011].&lt;/p&gt;
&lt;p&gt;But here is the point most tuning guides miss: swapping CBC for CTR fixes nothing that matters, because neither answers the second question. You trade a serial mode with padding for a parallel mode without it, and you keep every bit of the malleability. If your reason for the swap is security, you are solving the wrong problem.&lt;/p&gt;
&lt;h3&gt;Which AEAD&lt;/h3&gt;
&lt;p&gt;This is the comparison with real stakes, and every option is a defensible answer to a different constraint. AES-GCM is the throughput default on modern CPUs, hardware-accelerated by AES-NI and CLMUL, and brittle exactly where humans err -- a single reused nonce is catastrophic [@nist-sp-800-38d]. ChaCha20-Poly1305 is the software default: constant-time by construction, with no AES hardware and no cache-timing hazard [@rfc-8439-chacha20]. AES-CCM is CTR plus CBC-MAC, two-pass and small-footprint [@rfc-3610-ccm][@nist-sp-800-38c]; those documents define CCM, and its compact profile is why the IEEE wireless standards adopt it -- WPA2 (802.11i) [@krovetz-rogaway-ae-2011] and IEEE 802.15.4 low-power wireless [@rfc-4944][@rfc-9031] both build their link-layer security on it. AES-GCM-SIV is the nonce-misuse-resistant hedge [@rfc-8452-gcm-siv]. Ascon is the lightweight standard for microcontrollers [@nist-sp-800-232].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;AEAD&lt;/th&gt;
&lt;th&gt;Built from&lt;/th&gt;
&lt;th&gt;Passes&lt;/th&gt;
&lt;th&gt;Constant-time&lt;/th&gt;
&lt;th&gt;Nonce-reuse penalty&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;AES-GCM [@nist-sp-800-38d]&lt;/td&gt;
&lt;td&gt;CTR + GHASH&lt;/td&gt;
&lt;td&gt;1, online&lt;/td&gt;
&lt;td&gt;needs AES-NI, CLMUL&lt;/td&gt;
&lt;td&gt;catastrophic (forgery)&lt;/td&gt;
&lt;td&gt;server bulk, TLS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ChaCha20-Poly1305 [@rfc-8439-chacha20]&lt;/td&gt;
&lt;td&gt;stream + Poly1305&lt;/td&gt;
&lt;td&gt;1, online&lt;/td&gt;
&lt;td&gt;by construction (software)&lt;/td&gt;
&lt;td&gt;catastrophic&lt;/td&gt;
&lt;td&gt;mobile, no AES hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-CCM [@rfc-3610-ccm]&lt;/td&gt;
&lt;td&gt;CTR + CBC-MAC&lt;/td&gt;
&lt;td&gt;2, not online&lt;/td&gt;
&lt;td&gt;needs AES-NI&lt;/td&gt;
&lt;td&gt;catastrophic&lt;/td&gt;
&lt;td&gt;WPA2, IoT, small code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-GCM-SIV [@rfc-8452-gcm-siv]&lt;/td&gt;
&lt;td&gt;POLYVAL-SIV + CTR&lt;/td&gt;
&lt;td&gt;2, not online&lt;/td&gt;
&lt;td&gt;needs AES-NI, CLMUL&lt;/td&gt;
&lt;td&gt;graceful (leak equality)&lt;/td&gt;
&lt;td&gt;nonce-uncertain systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ascon [@nist-sp-800-232]&lt;/td&gt;
&lt;td&gt;sponge permutation&lt;/td&gt;
&lt;td&gt;1 (duplex)&lt;/td&gt;
&lt;td&gt;easy to protect&lt;/td&gt;
&lt;td&gt;catastrophic&lt;/td&gt;
&lt;td&gt;microcontrollers, IoT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The performance folklore is worth correcting too. The cleanest apples-to-apples software measurement, Krovetz and Rogaway at FSE 2011 on an Intel i5 &quot;Clarkdale,&quot; found CCM near 4.2 cycles per byte, GCM near 3.7, OCB near 1.5, and raw CTR near 1.3 [@krovetz-rogaway-ae-2011]. Read that as an &lt;em&gt;ordering&lt;/em&gt; under fixed effort, not a modern absolute: with mature AES-NI and CLMUL, AES-GCM reaches roughly 1 cycle per byte on current x86 [@gcm-siv-spec-2017]. The durable lesson is that hardware, not algorithm choice, moved GCM from 3.7 to 1 -- which is the whole reason CTR-based AEADs won.&lt;/p&gt;

The two non-38A AEADs from Section 5, ChaCha20-Poly1305 and Ascon, sit within a broader research lineage -- OCB, EAX, SIV/AES-SIV, IACBC/IAPM, McOE -- that is real but out of scope here; OCB is the elegant one-pass design that patents kept out of deployment for years [@rfc-7253-ocb].
&lt;p&gt;Every column wins on some axis and loses on another; none is unconditionally best. And the reasons &lt;em&gt;why&lt;/em&gt; no single scheme dominates are not engineering accidents. They are theorems. To use any of these correctly, you have to know the walls they are all pressed against.&lt;/p&gt;
&lt;h2&gt;8. You Cannot Get Integrity From a Confidentiality Mode&lt;/h2&gt;
&lt;p&gt;The two-question frame is not merely good advice. It is a theorem, and it draws a hard line no amount of clever engineering crosses.&lt;/p&gt;
&lt;p&gt;Start with the central impossibility. IND-CPA does not imply IND-CCA2 or non-malleability; BDJR proved ECB is not even IND-CPA and that CBC and CTR &lt;em&gt;are&lt;/em&gt; IND-CPA with proper IVs and nonces, but IND-CPA says nothing about an active attacker editing ciphertext [@bdjr-1997]. Bellare and Namprempre sharpened the target, separating INT-PTXT from INT-CTXT and proving that only Encrypt-then-MAC generically delivers IND-CPA plus INT-CTXT [@bellare-namprempre-2000][@krawczyk-2001].&lt;/p&gt;
&lt;p&gt;The consequence is a lower bound, not a tip: you cannot patch integrity into a bare CTR, CBC, CFB, or OFB mode, because malleability is a property of the confidentiality &lt;em&gt;goal&lt;/em&gt;, not a bug in any &lt;em&gt;construction&lt;/em&gt;. This is the reasoning &lt;a href=&quot;https://paragmali.com/blog/secure-against-whom-the-security-definitions-every-protocol-&quot; rel=&quot;noopener&quot;&gt;Part 1&lt;/a&gt; sets up in full.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; &quot;Confidentiality does not imply integrity&quot; is a theorem, not advice. IND-CPA does not imply IND-CCA2 or non-malleability, so you cannot patch integrity into a bare CTR, CBC, CFB, or OFB mode. It is a property of the goal, not a bug in the construction.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second wall is the block size.&lt;/p&gt;

The threshold at which collisions among random $n$-bit values become likely: around $2^{n/2}$ of them. For a block cipher it means ciphertext blocks start repeating -- and leaking $P_i \oplus P_j$ -- after roughly $2^{n/2}$ blocks, regardless of key length. This is the ceiling behind Sweet32 and the GCM nonce cap.
&lt;p&gt;Ciphertext-collision leakage grows like $q^2 / 2^n$ in the number of blocks $q$, so security degrades at about $q \approx 2^{n/2}$ blocks: roughly $2^{32}$ blocks (about 32 GiB) for a 64-bit cipher, which is the Sweet32 ceiling, and $2^{64}$ blocks for AES [@bdjr-1997][@sweet32-2016]. A provable ceiling, independent of key size -- doubling the key does not move it.&lt;/p&gt;
&lt;p&gt;GCM inherits its own two ceilings, and conflating them is a common error. Per SP 800-38D, a single message is capped at $2^{39} - 256$ bits (about 64 GiB), and, under random 96-bit nonces, the number of invocations per key must stay below about $2^{32}$ to keep the nonce-collision probability negligible [@nist-sp-800-38d]. One is a length limit; the other is a count limit. They are different numbers that both bite.&lt;/p&gt;
&lt;p&gt;The last wall is the sharpest, because no computational assumption stands behind it. Reusing a $(\text{key}, \text{nonce})$ in any keystream mode leaks $C_1 \oplus C_2 = P_1 \oplus P_2$ -- a two-time pad. You can watch it recover a plaintext with nothing but XOR:&lt;/p&gt;
&lt;p&gt;{`
// Reusing a (key, nonce) reproduces the SAME keystream. That is a two-time pad.
function xorBytes(a, b) { return a.map(function (x, i) { return x ^ b[i]; }); }
function toBytes(s) { return Array.from(s).map(function (c) { return c.charCodeAt(0); }); }
function toStr(b) { return b.map(function (x) { return String.fromCharCode(x); }).join(&apos;&apos;); }&lt;/p&gt;
&lt;p&gt;var p1 = &apos;attack at dawn&apos;;
var p2 = &apos;defend the fort&apos;;
var n = Math.min(p1.length, p2.length);
var ks = toBytes(&apos;REUSEDPADREUSEDPAD&apos;).slice(0, n);   // the SAME pad used twice -- the bug&lt;/p&gt;
&lt;p&gt;var c1 = xorBytes(toBytes(p1).slice(0, n), ks);
var c2 = xorBytes(toBytes(p2).slice(0, n), ks);&lt;/p&gt;
&lt;p&gt;// The attacker never has the key. He XORs the two ciphertexts; the pad cancels:
var leaked = xorBytes(c1, c2);                         // equals p1 XOR p2&lt;/p&gt;
&lt;p&gt;// With a crib -- a good guess at p1 -- he recovers p2 outright:
var crib = toBytes(&apos;attack at dawn&apos;).slice(0, n);
console.log(&apos;Recovered from a crib: &apos; + toStr(xorBytes(leaked, crib)));  // defend the for
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Reusing a $(\text{key}, \text{nonce})$ leaks $P_1 \oplus P_2$ with no computational assumption to fall back on -- no key length saves you. In GCM it is worse: repeated nonces also expose the GHASH subkey $H$ -- uniquely, once two or more collisions accumulate -- enabling universal forgery [@joux-2006][@nist-sp-800-38d].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The core science, then, is closed. &quot;Confidentiality does not imply integrity&quot; is settled, reuse is an information-theoretic floor, and the block-size wall is provable. If the theory is finished, what is left to work on? More than you would guess -- and it is where the modes still bite.&lt;/p&gt;
&lt;h2&gt;9. Where Modes Still Bite&lt;/h2&gt;
&lt;p&gt;The confidentiality-versus-integrity fight is won. The live frontier is one level up: not &quot;is it confidential?&quot; but &quot;how &lt;em&gt;resilient&lt;/em&gt; is the authenticated scheme when humans and hardware misbehave?&quot; Four problems are genuinely open, and one popular worry is not a problem at all.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make nonce-misuse-resistance the default, not the hedge.&lt;/strong&gt; AES-GCM fails catastrophically on nonce reuse, yet reuse -- from stateless senders, VM clones, restarted counters -- is among the most common real misuses [@nist-sp-800-38d]. AES-GCM-SIV delivers graceful degradation at roughly 1 cycle per byte and up to $2^{50}$ messages per key, &quot;well suited for real world applications that need a nonce-misuse resistant Authenticated Encryption scheme&quot; [@gcm-siv-spec-2017].&lt;/p&gt;
&lt;p&gt;But it is two-pass and offline, and it remains opt-in. The open problem is an AEAD that is online, single-pass, parallel, roughly 1 cycle per byte, &lt;em&gt;and&lt;/em&gt; misuse-resistant at once -- and, harder, getting TLS and KMS libraries to make it the default. NIST IR 8459 flags nonce management across the whole SP 800-38 series as a first-order concern [@nist-ir-8459].&lt;/p&gt;

The property that binds a ciphertext to the single key and context that produced it, so it cannot be made to decrypt validly under a second key. Standard AEAD security says nothing about it, which is why AES-GCM and ChaCha20-Poly1305 lack it -- and why a ciphertext can be crafted to open to two different valid plaintexts under two different keys.
&lt;p&gt;&lt;strong&gt;Key commitment and robustness.&lt;/strong&gt; AES-GCM and ChaCha20-Poly1305 are not key-committing: a single ciphertext can be built to decrypt to valid plaintexts under &lt;em&gt;two&lt;/em&gt; different keys [@key-commitment-2022]. Real systems assume otherwise, so this breaks password-based encryption, message franking, and envelope schemes.&lt;/p&gt;
&lt;p&gt;Partitioning-oracle attacks turned that gap into practical password recovery against Shadowsocks proxies; the same study only &lt;em&gt;surveyed&lt;/em&gt; protocols such as OPAQUE as potentially vulnerable rather than breaking them [@partitioning-oracles-2021]. The &quot;invisible salamanders&quot; attack built AES-GCM ciphertexts that decrypt to valid files under two keys, defeating message franking [@fast-franking-2018], a technique later generalized across file formats [@key-commitment-2022]. A genuine lower bound -- compactly committing AE is provably impossible at AES-GCM&apos;s exact performance profile [@fast-franking-2018] -- meets a cheap upper bound -- committing GCM and GCM-SIV variants at no ciphertext expansion [@committing-ae-2022]. The bounds nearly meet, yet the deployed default still sits on the wrong side.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constant-time implementation.&lt;/strong&gt; CBC-decrypt-then-MAC timing gave us Lucky Thirteen, and table-based AES and GHASH leak through cache [@lucky-thirteen-2013]. This is effectively solved on hardware with AES-NI and CLMUL, and ChaCha20-Poly1305 is constant-time by design [@rfc-8439-chacha20]. It stays a live hazard on microcontrollers and throughout the legacy CBC base.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The forty-year migration.&lt;/strong&gt; A vast deployed base still runs CBC and 64-bit block ciphers, keeping Sweet32 and padding oracles alive. TLS 1.3 removed CBC-mode cipher suites and mandates AEAD [@rfc-8446-tls13], and IR 8459 audits the whole series [@nist-ir-8459], but embedded firmware, file-format crypto, database encryption, and private protocols lag by years. This is an engineering and logistics problem, not a mathematical one -- and it is the one that keeps the Failure Catalog growing.&lt;/p&gt;

A widespread belief holds that quantum computers break block cipher modes. To first order they do not: Grover&apos;s algorithm gives only a quadratic speedup on key search, so doubling the key (AES-256) restores the margin. The post-quantum churn is in key exchange and signatures, not in symmetric modes or AEADs [@nist-ir-8105].
&lt;p&gt;None of these is a hole in the confidentiality-versus-integrity theory. All are the gap between the ideal AEAD and the one you can install today -- which is exactly the gap a practitioner has to bridge. So here are the rules that bridge it.&lt;/p&gt;
&lt;h2&gt;10. Use X With These Params In Case Y&lt;/h2&gt;
&lt;p&gt;Everything so far collapses into one rule and a short decision tree you can apply without re-deriving a theorem. The rule: use a vetted AEAD, not a raw confidentiality mode [@ferguson-schneier-kohno-2010].&lt;/p&gt;
&lt;p&gt;The decision guide, in priority order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Default:&lt;/strong&gt; AES-GCM with a 96-bit nonce, unique per key -- prefer a deterministic counter -- and a hard cap of fewer than $2^{32}$ messages per key [@nist-sp-800-38d].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cannot guarantee unique nonces:&lt;/strong&gt; AES-GCM-SIV [@rfc-8452-gcm-siv], or XChaCha20-Poly1305, which widens the RFC 8439 ChaCha20-Poly1305 construction to a 192-bit random nonce [@rfc-8439-chacha20].The 192-bit-nonce XChaCha20 variant is specified in the IRTF draft draft-irtf-cfrg-xchacha, not in RFC 8439, which standardizes only the 96-bit ChaCha20-Poly1305 [@rfc-8439-chacha20]. The wider nonce is exactly what lets you pick nonces at random without tracking a counter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No fast AES hardware, or you need constant-time software:&lt;/strong&gt; ChaCha20-Poly1305 [@rfc-8439-chacha20].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Constrained or IoT, small code budget:&lt;/strong&gt; Ascon-AEAD128 [@nist-sp-800-232] or AES-CCM [@rfc-3610-ccm].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Need key or context commitment&lt;/strong&gt; (password-based encryption, franking, envelope, rotation): a committing AEAD [@committing-ae-2022].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Must drop to a raw mode&lt;/strong&gt; (interoperability or a FIPS boundary): CTR plus Encrypt-then-MAC (CMAC or HMAC) with a unique nonce, or CBC only with a fresh &lt;em&gt;unpredictable&lt;/em&gt; IV plus Encrypt-then-MAC plus constant-time padding [@nist-sp-800-38a][@bellare-namprempre-2000].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Streaming or large objects:&lt;/strong&gt; do not ship one monolithic AEAD blob you cannot buffer. Split the stream into records, give each a unique per-chunk nonce, and authenticate a sequence number plus an explicit end-of-stream marker, so a dropped, reordered, or truncated record is caught rather than silently accepted. This is the record-protocol pattern DTLS 1.3 uses -- rejecting duplicates through &quot;a sliding receive window&quot; -- and that QUIC uses by binding each packet number into its AEAD nonce; together they close truncation and replay, the two integrity gaps a bare mode cannot see [@smyth-pironti-2013][@rfc-9147-dtls13][@rfc-9001-quic-tls].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Never:&lt;/strong&gt; ECB for messages, a 64-bit block cipher for bulk data, a reused nonce, or &quot;encryption&quot; with no integrity tag.&lt;/li&gt;
&lt;/ol&gt;

flowchart TD
    Start[&quot;Need to encrypt a message&quot;] --&amp;gt; Q1{&quot;Is a vetted AEAD available?&quot;}
    Q1 --&amp;gt;|&quot;no&quot;| Raw[&quot;CTR or CBC plus Encrypt-then-MAC, verify tag first&quot;]
    Q1 --&amp;gt;|&quot;yes&quot;| Q2{&quot;Can you guarantee unique nonces?&quot;}
    Q2 --&amp;gt;|&quot;no&quot;| NMR[&quot;AES-GCM-SIV or XChaCha20-Poly1305 (192-bit nonce)&quot;]
    Q2 --&amp;gt;|&quot;yes&quot;| Q3{&quot;Fast AES hardware present?&quot;}
    Q3 --&amp;gt;|&quot;no&quot;| Chacha[&quot;ChaCha20-Poly1305&quot;]
    Q3 --&amp;gt;|&quot;yes&quot;| Q4{&quot;Constrained device?&quot;}
    Q4 --&amp;gt;|&quot;yes&quot;| Small[&quot;Ascon-AEAD128 or AES-CCM&quot;]
    Q4 --&amp;gt;|&quot;no&quot;| GCM[&quot;AES-GCM, 96-bit nonce, fewer than 2^32 messages per key&quot;]
&lt;p&gt;When you do touch a raw mode, the contract is the whole game. &lt;a href=&quot;https://paragmali.com/blog/predictable-or-repeated-the-only-two-ways-cryptographic-rand&quot; rel=&quot;noopener&quot;&gt;Part 2&lt;/a&gt; covers how to &lt;em&gt;generate&lt;/em&gt; these values; this table says what each mode &lt;em&gt;requires&lt;/em&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Consequence of violation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ECB&lt;/td&gt;
&lt;td&gt;none (and that is the flaw)&lt;/td&gt;
&lt;td&gt;determinism leaks block equality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CBC&lt;/td&gt;
&lt;td&gt;unpredictable and unique IV&lt;/td&gt;
&lt;td&gt;a predictable IV enables BEAST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CFB&lt;/td&gt;
&lt;td&gt;unpredictable and unique IV&lt;/td&gt;
&lt;td&gt;a predictable IV enables chosen-plaintext distinguishing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OFB&lt;/td&gt;
&lt;td&gt;unique nonce&lt;/td&gt;
&lt;td&gt;reuse is a two-time pad&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTR&lt;/td&gt;
&lt;td&gt;unique nonce (unpredictability not required)&lt;/td&gt;
&lt;td&gt;reuse is a two-time pad&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Those requirements come straight from SP 800-38A [@nist-sp-800-38a]; the raw bytes that satisfy them come from a CSPRNG, which the &lt;a href=&quot;https://paragmali.com/blog/a-key-is-only-as-unguessable-as-the-dice-that-made-it-inside&quot; rel=&quot;noopener&quot;&gt;Windows CSPRNG post&lt;/a&gt; covers, and the real API calls that wire AES-CBC and AES-GCM together live in the &lt;a href=&quot;https://paragmali.com/blog/cng-architecture-bcrypt-ncrypt-ksps&quot; rel=&quot;noopener&quot;&gt;CNG post&lt;/a&gt;. Finally, every common misuse maps one-to-one to a named break and its fix:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Misuse&lt;/th&gt;
&lt;th&gt;Named break&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ECB for structured data&lt;/td&gt;
&lt;td&gt;Adobe 2013 [@troyhunt-adobe-2013]&lt;/td&gt;
&lt;td&gt;AEAD over AES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;static or predictable IV&lt;/td&gt;
&lt;td&gt;BEAST [@cve-2011-3389]&lt;/td&gt;
&lt;td&gt;fresh unpredictable IV, or an AEAD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reused GCM nonce&lt;/td&gt;
&lt;td&gt;Nonce-Disrespecting Adversaries [@nonce-disrespecting-2016]&lt;/td&gt;
&lt;td&gt;counter nonces, or GCM-SIV / XChaCha&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MAC-then-encrypt or encrypt-and-MAC&lt;/td&gt;
&lt;td&gt;Lucky Thirteen [@lucky-thirteen-2013]&lt;/td&gt;
&lt;td&gt;Encrypt-then-MAC, verify before decrypt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;no integrity at all&lt;/td&gt;
&lt;td&gt;Efail [@efail-2018]&lt;/td&gt;
&lt;td&gt;an AEAD, or Encrypt-then-MAC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64-bit block cipher for bulk&lt;/td&gt;
&lt;td&gt;Sweet32 [@sweet32-2016]&lt;/td&gt;
&lt;td&gt;a 128-bit-block AEAD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;truncation with no length integrity&lt;/td&gt;
&lt;td&gt;Truncation, Smyth-Pironti [@smyth-pironti-2013]&lt;/td&gt;
&lt;td&gt;authenticate length and end-of-stream&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

Run `openssl s_client -connect example.com:443 -tls1_3` and read the `Cipher` line: a modern server reports an AEAD such as `TLS_AES_128_GCM_SHA256` or `TLS_CHACHA20_POLY1305_SHA256`. If you instead see a suite with `CBC` in the name, you are looking at a legacy, malleable-mode configuration that belongs on the migration list.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Read every mode as a building block with an exact IV/nonce contract, and read every break as a missing integrity answer or a violated contract. Default to an AEAD; touch a raw mode only under Encrypt-then-MAC discipline, and only when an AEAD is off the table.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Notice that every rule is the same rule wearing different clothes: pick the primitive that answers &lt;em&gt;both&lt;/em&gt; questions, and honor its IV/nonce contract. The folklore that gets this wrong is dense enough to deserve its own section.&lt;/p&gt;
&lt;h2&gt;11. Misconceptions, Named and Corrected&lt;/h2&gt;
&lt;p&gt;Seven half-truths cause real incidents. Each dissolves under the same two-question lens.&lt;/p&gt;


No. All five SP 800-38A modes are malleable, so an attacker who cannot read your ciphertext can still predictably edit the plaintext -- bit-for-bit in the additive keystream modes CTR and OFB, block-coupled in CBC, and a mix of the two in CFB. Confidentiality and integrity are different guarantees; you need a MAC or an AEAD to get the second one, and encryption alone does not provide it.


Only as a building block, never as a message-encryption mode. The raw single-block permutation is legitimate inside key wrap and CMAC or CBC-MAC. But ECB is deterministic, so the moment your data has any structure or repetition it leaks block equality -- which is why NIST is moving ECB to legacy use [@nist-sp-800-131a-r3]. The rule is &quot;never ECB for messages,&quot; not &quot;ECB has no use anywhere.&quot;


No. A random IV fixes ECB&apos;s determinism, but it adds no integrity -- the mode is still malleable. And the requirement is not uniform: CBC and CFB need an *unpredictable* IV, while CTR and OFB need only a *unique* nonce [@nist-sp-800-38a]. Getting that distinction wrong is exactly what BEAST exploited.


No. Under random 96-bit nonces you must stay below roughly $2^{32}$ invocations per key to keep the nonce-collision probability negligible [@nist-sp-800-38d]. Past that, a repeat becomes likely, and a repeated GCM nonce fails catastrophically. If you cannot count, use AES-GCM-SIV or XChaCha20-Poly1305 instead.


That fixes nothing that matters. Both are confidentiality-only and both are malleable; swapping one for the other trades performance characteristics, not security [@rogaway-modes-2011]. The fix is an AEAD, not a different malleable mode.


Not under nonce reuse. A single repeated $(\text{key}, \text{nonce})$ leaks $P_1 \oplus P_2$, and with two or more collisions it recovers the GHASH subkey $H$, enabling universal forgery -- Joux&apos;s &quot;forbidden attack,&quot; which was later found live on real TLS servers [@joux-2006][@nonce-disrespecting-2016]. GCM is only as strong as its nonce discipline.


Order matters. MAC-then-encrypt and encrypt-and-MAC are fragile and produced Lucky Thirteen and the padding-oracle family [@lucky-thirteen-2013]. The proven-safe generic composition is Encrypt-then-MAC: authenticate the ciphertext and verify the tag *before* you decrypt [@bellare-namprempre-2000].

&lt;p&gt;Every one dissolves into the same sentence -- which is where this started, and where it ends.&lt;/p&gt;
&lt;h2&gt;Two Questions, Forty Years&lt;/h2&gt;
&lt;p&gt;Return to the opening. A ciphertext AES kept perfectly secret, rewritten in transit by an attacker who never read a byte of it, and accepted as authentic -- because the mode answered only the first of two questions. That was not an exotic failure. It was the ordinary shape of every break in this article.&lt;/p&gt;
&lt;p&gt;Run the catalog back through the lens and the pattern is total. Adobe [@troyhunt-adobe-2013], Vaudenay&apos;s padding oracle [@vaudenay-2002], BEAST [@cve-2011-3389], Lucky Thirteen [@lucky-thirteen-2013], POODLE [@cve-2014-3566], Sweet32 [@cve-2016-2183], Efail [@efail-2018], and GCM nonce reuse [@nonce-disrespecting-2016]: in every case, AES or DES did exactly what it promised, and the variable was always &lt;em&gt;which question the design forgot&lt;/em&gt; or &lt;em&gt;which IV/nonce contract it violated&lt;/em&gt;. Not one of these was a cipher break.&lt;/p&gt;
&lt;p&gt;Read that way, the 2024-2026 state of the art is a single move. The field stopped iterating confidentiality modes and standardized the &lt;em&gt;second&lt;/em&gt; answer. Authenticated encryption is the destination -- and its dominant AES instances, GCM and CCM, are literally these very modes plus a MAC, while ChaCha20-Poly1305 and Ascon supply a parallel lineage that is not [@nist-ir-8459][@nist-sp-800-232]. The frontier moved with it: nonce-misuse resistance and key commitment are the properties the deployed defaults still lack.&lt;/p&gt;
&lt;p&gt;The payoff of the field guide is the same as its premise. Master the five not as interchangeable dropdown options but as building blocks with exact contracts, and every break -- past or future -- becomes readable on sight. You do not need to memorize the next CVE. You need one test, and you already have it: &lt;em&gt;which question did this mode answer, and was its IV/nonce contract honored?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That lens outlives every mode, every cipher, and every standard revision. Which is why this is Part 5 of a field guide to protocol design, not a chapter on five diagrams.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;block-cipher-modes-ecb-to-ctr&quot; keyTerms={[
  { term: &quot;Block cipher&quot;, definition: &quot;A keyed, invertible permutation on one fixed-size block of bits (64 for DES, 128 for AES).&quot; },
  { term: &quot;Mode of operation&quot;, definition: &quot;The wrapper that lifts a one-block cipher to messages of arbitrary length.&quot; },
  { term: &quot;IND-CPA&quot;, definition: &quot;Indistinguishability under chosen-plaintext attack; it forces secure encryption to be randomized or stateful.&quot; },
  { term: &quot;Initialization Vector (IV)&quot;, definition: &quot;A per-message starting value; it must be unpredictable for CBC and CFB.&quot; },
  { term: &quot;Nonce&quot;, definition: &quot;A number used once per key; CTR and OFB need it unique, not unpredictable.&quot; },
  { term: &quot;Malleability&quot;, definition: &quot;An attacker can turn a ciphertext into a predictable change of the plaintext, with no key.&quot; },
  { term: &quot;Message Authentication Code (MAC)&quot;, definition: &quot;A keyed integrity tag that supplies the answer a confidentiality mode omits.&quot; },
  { term: &quot;AEAD&quot;, definition: &quot;Authenticated Encryption with Associated Data; confidentiality and integrity in one primitive.&quot; },
  { term: &quot;Birthday bound&quot;, definition: &quot;Collisions among n-bit values become likely near 2 to the n over 2; the block-size ceiling.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>block-cipher-modes</category><category>aes</category><category>authenticated-encryption</category><category>aead</category><category>cryptography</category><category>cbc</category><category>ctr</category><category>gcm</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>They Read Your Plaintext Without Breaking Your Cipher: A Field Guide to Padding Oracles</title><link>https://paragmali.com/blog/they-read-your-plaintext-without-breaking-your-cipher-a-fiel/</link><guid isPermaLink="true">https://paragmali.com/blog/they-read-your-plaintext-without-breaking-your-cipher-a-fiel/</guid><description>A padding oracle reads your plaintext without touching your key. Why CBC, Vaudenay, Lucky13, and POODLE are one bug -- and why Encrypt-then-MAC ends it.</description><pubDate>Wed, 08 Jul 2026 20:09:31 GMT</pubDate><content:encoded>
A padding oracle lets an attacker read your plaintext without ever touching your key -- and it is not a flaw in AES, in CBC, or even in PKCS#7. It is what you get whenever a receiver reveals *whether an attacker-chosen ciphertext decrypted to well-formed plaintext* before it has proven that ciphertext authentic. That one leaked bit (&quot;was the padding valid?&quot;), plus CBC&apos;s malleability, recovers plaintext one byte at a time -- about 128 guesses per byte -- as Serge Vaudenay showed in 2002 and Juliano Rizzo and Thai Duong weaponized against ASP.NET in 2010.&lt;p&gt;This field guide follows the &lt;em&gt;same&lt;/em&gt; bug leaking through progressively quieter channels: a loud error (Vaudenay), coarse timing (Canvel), statistical timing under unified errors (Lucky Thirteen), SSL 3.0&apos;s unchecked padding (POODLE), and the oracle re-created by Lucky Thirteen&apos;s own fix (CVE-2016-2107). Every point fix lost. The single structural cure is to invert the order: &lt;strong&gt;authenticate before you decrypt-and-unpad.&lt;/strong&gt; Encrypt-then-MAC proves it attains IND-CCA plus INT-CTXT; AEAD, mandated by TLS 1.3, ships it with no knob to misset. The article ends with ranked decision rules and a design-review checklist for 2026.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;1. The Break That Never Touched the Key&lt;/h2&gt;
&lt;p&gt;In September 2010, two researchers pointed a few thousand malformed requests at an ordinary ASP.NET application and walked away with its authentication tickets and its &lt;code&gt;web.config&lt;/code&gt; -- the site&apos;s master secrets -- without ever attacking its AES-256 encryption or going near the key [@rizzo_duong_woot2010]. It had done nothing more than return one error when a decrypted request had bad padding and a different error when the padding was fine but the data was not. That one-bit difference is a decryption machine: the attackers never broke the cipher, they turned the server&apos;s error handling into the decryption function.&lt;/p&gt;
&lt;p&gt;Sit with the paradox, because the rest of this article lives inside it. AES-256 was, and is, intact. Nobody factored anything, guessed a key, or exploited a weakness in the block cipher&apos;s rounds. The plaintext walked out the door one byte at a time purely because the server answered a question it should never have been willing to answer: &lt;em&gt;was this ciphertext, which I did not create, well-formed after I decrypted it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Juliano Rizzo and Thai Duong automated that question against &lt;code&gt;WebResource.axd&lt;/code&gt; and &lt;code&gt;ScriptResource.axd&lt;/code&gt; handlers and recovered Forms-authentication tickets and server files. The United States National Vulnerability Database catalogs it as CVE-2010-3332, the &quot;ASP.NET Padding Oracle Vulnerability,&quot; and Microsoft shipped an out-of-band patch to close it [@cve_2010_3332]. This was not a lab curiosity. It was, at the time, the largest deployed instance of a bug that had been sitting in plain sight for eight years.&lt;/p&gt;

A padding oracle is an attack class, not a cipher weakness. A receiver decrypts an attacker-chosen ciphertext, checks whether the recovered plaintext has valid padding, and reveals the verdict -- through an error message, a timing difference, or any observable behavior. That single accept/reject bit, repeated, becomes a plaintext-recovery oracle that never attacks the underlying cipher or key.
&lt;p&gt;The reframe is worth stating in the sharpest possible terms, because once you hold it you will see this bug everywhere.&lt;/p&gt;

The attacker never attacks the cipher. They turn the receiver&apos;s error handling into the decryption function -- &quot;decrypt, then validate&quot; becomes &quot;decrypt, then confess.&quot;
&lt;p&gt;This is Part 6 of a field guide for protocol designers. It assumes the malleability of CBC mode from Part 5 (the lever the attack pulls) and the &lt;a href=&quot;https://paragmali.com/blog/secure-against-whom-the-security-definitions-every-protocol-/&quot; rel=&quot;noopener&quot;&gt;chosen-ciphertext adversary&lt;/a&gt; from Part 1 (this &lt;em&gt;is&lt;/em&gt; that adversary, deployed and winning). By the end you will carry one diagnostic sentence and drop every named break in this article -- Vaudenay, Lucky Thirteen, POODLE, and tomorrow&apos;s application-layer oracle -- onto it on sight: &lt;em&gt;when a ciphertext you did not create arrives, what does the receiver reveal about it before it has proven the ciphertext authentic?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If AES was intact and the key was never touched, then the machine that recovered the plaintext was built entirely out of the server&apos;s own responses. That idea did not begin with CBC, or even with symmetric cryptography. To see the atom clearly, go back to the first time anyone realized that a receiver&apos;s verdict on validity is itself a decryption function.&lt;/p&gt;
&lt;h2&gt;2. A Validity Check Is a Decryption Oracle&lt;/h2&gt;
&lt;p&gt;The year is 1998, the place is Bell Labs, and Daniel Bleichenbacher is staring at an SSL server that is far too honest. When the server receives an RSA-encrypted message, it decrypts and checks whether the result has the structure that the PKCS #1 v1.5 standard demands. If the structure is wrong, it says so. Bleichenbacher realized that this single yes/no answer -- &lt;em&gt;does the decrypted message have valid PKCS #1 formatting?&lt;/em&gt; -- is enough to recover the plaintext.&lt;/p&gt;
&lt;p&gt;With roughly $2^{20}$ adaptively chosen queries, he could extract an RSA-protected session key without factoring the modulus and without ever learning the private key [@bleichenbacher1998]. The server&apos;s &quot;is this well-formed?&quot; answer &lt;em&gt;was&lt;/em&gt; the attacker&apos;s decryption function. This is the seed of everything that follows.&lt;/p&gt;
&lt;p&gt;It is also the moment to nail down a boundary that expert readers will check for. Bleichenbacher&apos;s attack is an &lt;strong&gt;RSA PKCS #1 v1.5&lt;/strong&gt; oracle -- a different primitive with different arithmetic. It is the conceptual ancestor of the CBC padding-oracle class &quot;in spirit,&quot; but it is never itself a CBC padding oracle [@bleichenbacher1998].Calling Bleichenbacher &quot;the first CBC padding oracle&quot; is a common and consequential error. His target is RSA public-key encryption; the CBC class is symmetric. The shared idea -- a structural validity verdict on attacker-chosen ciphertext leaks the plaintext -- is what makes him the ancestor, not the mechanism. The distinction matters because the family tree has two branches, and confusing them muddles the fix.&lt;/p&gt;

In an adaptive chosen-ciphertext attack, the adversary submits ciphertexts of its choosing and learns something from the receiver&apos;s reaction to each one. A scheme is IND-CCA2 secure only if those reactions leak nothing that helps distinguish or recover plaintext. A padding oracle is precisely a receiver whose reaction leaks -- so it is a live, deployed IND-CCA2 break, the security notion this series defines in Part 1.
&lt;p&gt;The whole subject lives inside that definition. If a receiver&apos;s response to a ciphertext it did not create tells the attacker anything, the game is already lost -- the only question is how expensive the win is.&lt;/p&gt;

Bleichenbacher&apos;s oracle never died; it changed clothes. **DROWN** (2016) revived it by using a server&apos;s SSLv2 support to attack modern TLS [@drown_attack2016]. **ROBOT** (2017 to 2018) found the same PKCS #1 v1.5 oracle live in load balancers and TLS stacks from major vendors, nearly two decades on [@robot_2018]. And the **Marvin Attack** (2023) showed the timing variant still breaks RSA implementations &quot;previously thought immune&quot; [@marvin_attack2023]. All three are RSA-side breaks -- a different primitive from the CBC story told here -- and they appear only as this signpost so nobody mistakes them for CBC oracles. The lesson each one re-teaches is the same: a validity verdict on attacker-chosen input is a decryption oracle, whatever the cipher.
&lt;p&gt;Four years after Bleichenbacher, Serge Vaudenay carried the idea across the aisle from public-key to symmetric cryptography. In &quot;Security Flaws Induced by CBC Padding,&quot; presented at EUROCRYPT 2002, he showed that a receiver which decrypts a CBC ciphertext and reveals whether the padding is valid becomes a plaintext-recovery oracle against SSL, IPSEC, and WTLS [@vaudenay2002]. This is the founding result of the class -- the moment &quot;confidentiality without integrity&quot; was shown to be, in the general case, a decryption oracle waiting to be asked.&lt;/p&gt;
&lt;p&gt;The object it manipulates had arrived on schedule: PKCS #7 padding, the append-&lt;code&gt;n&lt;/code&gt;-bytes-each-equal-to-&lt;code&gt;n&lt;/code&gt; scheme, was standardized as RFC 2315 in the same era, so the manipulable surface and the attack template appeared together [@rfc2315]. Vaudenay&apos;s procedure is documented in cryptography&apos;s standard texts as the canonical illustration of chosen-ciphertext insecurity [@katz_lindell_imc].&lt;/p&gt;

timeline
    title Padding oracles, 1998 to 2022
    1998 : Bleichenbacher RSA PKCS number 1 oracle
    2000 : Bellare-Namprempre composition theorem
    2002 : Vaudenay CBC padding oracle
    2003 : Canvel timing oracle vs TLS
    2010 : ASP.NET break by Rizzo and Duong
    2013 : Lucky Thirteen statistical timing
    2014 : POODLE and RFC 7366 Encrypt-then-MAC
    2016 : CVE-2016-2107, the fix re-creates the oracle
    2018 : TLS 1.3 removes CBC, mandates AEAD
    2022 : BCP 195 recommends against CBC
&lt;p&gt;Vaudenay&apos;s real contribution was noticing that CBC makes the symmetric version &lt;em&gt;cleaner&lt;/em&gt; than Bleichenbacher&apos;s RSA original: flip a byte, watch the verdict, recover a byte. To believe that -- and to earn the right to use it on every later break -- you have to see the arithmetic. It is simpler than it sounds, and once you see it you cannot un-see it in any decrypt-then-check system you review.&lt;/p&gt;
&lt;h2&gt;3. The Atom: Vaudenay&apos;s Oracle, Worked Byte by Byte&lt;/h2&gt;
&lt;p&gt;Everything in this article is one move, performed once here and then reused by every named break with only the &lt;em&gt;channel&lt;/em&gt; changed. Derive it in full and the rest of the piece can move fast. There are three steps: understand the padding, understand the lever, then watch the recovery.&lt;/p&gt;
&lt;h3&gt;Step one: three padding formats, disambiguated once&lt;/h3&gt;
&lt;p&gt;Block ciphers operate on whole blocks, so a message that does not fill the last block must be padded, and the padding must be self-describing so the receiver can strip it. PKCS #7 is the canonical scheme.&lt;/p&gt;

To pad a message to a block boundary, append `n` bytes, each equal to the value `n`. Need three bytes of padding? Append `03 03 03`. Need one? Append `01`. If the message is already block-aligned, append a *full extra block* of padding (for a 16-byte AES block, sixteen bytes of `10`). To unpad, read the final byte `n`, verify that the last `n` bytes all equal `n`, and strip them. Standardized in RFC 2315 [@rfc2315].
&lt;p&gt;Here is the trap that catches expert readers, so disambiguate it now and never again: not every named attack operates on literal PKCS #7 bytes. Three formats matter, and mitigations for one do not automatically cover another.&lt;/p&gt;
&lt;p&gt;PKCS #7 (RFC 2315) requires every pad byte to equal the pad length [@rfc2315]. TLS 1.0 through 1.2 use a PKCS #7-&lt;em&gt;like&lt;/em&gt; scheme where every pad byte equals &lt;code&gt;length - 1&lt;/code&gt;, and -- this detail will return with Lucky Thirteen -- the record is MAC&apos;d, &lt;em&gt;then&lt;/em&gt; padded, &lt;em&gt;then&lt;/em&gt; encrypted [@rfc5246]. SSL 3.0 is the dangerous outlier: its pad bytes are &lt;em&gt;arbitrary&lt;/em&gt;, and only the final length byte is constrained, so there is effectively no padding content to check at all [@rfc6101].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Padding format&lt;/th&gt;
&lt;th&gt;Pad-byte rule&lt;/th&gt;
&lt;th&gt;What the receiver checks&lt;/th&gt;
&lt;th&gt;Break that targets it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;PKCS #7 (RFC 2315)&lt;/td&gt;
&lt;td&gt;Append &lt;code&gt;n&lt;/code&gt; bytes each equal to &lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Length byte and every pad byte&lt;/td&gt;
&lt;td&gt;Vaudenay&apos;s canonical oracle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS 1.0 to 1.2 (RFC 5246)&lt;/td&gt;
&lt;td&gt;Every pad byte equals &lt;code&gt;length - 1&lt;/code&gt;; MAC then pad then encrypt&lt;/td&gt;
&lt;td&gt;Length and pad bytes, after decrypt&lt;/td&gt;
&lt;td&gt;Lucky Thirteen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSL 3.0 (RFC 6101)&lt;/td&gt;
&lt;td&gt;Pad bytes arbitrary; only the final length byte constrained&lt;/td&gt;
&lt;td&gt;Length byte only; pad bytes unchecked&lt;/td&gt;
&lt;td&gt;POODLE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The DES-era ancestor is PKCS #5, re-published as RFC 8018, which is the same scheme fixed at an 8-byte block; PKCS #7 generalizes it to any block size up to 255 [@rfc8018]. The two names describe one idea, which is why you see both in old code.&lt;/p&gt;
&lt;p&gt;That single table is why &quot;just make the padding check uniform&quot; was never a complete fix -- it says nothing about SSL 3.0, where there is no pad content to make uniform.&lt;/p&gt;
&lt;h3&gt;Step two: CBC malleability, the lever&lt;/h3&gt;

In CBC decryption, each plaintext block is $P_i = D_k(C_i) \oplus C_{i-1}$: decrypt the current ciphertext block with the block cipher, then XOR the previous ciphertext block. Because that XOR is the last step, an attacker who flips a bit in $C_{i-1}$ deterministically flips the *same* bit in $P_i$ -- steering the plaintext without any knowledge of the key. Part 5 derives this in full; here it is the lever the oracle pulls.

flowchart TD
    Ci[&quot;Target ciphertext block Ct&quot;] --&amp;gt; Dk[&quot;Block cipher decryption Dk&quot;]
    Dk --&amp;gt; Inter[&quot;Intermediate block, equals Dk of Ct&quot;]
    Cprev[&quot;Previous ciphertext block, attacker controls it&quot;] --&amp;gt; XORnode((&quot;XOR&quot;))
    Inter --&amp;gt; XORnode
    XORnode --&amp;gt; Pt[&quot;Recovered plaintext block Pt&quot;]
    Attacker[&quot;Attacker flips byte j of the previous block&quot;] -.-&amp;gt; Cprev
    Attacker -.-&amp;gt; Result[&quot;Byte j of Pt flips by the same amount, no key needed&quot;]
&lt;p&gt;Hold the two pieces together: the receiver will tell you whether a decrypted block has valid padding, and you can steer any byte of that decrypted block by editing the block in front of it. Those two facts are a decryption oracle.&lt;/p&gt;
&lt;h3&gt;Step three: the recovery, last byte first&lt;/h3&gt;
&lt;p&gt;Take a target ciphertext block $C_t$ whose plaintext you want. Prepend a block $C&apos;$ that you fully control, and ask the receiver to decrypt the pair. The receiver computes an intermediate block $I = D_k(C_t)$ and returns the plaintext $P = I \oplus C&apos;$, then checks its padding. You do not know $I$, but you can search for it one byte at a time.&lt;/p&gt;
&lt;p&gt;Fix your attention on the last byte. Vary $C&apos;$&apos;s last byte over all 256 possible values and watch the verdict. For exactly one value, the decrypted last byte becomes &lt;code&gt;0x01&lt;/code&gt;, which is valid single-byte padding, and the receiver accepts. At that instant you know that $I[\text{last}] \oplus C&apos;[\text{last}] = \texttt{0x01}$, so the intermediate byte is $I[\text{last}] = C&apos;[\text{last}] \oplus \texttt{0x01}$. XOR that against the &lt;em&gt;real&lt;/em&gt; previous ciphertext byte and you have recovered a true plaintext byte -- and AES was never touched.&lt;/p&gt;
&lt;p&gt;One honest wrinkle hides inside &quot;about 128 guesses.&quot; A guess can occasionally produce valid &lt;em&gt;longer&lt;/em&gt; padding by luck -- for instance if the plaintext already ended in &lt;code&gt;0x02&lt;/code&gt;, a crafted byte could yield &lt;code&gt;02 02&lt;/code&gt;. So the careful attacker perturbs the second-to-last byte to confirm the intended &lt;code&gt;01&lt;/code&gt; interpretation. That rare double-check is why the average is ~128 rather than a clean 128, and why worst-case is 256.&lt;/p&gt;
&lt;p&gt;To peel the next byte, target two-byte padding: set the known last byte to decrypt to &lt;code&gt;0x02&lt;/code&gt; (you can, because you now know its intermediate), and brute-force the second-to-last byte until the receiver sees &lt;code&gt;02 02&lt;/code&gt;. March inward -- &lt;code&gt;03 03 03&lt;/code&gt;, then &lt;code&gt;04 04 04 04&lt;/code&gt; -- and a full block falls. The cost is about &lt;strong&gt;128 guesses per byte on average and 256 in the worst case&lt;/strong&gt; [@vaudenay2002].&lt;/p&gt;

sequenceDiagram
    participant A as Attacker
    participant O as Oracle receiver
    Note over A,O: Goal, learn the last byte of target block Ct
    A-&amp;gt;&amp;gt;O: Send chosen block Cprime, then Ct
    O-&amp;gt;&amp;gt;O: Decrypt, inspect last-byte padding
    O--&amp;gt;&amp;gt;A: invalid padding
    Note over A: Increment last byte of Cprime, retry
    A-&amp;gt;&amp;gt;O: The value making the last plaintext byte 0x01
    O-&amp;gt;&amp;gt;O: Padding parses as one valid byte
    O--&amp;gt;&amp;gt;A: valid padding
    Note over A,O: Intermediate byte is that guess XOR 0x01
    Note over A: True plaintext byte is intermediate XOR real previous byte
&lt;p&gt;Run the atom yourself. The simulation below models the oracle over a fixed intermediate block -- no real cipher, so you can watch the one-in-256 accept that leaks a byte.&lt;/p&gt;
&lt;p&gt;{`
// A toy padding oracle over a fixed 16-byte &quot;intermediate&quot; block.
// No real crypto: we model I = D_k(C_t) as a known array so you can watch
// the 1-in-256 accept that leaks one plaintext byte.
const BLOCK = 16;&lt;/p&gt;
&lt;p&gt;// Pretend these are the secret intermediate bytes I = D_k(C_t).
const intermediate = [0x8a,0x2f,0x11,0x77,0x4c,0x93,0xe0,0x05,
                      0xbb,0x6d,0x19,0xa4,0x3c,0xf8,0x52,0x7e];
// The real previous-ciphertext block (known to the attacker).
const realPrev = [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
                  0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10];&lt;/p&gt;
&lt;p&gt;// Oracle: is the last decrypted byte valid 0x01 padding?
function oracle(cprime) {
  const lastPlain = intermediate[BLOCK-1] ^ cprime[BLOCK-1];
  return lastPlain === 0x01;   // the single leaked bit
}&lt;/p&gt;
&lt;p&gt;// Attack: brute-force the last byte of a controlled block.
let guesses = 0;
const cprime = new Array(BLOCK).fill(0);
for (let g = 0; g &amp;lt; 256; g++) {
  guesses++;
  cprime[BLOCK-1] = g;
  if (oracle(cprime)) {
    const intByte = g ^ 0x01;                    // I[last] = guess XOR 0x01
    const plainByte = intByte ^ realPrev[BLOCK-1];
    console.log(&quot;Accepted after &quot; + guesses + &quot; guesses&quot;);
    console.log(&quot;Recovered intermediate byte: 0x&quot; + intByte.toString(16));
    console.log(&quot;Recovered plaintext byte:    0x&quot; + plainByte.toString(16));
    break;
  }
}
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; One reliable accept/reject bit on attacker-chosen ciphertext, plus CBC&apos;s malleability, is a complete decryption function -- about 128 guesses per byte, and the key is never touched. Every named break in the rest of this article is that same atom, with only the channel that carries the bit changed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is Aha number one, and it dismantles the mental model most engineers start with. AES-256&apos;s strength was never the variable. The variable was what the receiver was willing to say about a ciphertext it had not authenticated. Before moving on, one point of vocabulary, because it changes how you diagnose the bug.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A padding oracle is an &lt;em&gt;attack class&lt;/em&gt; -- a side channel against a &lt;em&gt;construction&lt;/em&gt; (CBC-mode encryption composed with a MAC), not a weakness in a primitive. The block cipher (AES) and the MAC (HMAC) are the primitives, and they are doing exactly what they promise. The oracle lives in how they are composed and in what the receiver reveals. Say &quot;attack class&quot; and &quot;construction,&quot; never &quot;the padding-oracle primitive.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The atom needs exactly one thing from the receiver: a distinguishable answer to &quot;was the padding valid?&quot; Vaudenay read that answer off a loud error message. The next fifteen years are the story of the field muffling that answer, one channel at a time -- and the same bit escaping through the next-quietest one every single time.&lt;/p&gt;
&lt;h2&gt;4. One Distinguisher, Four Quieter Channels&lt;/h2&gt;
&lt;p&gt;The atom never changes. What changes is &lt;em&gt;how the accept/reject bit is observed&lt;/em&gt; -- and each time the field silences one channel, the bit re-emerges through a quieter one. Here is the entire failure catalog as one descending staircase, with POODLE branching off to the side.&lt;/p&gt;

flowchart TD
    A[&quot;Loud padding-error message (Vaudenay, ASP.NET)&quot;] --&amp;gt;|&quot;Unify the alert&quot;| B[&quot;Coarse timing gap (Canvel)&quot;]
    B --&amp;gt;|&quot;Compute the MAC anyway&quot;| C[&quot;Statistical timing (Lucky Thirteen)&quot;]
    C --&amp;gt;|&quot;Constant-time AES-NI fast path&quot;| D[&quot;Fix re-creates the oracle (CVE-2016-2107)&quot;]
    D --&amp;gt;|&quot;Verify authenticity first&quot;| F[&quot;Encrypt-then-MAC and AEAD, no verdict to leak&quot;]
    P[&quot;Unchecked padding by spec (POODLE, SSL 3.0)&quot;] --&amp;gt;|&quot;Retire SSL 3.0 and CBC&quot;| F
&lt;p&gt;&lt;strong&gt;Channel one -- the loud error message (Vaudenay 2002, ASP.NET 2010).&lt;/strong&gt; The first receivers simply returned a distinct &quot;padding error,&quot; trivially observable. Vaudenay read it straight off the response, and eight years later Rizzo and Duong read it off differing HTTP responses from ASP.NET applications, recovering authentication tickets and &lt;code&gt;web.config&lt;/code&gt; at scale [@rizzo_duong_woot2010] [@cve_2010_3332]. The obvious countermeasure: return one indistinguishable error for both padding failures and data failures. That closes the loudest channel and opens the next.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Channel two -- coarse timing (Canvel et al. 2003).&lt;/strong&gt; Once OpenSSL returned the &lt;em&gt;same&lt;/em&gt; &lt;code&gt;bad_record_mac&lt;/code&gt; alert for padding and MAC failures, Brice Canvel, Alain Hiltgen, Serge Vaudenay, and Martin Vuagnoux showed the verdict still leaked through &lt;em&gt;when&lt;/em&gt; the alert arrived: a receiver that accepted the padding went on to compute the MAC, while one that rejected padding could bail early, and the resulting millisecond gap reconstituted the oracle [@canvel2003]. They intercepted a password over a live OpenSSL TLS channel. This is the first concrete demonstration of the pattern that organizes the whole subject. The standards response, TLS 1.1 (RFC 4346), mandated uniform alert handling and explicit per-record initialization vectors [@rfc4346]. The countermeasure: make the decryption path constant-time -- compute the MAC even on padding failure so both paths take equal time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Channel three -- statistical timing, Lucky Thirteen (AlFardan and Paterson, 2013).&lt;/strong&gt; This is the break that proved constant-time is &lt;em&gt;the&lt;/em&gt; hard problem, and it is worth binding tightly to the thesis, because it is not merely &quot;a timing attack.&quot; TLS uses MAC-then-encrypt with a specific receiver order: decrypt, &lt;em&gt;strip the padding&lt;/em&gt;, then run HMAC over what remains. The trouble is that &quot;what remains&quot; has a length that depends on how many bytes the receiver treated as padding -- and HMAC&apos;s running time depends on that length, because the hash compression function runs one extra time at certain length thresholds. So the attacker&apos;s &lt;em&gt;guess about the padding&lt;/em&gt; changes the MAC-computation time by a few tens of CPU cycles [@lucky13_2013].&lt;/p&gt;

A comparison (or, more broadly, a code path) is constant-time when its running time does not depend on secret data or on how far into the data a difference occurs. A tag check that returns early on the first mismatched byte leaks *where* the mismatch is; a constant-time check XORs all bytes and inspects the accumulated difference once. Lucky Thirteen forced constant-time unpadding-and-MAC on the whole industry, and CVE-2016-2107 shows how easily a hand-written fast path reintroduces the oracle -- there, through a missing length check that produced a distinguishable alert rather than a timing gap.
&lt;p&gt;Nadhem AlFardan and Kenneth Paterson amplified that sub-microsecond difference statistically across the network, recovering a full plaintext block in about $2^{23}$ TLS sessions, dropping to roughly $2^{13}$ sessions per byte with favorable positioning, across OpenSSL, GnuTLS, PolarSSL, and more (CVE-2013-0169) [@lucky13_2013] [@cve_2013_0169]. Bind it to the ordering: MAC-then-encrypt &lt;em&gt;forces&lt;/em&gt; a length-dependent MAC, so the timing leak is a property of the order of operations, not a stray implementation slip.The name &quot;Lucky Thirteen&quot; comes from the 13 bytes TLS feeds into the HMAC before the record body: a 5-byte TLS record header plus an 8-byte sequence number. Their alignment against the 64-byte hash-compression boundary is exactly what opens the timing gap. A number that sounds whimsical is really a byte-counting accident. The next countermeasure was obvious and genuinely hard: make the MAC and the unpadding constant-time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Channel four -- unchecked structure, POODLE (Moller, Duong, and Kotowicz 2014).&lt;/strong&gt; Here the staircase forks into a parallel branch. SSL 3.0&apos;s pad bytes are &lt;em&gt;arbitrary by specification&lt;/em&gt; -- only the final length byte is constrained -- so there is no padding check to harden, no message to unify, no timing to flatten [@rfc6101]. An attacker who maneuvers a target byte into the last position of a block learns it from &lt;em&gt;MAC pass or fail alone&lt;/em&gt;, needing neither an error message nor a timing measurement, at an expected cost of 256 SSL 3.0 requests per byte [@poodle_writeup] [@cve_2014_3566]. The name expands to Padding Oracle On Downgraded Legacy Encryption, and this is where a persistent misconception must be corrected.POODLE&apos;s downgrade is the &lt;em&gt;enabler&lt;/em&gt;, not the bug. The downgrade only forces a modern client back onto vulnerable SSL 3.0; the vulnerability is the unchecked pad. The proof is TLS-POODLE (CVE-2014-8730), which hit TLS stacks that copied SSL 3.0&apos;s lax padding check and works with &lt;em&gt;no downgrade at all&lt;/em&gt; [@cve_2014_8730]. Frame POODLE as a padding oracle first, a downgrade second. Google&apos;s write-up and the accompanying announcement documented the mechanism and effort in full [@poodle_writeup] [@google_poodle_blog]. Because there is no check to make uniform, the only fix is to remove SSL 3.0, and CBC, from the wire entirely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Channel five -- the oracle the fix re-created (CVE-2016-2107, 2016).&lt;/strong&gt; This is the single clearest proof of the thesis. OpenSSL&apos;s AES-NI assembly fast path, written to make the Lucky Thirteen countermeasure constant-time, mishandled a length check -- and re-opened a padding oracle. It was found with the TLS-Attacker fuzzing methodology [@somorovsky_fuzzing2016], and the National Vulnerability Database records the cause in words worth quoting exactly.&lt;/p&gt;

This vulnerability [CVE-2016-2107] exists because of an incorrect fix for CVE-2013-0169.
&lt;p&gt;The constant-time patch for Lucky Thirteen re-created the very oracle it was written to close, and OpenSSL shipped the repair in 1.0.2h and 1.0.1t [@cve_2016_2107] [@openssl_secadv_20160503]. It did not travel alone. Amazon&apos;s s2n library added a Lucky Thirteen countermeasure that still leaked, revived as Lucky Microseconds by Martin Albrecht and Kenneth Paterson -- and the randomized delays s2n had added as masking were part of the problem [@lucky_microseconds2016].&lt;/p&gt;
&lt;p&gt;Then, in 2019, Craig Young&apos;s Zombie POODLE and GOLDENDOODLE and a large Internet scan by Robert Merget and colleagues found CBC padding oracles still live in 1.83% of the Alexa Top Million, distinguishable by the &lt;em&gt;content&lt;/em&gt; of server responses with no precise timing required at all [@merget2019] [@qualys_zombie_poodle2019].&lt;/p&gt;
&lt;p&gt;Zombie POODLE is an invalid-padding, valid-MAC oracle; GOLDENDOODLE is the mirror image, a valid-padding, invalid-MAC oracle. Different verdicts, same atom.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Incident&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Leak channel&lt;/th&gt;
&lt;th&gt;Root cause&lt;/th&gt;
&lt;th&gt;Primary source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Vaudenay&lt;/td&gt;
&lt;td&gt;2002&lt;/td&gt;
&lt;td&gt;Distinct padding error&lt;/td&gt;
&lt;td&gt;MtE-CBC observable branch&lt;/td&gt;
&lt;td&gt;[@vaudenay2002]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canvel et al.&lt;/td&gt;
&lt;td&gt;2003&lt;/td&gt;
&lt;td&gt;Coarse timing&lt;/td&gt;
&lt;td&gt;MAC computed vs skipped&lt;/td&gt;
&lt;td&gt;[@canvel2003]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASP.NET (Rizzo, Duong)&lt;/td&gt;
&lt;td&gt;2010&lt;/td&gt;
&lt;td&gt;Distinct HTTP error&lt;/td&gt;
&lt;td&gt;Padding vs data error revealed&lt;/td&gt;
&lt;td&gt;[@rizzo_duong_woot2010] [@cve_2010_3332]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lucky Thirteen&lt;/td&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;Statistical timing&lt;/td&gt;
&lt;td&gt;Strip-then-MAC length dependence&lt;/td&gt;
&lt;td&gt;[@lucky13_2013] [@cve_2013_0169]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POODLE&lt;/td&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;MAC pass or fail on shifted byte&lt;/td&gt;
&lt;td&gt;SSL 3.0 unchecked padding&lt;/td&gt;
&lt;td&gt;[@poodle_writeup] [@cve_2014_3566]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS-POODLE&lt;/td&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;Same, no downgrade&lt;/td&gt;
&lt;td&gt;TLS stacks copying the lax check&lt;/td&gt;
&lt;td&gt;[@cve_2014_8730]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2016-2107&lt;/td&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;Distinguishable alert (bad_record_mac vs record_overflow)&lt;/td&gt;
&lt;td&gt;Constant-time fix slipped a length check&lt;/td&gt;
&lt;td&gt;[@cve_2016_2107]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zombie POODLE, GOLDENDOODLE&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;Content differences in responses&lt;/td&gt;
&lt;td&gt;Deployed CBC-HMAC long tail, 1.83%&lt;/td&gt;
&lt;td&gt;[@merget2019] [@qualys_zombie_poodle2019]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Never return a distinct &quot;bad padding&quot; error, and never let padding validity change a branch or the timing of the response. Any distinguishable decryption outcome on attacker-chosen ciphertext -- an error string, a millisecond, a TCP reset, a difference in response content -- is a padding oracle. The channel does not matter; the observability does.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One clarification sharpens the definition by contrast. BEAST (2011) is often filed next to these breaks, but it is &lt;em&gt;not&lt;/em&gt; a padding oracle: it is a &lt;a href=&quot;https://paragmali.com/blog/predictable-or-repeated-the-only-two-ways-cryptographic-rand/&quot; rel=&quot;noopener&quot;&gt;predictable-initialization-vector&lt;/a&gt;, chosen-plaintext attack on CBC [@beast_2011], and it belongs to the IV story of Part 2 and Part 5, not here.The tell is the direction of information flow. A padding oracle recovers &lt;em&gt;unknown&lt;/em&gt; plaintext from the receiver&apos;s verdict on the attacker&apos;s ciphertext. BEAST confirms &lt;em&gt;guessed&lt;/em&gt; plaintext by exploiting a predictable IV. Different precondition, different fix -- naming it here only sharpens what a padding oracle is.&lt;/p&gt;
&lt;p&gt;Five generations, five channels, one bit. Every fix silenced the loudest remaining leak, and every fix was beaten by the next-quietest -- including a fix that became its own oracle. Whack-a-mole is not a strategy; it is a symptom. And the symptom points at a diagnosis the field had actually proved correct two years before Vaudenay&apos;s attack, and simply had not deployed.&lt;/p&gt;
&lt;h2&gt;5. The Bug Is the Order, Not the Padding&lt;/h2&gt;
&lt;p&gt;Stop looking at the padding. A padding oracle is not a padding bug; it is the consequence of &lt;em&gt;checking padding on data you have not authenticated&lt;/em&gt;. Change what you check first, and the oracle has nothing to answer. To see why, you need the piece the attack has been quietly relying on: the MAC, and the three ways to combine it with encryption.&lt;/p&gt;

A MAC is a keyed tag that proves a message is authentic and unmodified: only a holder of the secret key can produce a tag that verifies. HMAC is the deployed instance. A valid MAC on a ciphertext means the ciphertext is genuine -- it came from someone with the key, and nothing tampered with it. Part 3 covers HMAC&apos;s structure; here the point is simply *when* you check it.
&lt;p&gt;In 2000, Mihir Bellare and Chanathip Namprempre formalized the three &quot;generic composition&quot; ways to bolt a MAC onto an encryption scheme and proved exactly what each one buys [@bellare_namprempre2000]. Each maps cleanly onto a real protocol.&lt;/p&gt;

Compute the MAC over the *plaintext*, then encrypt the plaintext, MAC, and padding together. On receipt the order is forced: decrypt, strip padding, *then* verify the MAC. Because the receiver must decrypt and unpad before it can check authenticity, the padding verdict is observable by construction. This is SSL and TLS&apos;s original choice -- and the reason SSL/TLS, and only SSL/TLS, became a fifteen-year catalog of padding oracles.

Encrypt the plaintext, then compute the MAC over the *ciphertext* (and the IV), and transmit ciphertext plus tag. On receipt, verify the tag *first*; decrypt only if it passes. A ciphertext the attacker altered fails the MAC and is discarded before any padding logic runs -- so there is no padding verdict to leak, through any channel. This is IPsec ESP&apos;s design and the shape RFC 7366 retrofits onto TLS.
&lt;p&gt;The third sibling, encrypt-and-MAC, tags the plaintext and sends the tag alongside the ciphertext; SSH chose it. It still forces decryption before verification, and because the tag is over the plaintext it can leak plaintext equality, so it is no cure [@bellare_kohno_namprempre_ssh2002].&lt;/p&gt;

flowchart TD
    subgraph MtE[&quot;MAC-then-encrypt (SSL and TLS)&quot;]
        M1[&quot;Decrypt&quot;] --&amp;gt; M2[&quot;Strip padding&quot;] --&amp;gt; M3[&quot;Verify MAC&quot;]
    end
    subgraph EnM[&quot;Encrypt-and-MAC (SSH)&quot;]
        E1[&quot;Decrypt&quot;] --&amp;gt; E2[&quot;Verify MAC over plaintext&quot;]
    end
    subgraph EtM[&quot;Encrypt-then-MAC (IPsec ESP)&quot;]
        T1[&quot;Verify MAC over IV and ciphertext&quot;] --&amp;gt; T2[&quot;Decrypt&quot;] --&amp;gt; T3[&quot;Strip padding&quot;]
    end
&lt;p&gt;Look at where the MAC check sits. In the first two, unauthenticated ciphertext reaches the decrypt-and-parse machinery &lt;em&gt;before&lt;/em&gt; anyone has proven it genuine. In the third, a forged ciphertext dies at the door.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Composition&lt;/th&gt;
&lt;th&gt;MAC covers&lt;/th&gt;
&lt;th&gt;Receiver order&lt;/th&gt;
&lt;th&gt;IND-CCA (generic)&lt;/th&gt;
&lt;th&gt;INT-CTXT (generic)&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MAC-then-encrypt&lt;/td&gt;
&lt;td&gt;Plaintext&lt;/td&gt;
&lt;td&gt;Decrypt, unpad, verify&lt;/td&gt;
&lt;td&gt;Not guaranteed&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SSL and TLS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encrypt-and-MAC&lt;/td&gt;
&lt;td&gt;Plaintext&lt;/td&gt;
&lt;td&gt;Decrypt, verify&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encrypt-then-MAC&lt;/td&gt;
&lt;td&gt;Ciphertext and IV&lt;/td&gt;
&lt;td&gt;Verify, decrypt, unpad&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;IPsec ESP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Now the theorem, stated precisely. Encrypt-then-MAC, composed from an IND-CPA encryption scheme and a strongly unforgeable MAC (SUF-CMA), generically attains both IND-CCA and integrity of ciphertexts -- the strongest guarantees of the three -- while MAC-then-encrypt and encrypt-and-MAC do not generically reach integrity of ciphertexts [@bellare_namprempre2000]. Strong unforgeability is the load-bearing word: with only ordinary unforgeability, a second valid tag on the same ciphertext is a fresh accepted ciphertext, and the guarantee weakens to integrity of &lt;em&gt;plaintexts&lt;/em&gt;. In practice the qualifier is free, because HMAC is strongly unforgeable, so the deployed guarantee is exactly as stated. That is the whole game: a construction with integrity of ciphertexts rejects any forged ciphertext &lt;em&gt;before&lt;/em&gt; decryption, so a padding oracle cannot form.&lt;/p&gt;
&lt;p&gt;One honest caveat, because the sloppy version of this claim is wrong. Hugo Krawczyk proved in 2001 that MAC-then-encrypt &lt;em&gt;is&lt;/em&gt; secure when the encryption is CBC or counter mode, under stated conditions [@krawczyk2001]. So MtE is not &quot;always broken.&quot;Krawczyk&apos;s result is conditional: MtE with CBC or CTR is provably secure &lt;em&gt;in the model&lt;/em&gt;, which means Canvel, Lucky Thirteen, and POODLE are implementation, side-channel, and underspecified-padding failures -- not refutations of a theorem. The precise statement guards against the overreach &quot;MtE is broken.&quot; What is true is subtler and more useful: MtE is conditionally provable and practically fragile, because it leaves unauthenticated ciphertext reaching the parser, and holding the model&apos;s assumptions in compiled code is the hard part [@krawczyk2001]. The practitioner&apos;s takeaway is not &quot;the theorem was wrong&quot; but &quot;the theorem&apos;s assumptions are unreasonably hard to preserve in real code -- so change the order and stop needing them.&quot; The practitioner literature has said as much for years [@ferguson_schneier_kohno_ce].&lt;/p&gt;
&lt;p&gt;Watch the difference on a single tampered ciphertext. The MtE receiver leaks a distinguishable outcome; the EtM receiver returns one indistinguishable failure before it parses anything.&lt;/p&gt;
&lt;p&gt;{`
// Two toy receivers over the SAME tampered ciphertext.
// No real crypto: &quot;decrypt&quot; and &quot;macOk&quot; are stand-ins so you can see
// what each receiver reveals.
function decrypt(ct)  { return { paddingValid: false }; } // tampering broke the pad
function macOk(ct)    { return ct.tag === &quot;authentic&quot;; }  // forged tag fails&lt;/p&gt;
&lt;p&gt;const tampered = { tag: &quot;forged&quot; };&lt;/p&gt;
&lt;p&gt;// MAC-then-encrypt: decrypt and check padding BEFORE the MAC.
function mteReceive(ct) {
  const p = decrypt(ct);
  if (!p.paddingValid) return &quot;PADDING_ERROR&quot;;  // leaks the padding verdict
  if (!macOk(ct))      return &quot;MAC_ERROR&quot;;
  return &quot;OK&quot;;
}&lt;/p&gt;
&lt;p&gt;// Encrypt-then-MAC: verify the MAC FIRST; never touch padding on forgeries.
function etmReceive(ct) {
  if (!macOk(ct)) return &quot;FAIL&quot;;                // one indistinguishable outcome
  const p = decrypt(ct);
  if (!p.paddingValid) return &quot;FAIL&quot;;
  return &quot;OK&quot;;
}&lt;/p&gt;
&lt;p&gt;console.log(&quot;MtE says:&quot;, mteReceive(tampered)); // PADDING_ERROR (distinguishable)
console.log(&quot;EtM says:&quot;, etmReceive(tampered)); // FAIL (nothing to learn)
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The bug is the &lt;em&gt;order&lt;/em&gt;, not the padding. Silencing channels is whack-a-mole; checking authenticity &lt;em&gt;first&lt;/em&gt; -- Encrypt-then-MAC, and its successor AEAD -- removes the precondition that unauthenticated ciphertext ever reaches a padding check, so the oracle has nothing left to answer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is Aha number two, and it reorganizes the entire catalog. Every generation before Encrypt-then-MAC silenced a channel while leaving the precondition intact; the last two remove the precondition itself.&lt;/p&gt;

flowchart TD
    G1[&quot;Gen 1, distinct padding error&quot;] --&amp;gt; G2[&quot;Gen 2, unified alert&quot;]
    G2 --&amp;gt; G3[&quot;Gen 3, constant-time MtE&quot;]
    G3 --&amp;gt; G4[&quot;Gen 4, Encrypt-then-MAC&quot;]
    G4 --&amp;gt; G5[&quot;Gen 5, AEAD&quot;]
    G1 -.-&amp;gt; S[&quot;Silenced a channel, precondition intact&quot;]
    G2 -.-&amp;gt; S
    G3 -.-&amp;gt; S
    G4 -.-&amp;gt; R[&quot;Removed the precondition, authenticity first&quot;]
    G5 -.-&amp;gt; R

The three compositions were not tried in sequence; they were chosen in *parallel* by different protocols and coexisted for years. MAC-then-encrypt went into SSL and TLS, encrypt-and-MAC into SSH, Encrypt-then-MAC into IPsec ESP [@bellare_namprempre2000]. Only the MtE branch became the fifteen-year catalog. IPsec&apos;s Encrypt-then-MAC branch was structurally immune from the start, which is the quiet punchline of the whole story: the fix TLS reached for in 2014 was, in effect, &quot;become IPsec&quot; -- the negotiated `encrypt_then_mac` extension of RFC 7366 [@rfc7366].
&lt;p&gt;AEAD (RFC 5116) is Encrypt-then-MAC&apos;s standardized successor: one primitive, authenticity intrinsic, no composition knob to misset [@rfc5116]. The theorem was published in 2000. Vaudenay&apos;s attack landed in 2002. And the fix did not reach the deployed TLS base until 2014 to 2018. The rest of this article is what &quot;check authenticity first&quot; looks like when it finally shipped at Internet scale -- and why, even now, the class is not entirely dead.&lt;/p&gt;
&lt;h2&gt;6. The State of the Art: Closed by Construction&lt;/h2&gt;
&lt;p&gt;The modern answer is boring, and that is exactly the point. Use a primitive where a padding oracle &lt;em&gt;cannot exist&lt;/em&gt;, because authenticity is checked first and there is no block padding at all.&lt;/p&gt;

An AEAD primitive takes a key, a nonce, a plaintext, and optional associated data, and produces a ciphertext with an integral authentication tag. Decryption verifies the tag as part of the operation and returns *nothing* -- a single indistinguishable failure -- if it does not match. There is no separate MAC to order, and for the stream-based AEADs in wide use there is no block padding to be oracular. Standardized as an interface in RFC 5116 [@rfc5116].
&lt;p&gt;Two AEADs carry nearly all modern traffic. &lt;strong&gt;AES-GCM&lt;/strong&gt; is the default where AES hardware exists: it is AES in counter mode for encryption, plus a GHASH tag over the ciphertext and associated data, verified before any plaintext is released. &lt;strong&gt;ChaCha20-Poly1305&lt;/strong&gt; is the default where AES hardware does not exist -- Google deployed it in Chrome on Android because it runs about three times faster than AES-GCM on devices without AES acceleration, and it is constant-time in portable software by design [@rfc8439] [@google_chacha_blog2014]. Both are counter-mode stream constructions, and that structural fact, not the label &quot;AEAD,&quot; is why they are immune.A stream construction has &lt;em&gt;no block padding at all&lt;/em&gt; -- the keystream is simply truncated to the plaintext length. So the object Vaudenay&apos;s atom acts on, a padded final block whose validity the receiver checks, does not exist. There is no surface. This is why &quot;GCM has a tag, could it have a padding oracle?&quot; answers itself: there is nothing to pad.&lt;/p&gt;
&lt;p&gt;Then the standards removed the choice. TLS 1.3 (RFC 8446, 2018) removes CBC cipher suites entirely and mandates AEAD, and QUIC inherits that record layer, so a conformant modern stack cannot express the padding-oracle precondition [@rfc8446].&lt;/p&gt;
&lt;p&gt;For the deployed base that could not jump straight to 1.3, RFC 7366 (2014) retrofits Encrypt-then-MAC onto TLS 1.0 through 1.2 as a negotiated extension -- extension type 22 -- citing Bellare-Namprempre and Krawczyk by name as the reason MtE &quot;is no longer regarded as secure&quot; [@rfc7366]. And BCP 195 (RFC 9325, 2022) codifies the operational rule: prefer TLS 1.3, prefer AEAD suites on 1.2, and recommend against CBC [@rfc9325].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;How it works&lt;/th&gt;
&lt;th&gt;What it buys&lt;/th&gt;
&lt;th&gt;Status 2024 to 2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;AES-GCM&lt;/td&gt;
&lt;td&gt;AES-CTR plus GHASH tag, verified first&lt;/td&gt;
&lt;td&gt;No padding surface, fastest with AES hardware&lt;/td&gt;
&lt;td&gt;Default (TLS 1.3, QUIC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ChaCha20-Poly1305&lt;/td&gt;
&lt;td&gt;ChaCha20 plus Poly1305, verified first&lt;/td&gt;
&lt;td&gt;Constant-time in software, ~3x without AES-NI&lt;/td&gt;
&lt;td&gt;Co-default, WireGuard, OpenSSH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encrypt-then-MAC (RFC 7366)&lt;/td&gt;
&lt;td&gt;MAC over IV and ciphertext, verified first&lt;/td&gt;
&lt;td&gt;Structural fix for legacy CBC&lt;/td&gt;
&lt;td&gt;Compose-by-hand rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Constant-time CBC-HMAC&lt;/td&gt;
&lt;td&gt;Harden the MtE order in place&lt;/td&gt;
&lt;td&gt;Nothing new; fragile&lt;/td&gt;
&lt;td&gt;Deprecated (BCP 195)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Misuse-resistant, committing AEAD&lt;/td&gt;
&lt;td&gt;AES-GCM-SIV, committing wrappers&lt;/td&gt;
&lt;td&gt;Nonce-repeat safety, key commitment&lt;/td&gt;
&lt;td&gt;Ascending, niche&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Padding-oracle detection&lt;/td&gt;
&lt;td&gt;TLS-Attacker, padcheck scanners&lt;/td&gt;
&lt;td&gt;Measures residual exposure&lt;/td&gt;
&lt;td&gt;Active tooling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The honest status has two levels. At the primitive level the class is &lt;em&gt;closed&lt;/em&gt;: TLS 1.3 has no CBC-HMAC record layer, so it has no padding oracle. But CBC-HMAC survives in the long tail -- legacy TLS, VPN appliances, load balancers, IoT stacks, and home-grown application crypto -- which is why padding oracles are still discovered, in 1.83% of the top million as recently as the 2019 scan, exploitable without precise timing [@merget2019].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Treat any distinguishable decryption error on a CBC-HMAC endpoint as a reportable finding, not a performance bug to smooth over. The lesson of five generations is that the construction, not any single leak, is the problem: CBC-HMAC is the thing to &lt;em&gt;retire&lt;/em&gt;. Every hour spent hardening its constant-time behavior is an hour not spent migrating to AEAD, which needs no such hardening.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&quot;Use AEAD&quot; is the entire answer for greenfield code. But engineers inherit constraints -- a mode they cannot change, a library without AEAD, a protocol mid-migration -- so the real question is not &quot;what is best&quot; but &quot;what are my options, ranked, and exactly when does each apply?&quot;&lt;/p&gt;
&lt;h2&gt;7. How to Not Have a Padding Oracle, Ranked&lt;/h2&gt;
&lt;p&gt;There are three ways to keep a padding oracle out of your system, in strict order of durability -- and the ranking is a theorem, not a taste. The yardstick is one question: &lt;em&gt;is authenticity checked before anything parses the plaintext?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First choice: AEAD.&lt;/strong&gt; Authenticity is intrinsic, there is no padding, and there are &lt;em&gt;zero composition knobs&lt;/em&gt; for an implementer to misset. This is the default, full stop. Its own frontier is a genuinely different problem, not a padding successor: nonce reuse under AES-GCM is catastrophic -- the &quot;forbidden attack,&quot; demonstrated against real TLS and IPMI stacks by Böck et al. (WOOT &apos;16) [@bock_nonce_woot2016] -- and standard AEAD is not key-committing, so one ciphertext can be made to open to different valid plaintexts under different keys [@albertini_committing2022]. Those are addressed by AES-GCM-SIV for nonce-misuse resistance and by committing AEAD constructions, which the CFRG&apos;s property vocabulary now names formally [@rfc8452] [@rfc9771]. Treat that as a one-line signpost, not a reason to hesitate on AEAD.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Second choice: Encrypt-then-MAC by hand.&lt;/strong&gt; Correct, but only if you get three things right -- an &lt;em&gt;independent&lt;/em&gt; MAC key (never the encryption key), coverage of &lt;em&gt;both&lt;/em&gt; the IV and the ciphertext, and a &lt;em&gt;constant-time&lt;/em&gt; tag comparison performed &lt;em&gt;before&lt;/em&gt; any decrypt or unpad. That is the RFC 7366 shape [@rfc7366]. Three knobs an implementer can misset is precisely the argument for reaching for AEAD&apos;s zero knobs whenever you can.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Third choice, and only if forced: constant-time MtE / CBC-HMAC.&lt;/strong&gt; This is the &quot;make the existing order safe in place&quot; path, and it is the cautionary option to &lt;em&gt;retire&lt;/em&gt;, not to choose. Lucky Thirteen, Lucky Microseconds, and CVE-2016-2107 are the evidence that it fights the construction: MtE keeps unauthenticated ciphertext reaching the parser, so the distinguisher re-emerges through whatever the CPU or the compiler leaves open [@lucky13_2013] [@cve_2016_2107].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;AES-GCM&lt;/th&gt;
&lt;th&gt;ChaCha20-Poly1305&lt;/th&gt;
&lt;th&gt;Encrypt-then-MAC (CBC-HMAC)&lt;/th&gt;
&lt;th&gt;Constant-time MtE (CBC-HMAC)&lt;/th&gt;
&lt;th&gt;AES-GCM-SIV&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Authenticity checked first?&lt;/td&gt;
&lt;td&gt;Yes (intrinsic)&lt;/td&gt;
&lt;td&gt;Yes (intrinsic)&lt;/td&gt;
&lt;td&gt;Yes (verify tag first)&lt;/td&gt;
&lt;td&gt;No (decrypt and unpad first)&lt;/td&gt;
&lt;td&gt;Yes (intrinsic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Padding-oracle surface&lt;/td&gt;
&lt;td&gt;None (stream)&lt;/td&gt;
&lt;td&gt;None (stream)&lt;/td&gt;
&lt;td&gt;None (rejected pre-unpad)&lt;/td&gt;
&lt;td&gt;Full (precondition survives)&lt;/td&gt;
&lt;td&gt;None (stream)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Composition knobs to misset&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Many&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nonce or IV reuse behavior&lt;/td&gt;
&lt;td&gt;Catastrophic&lt;/td&gt;
&lt;td&gt;Catastrophic&lt;/td&gt;
&lt;td&gt;IV must be unpredictable&lt;/td&gt;
&lt;td&gt;IV must be unpredictable&lt;/td&gt;
&lt;td&gt;Graceful (equality leak only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status 2024 to 2026&lt;/td&gt;
&lt;td&gt;Active default&lt;/td&gt;
&lt;td&gt;Active co-default&lt;/td&gt;
&lt;td&gt;Compose-by-hand rule&lt;/td&gt;
&lt;td&gt;Deprecated (BCP 195)&lt;/td&gt;
&lt;td&gt;Ascending, niche&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Only the first two options remove the &lt;em&gt;precondition&lt;/em&gt;; the third merely silences the loudest channel. That is the whole ranking, and it maps onto the parallel history from the last section: AEAD and Encrypt-then-MAC are what IPsec effectively had from the start, while constant-time MtE is the fifteen-year attempt to make SSL/TLS&apos;s original order safe without changing it.&lt;/p&gt;
&lt;p&gt;So the durable options all share one property: they refuse to let unauthenticated ciphertext reach a parser. That raises a deeper question a careful reader should now be asking. &lt;em&gt;Why&lt;/em&gt; is one accept/reject bit enough to be fatal in the first place -- and is Encrypt-then-MAC &lt;em&gt;provably&lt;/em&gt; enough to stop it, or just empirically better so far?&lt;/p&gt;
&lt;h2&gt;8. Why a Bit Is Enough, and Why the Fix Is a Theorem&lt;/h2&gt;
&lt;p&gt;Two boundaries frame the whole subject: how &lt;em&gt;little&lt;/em&gt; leakage the attacker needs, which is frighteningly little, and how &lt;em&gt;hard&lt;/em&gt; the defender&apos;s guarantee actually is, which is a proof rather than a hope.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The lower bound: one reliable bit suffices.&lt;/strong&gt; A single accept/reject bit per query, combined with CBC&apos;s malleability, recovers plaintext at about 128 guesses per byte, and the cipher is never attacked [@vaudenay2002]. The consequence is a hard limit on defense that every engineer should internalize: there is no &quot;leak too small to matter,&quot; only &quot;too noisy to measure cheaply.&quot; The bit is information-theoretically sufficient; the only variable is how many queries it takes to read it reliably.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Lucky Thirteen turned a difference of a few tens of CPU cycles -- invisible to a human, buried in network jitter -- into full plaintext recovery by amplifying it statistically over many sessions [@lucky13_2013]. If a one-bit distinguisher exists at all, &quot;make it quieter&quot; only raises the query count; it never reaches zero. The only defense that reduces the leak to &lt;em&gt;nothing&lt;/em&gt; is removing the precondition, so no bit is ever produced.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;The impossibility in the middle.&lt;/strong&gt; An unauthenticated, malleable mode is provably not IND-CCA2. CBC without integrity is a decryption oracle by construction, so no amount of error-message hygiene or timing equalization can rescue MAC-then-encrypt CBC against a determined side-channel adversary. The impossibility lives in the &lt;em&gt;precondition itself&lt;/em&gt; -- in letting a malleable ciphertext be decrypted before it is authenticated -- which is why the deployed padding oracle is exactly the &lt;a href=&quot;https://paragmali.com/blog/secure-against-whom-the-security-definitions-every-protocol-/&quot; rel=&quot;noopener&quot;&gt;IND-CCA2 break&lt;/a&gt; this series defines in Part 1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The upper bound: the fix is a hard theorem.&lt;/strong&gt; The best achievable defense is a proved one.&lt;/p&gt;

A scheme has integrity of ciphertexts when an adversary, even after seeing many valid ciphertexts, cannot produce *any* new ciphertext the receiver accepts as valid. This is the property that closes the oracle: if every forged ciphertext is rejected before decryption, the receiver never reveals a padding verdict on attacker-chosen input. Encrypt-then-MAC and AEAD provide it; MAC-then-encrypt does not, generically.
&lt;p&gt;Encrypt-then-MAC with an IND-CPA cipher and a strongly unforgeable MAC (SUF-CMA) generically attains IND-CCA plus integrity of ciphertexts, so a forged ciphertext is rejected with overwhelming probability &lt;em&gt;before&lt;/em&gt; decryption -- the oracle is closed by theorem, not by patch [@bellare_namprempre2000]. Krawczyk marks the honest boundary of the alternative: MAC-then-encrypt is conditionally provable for CBC and counter mode, so the real-world MtE breaks are implementation and side-channel failures, not refutations of a theorem -- but Encrypt-then-MAC needs no such conditions [@krawczyk2001].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; At the level of construction design there is no gap. The lower bound -- any observable padding verdict yields byte-at-a-time decryption -- is &lt;em&gt;met&lt;/em&gt; by removing the precondition, and the upper bound -- reject forgeries before decryption, IND-CCA plus INT-CTXT -- is &lt;em&gt;achieved&lt;/em&gt; by Encrypt-then-MAC and AEAD. Best-possible and best-achieved coincide. Every remaining gap is implementation and deployment, not mathematics.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is Aha number three, and it is a humbler note than it first sounds. If the design problem is provably solved, why do scanners still find these oracles in production, and why did a correct construction get re-broken by its own patch? Because &quot;solved on paper&quot; and &quot;solved in a compiled binary on a specific CPU, deployed to a billion devices&quot; are different sentences -- and the space between them is where the class still lives.&lt;/p&gt;
&lt;h2&gt;9. Where Padding Oracles Still Live&lt;/h2&gt;
&lt;p&gt;The construction-level problem is closed; the &lt;em&gt;class&lt;/em&gt; is not. Here are four places the 2002 bug remains exploitable, and one frontier that would end the whack-a-mole.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constant-time is a moving target.&lt;/strong&gt; Even with the correct construction, a specific compiled binary on a specific CPU can reintroduce a secret-dependent timing difference through branch prediction, cache behavior, or an assembly fast path -- and the countermeasure can also slip in a plainer way. CVE-2016-2107 is the canonical evidence: OpenSSL&apos;s AES-NI fast path, written to make the fix constant-time, dropped a length check and re-created the oracle -- leaking not through timing but through a distinguishable alert (bad_record_mac versus record_overflow), which is why TLS-Attacker found it by clustering responses rather than measuring cycles [@cve_2016_2107]. The strongest partial answer is formally verified, secret-independent cryptographic code -- HACL* and EverCrypt prove memory safety, functional correctness, &lt;em&gt;and&lt;/em&gt; secret independence, and ship in Firefox and NSS [@hacl_star]. But that covers primitives, not yet whole record layers end to end, so the verification frontier is real.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The deployed CBC-HMAC long tail.&lt;/strong&gt; Legacy TLS, VPN appliances, load balancers, and IoT stacks that cannot move to TLS 1.3 keep MAC-then-encrypt CBC alive. The 2019 scan put the exposure at 1.83% of the top million, exploitable without precise timing, and the population shrinks year over year rather than vanishing -- a trend the SSL Pulse dashboard tracks [@merget2019] [@ssl_pulse].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Application-layer oracles.&lt;/strong&gt; This is the part TLS 1.3 does not reach, and it deserves its own aside because it is where the next decade of these bugs will be found.&lt;/p&gt;

Tibor Jager and Juraj Somorovsky broke the W3C XML Encryption standard with the same oracle, decrypting XML in SOAP and web-services stacks by watching how an endpoint reacted to manipulated ciphertext -- proof that the mechanism operates far outside TLS [@jager_somorovsky_xmlenc2011]. The application layer is full of the same shape: JWE and JOSE `A128CBC-HS256` tokens, encrypted cookies, and ViewState-style tokens reproduce the 2002 bug, often with no MAC at all, above TLS where network scanners cannot see them. A separate but adjacent hazard, Efail, exploited a CBC *malleability gadget* in S/MIME and a CFB gadget in OpenPGP to exfiltrate plaintext directly -- not a padding-verdict oracle, but the same &quot;unauthenticated malleable ciphertext&quot; precondition wearing different clothes [@efail2018].
&lt;p&gt;&lt;strong&gt;Format and parse oracles beyond padding.&lt;/strong&gt; Generalize once more: &lt;em&gt;any&lt;/em&gt; observable post-decryption structural verdict -- a JSON parse success, a protobuf validity check, a decompression outcome -- is a padding oracle by another name whenever it acts on unauthenticated ciphertext. The padding was only ever the first structure anyone checked. Jager and Somorovsky already proved the mechanism outside padding entirely [@jager_somorovsky_xmlenc2011], and systematic detection of &quot;decrypt-then-parse&quot; leaks is not yet automated the way TLS padding-oracle scanning now is.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AEAD&apos;s own frontier.&lt;/strong&gt; The successor primitive has two sharp edges of its own -- catastrophic nonce reuse in AES-GCM [@bock_nonce_woot2016] and the lack of key commitment [@albertini_committing2022] -- which matter most in exactly the places large systems trip: nonce management across many distributed senders, and multi-key or multi-recipient contexts like JWT and envelope encryption. Both are addressed &lt;em&gt;separately&lt;/em&gt; today, by AES-GCM-SIV for misuse resistance and by committing constructions that RFC 9771&apos;s vocabulary now specifies, but no single ubiquitous primitive yet delivers misuse-resistant &lt;em&gt;and&lt;/em&gt; committing &lt;em&gt;and&lt;/em&gt; fast &lt;em&gt;and&lt;/em&gt; online at once [@rfc8452] [@rfc9771]. That convergence is the open engineering target, and it is a different problem from the padding oracle, not a continuation of it.&lt;/p&gt;
&lt;p&gt;Every one of these is the same sentence wearing new clothes: unauthenticated, attacker-chosen input reaching a check whose verdict is observable. Which means the practical guide almost writes itself -- it is the thesis made operational.&lt;/p&gt;
&lt;h2&gt;10. Decision Rules: Use X With These Params in Case Y&lt;/h2&gt;
&lt;p&gt;Everything above collapses into a short decision procedure and a shorter list of nevers.&lt;/p&gt;

flowchart TD
    Start[&quot;Need authenticated encryption&quot;] --&amp;gt; Q1{&quot;Greenfield design?&quot;}
    Q1 --&amp;gt;|&quot;Yes&quot;| Q2{&quot;AES hardware present?&quot;}
    Q2 --&amp;gt;|&quot;Yes&quot;| GCM[&quot;AES-GCM, unique 96-bit nonce&quot;]
    Q2 --&amp;gt;|&quot;No&quot;| ChaCha[&quot;ChaCha20-Poly1305&quot;]
    Q1 --&amp;gt;|&quot;No, stuck with CBC&quot;| Q3{&quot;Can you retire CBC?&quot;}
    Q3 --&amp;gt;|&quot;Yes&quot;| GCM
    Q3 --&amp;gt;|&quot;No&quot;| EtM[&quot;Encrypt-then-MAC, RFC 7366, verify first&quot;]
    GCM --&amp;gt; Q4{&quot;Nonce uniqueness hard?&quot;}
    Q4 --&amp;gt;|&quot;Yes&quot;| SIV[&quot;AES-GCM-SIV&quot;]
    Q4 --&amp;gt;|&quot;No&quot;| Done[&quot;Ship it&quot;]
&lt;p&gt;The rules, in order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Default to a vetted AEAD, from a library you cannot misuse.&lt;/strong&gt; Use AES-GCM with a unique 96-bit nonce and fewer than $2^{32}$ messages per key where the CPU has AES-NI; use ChaCha20-Poly1305 where there is no AES hardware, or when you want constant-time behavior from portable software [@rfc8439]. In application code, reach for libsodium&apos;s &lt;code&gt;secretbox&lt;/code&gt; or Google Tink rather than raw primitives, and prefer any API where you &lt;em&gt;cannot&lt;/em&gt; express &quot;decrypt, then check&quot; -- the safest libraries never hand you plaintext before verification.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If nonce uniqueness is hard to guarantee&lt;/strong&gt; across many independent senders or under snapshot and rollback risk, use AES-GCM-SIV, so a nonce repeat degrades gracefully instead of catastrophically [@rfc8452].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If a ciphertext may be opened under more than one key&lt;/strong&gt; -- JWT and JOSE, envelope encryption, abuse reporting -- use a committing AEAD [@albertini_committing2022] [@rfc9771].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If you must compose by hand,&lt;/strong&gt; use Encrypt-then-MAC: encrypt, then compute the MAC over the IV and ciphertext with an &lt;em&gt;independent&lt;/em&gt; MAC key, and verify the tag in constant time &lt;em&gt;before&lt;/em&gt; you decrypt or unpad [@rfc7366].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;On a legacy TLS 1.2 CBC deployment you cannot yet retire,&lt;/strong&gt; negotiate RFC 7366 Encrypt-then-MAC, prefer AEAD suites, and follow BCP 195 [@rfc9325].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Never&lt;/strong&gt; return a distinct &quot;bad padding&quot; error; never branch or vary timing on padding validity; never decrypt before verifying; never reuse the encryption key as the MAC key; never leave the IV out of the MAC; and never ship SSL 3.0 or non-RFC-7366 CBC.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are stuck at the fourth rule, the shape below is the reference. It is dependency-free and non-cryptographic on purpose: copy the &lt;em&gt;order of operations&lt;/em&gt;, not the stand-in primitives.&lt;/p&gt;
&lt;p&gt;{`
// Reference SHAPE for a correct Encrypt-then-MAC open().
// constantTimeEqual, hmac, cbcDecrypt, removePkcs7 are stand-ins, NOT real crypto.
function constantTimeEqual(a, b) {
  if (a.length !== b.length) return false;
  let diff = 0;
  for (let i = 0; i &amp;lt; a.length; i++) diff |= a[i] ^ b[i];
  return diff === 0;   // no early exit: time is independent of where they differ
}&lt;/p&gt;
&lt;p&gt;function open(kEnc, kMac, iv, ciphertext, tag) {
  // 1. Authenticate FIRST, over IV concat ciphertext, in constant time.
  const expected = hmac(kMac, iv.concat(ciphertext));
  if (!constantTimeEqual(tag, expected)) return &quot;FAIL&quot;;  // one outcome, always&lt;/p&gt;
&lt;p&gt;  // 2. Only authentic ciphertext ever reaches decryption and unpadding.
  const padded = cbcDecrypt(kEnc, iv, ciphertext);
  const plain = removePkcs7(padded);
  return plain === null ? &quot;FAIL&quot; : plain;                // same FAIL either way
}&lt;/p&gt;
&lt;p&gt;// Stand-ins so the snippet runs (NOT secure):
function hmac(k, data)          { return data.map((b) =&amp;gt; (b ^ k) &amp;amp; 0xff); }
function cbcDecrypt(k, iv, c)   { return c; }
function removePkcs7(p)         { return p; }&lt;/p&gt;
&lt;p&gt;console.log(open(1, 2, [9, 9], [4, 5, 6], [7, 7, 7])); // FAIL: forged tag rejected first
`}&lt;/p&gt;
&lt;p&gt;Every misuse in real code maps one-to-one onto a named break in the catalog. That mapping is the practical guide as a grid.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Misuse seen in code&lt;/th&gt;
&lt;th&gt;The named break it reproduces&lt;/th&gt;
&lt;th&gt;The fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Distinct &quot;bad padding&quot; error&lt;/td&gt;
&lt;td&gt;Vaudenay, ASP.NET&lt;/td&gt;
&lt;td&gt;Verify authenticity first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-constant-time unpad and MAC&lt;/td&gt;
&lt;td&gt;Lucky Thirteen&lt;/td&gt;
&lt;td&gt;AEAD, or constant-time EtM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unchecked pad bytes&lt;/td&gt;
&lt;td&gt;POODLE&lt;/td&gt;
&lt;td&gt;Retire SSL 3.0 and CBC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-NI fast-path length slip&lt;/td&gt;
&lt;td&gt;CVE-2016-2107&lt;/td&gt;
&lt;td&gt;Verified constant-time, or AEAD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verifying the MAC after decrypting&lt;/td&gt;
&lt;td&gt;The whole class&lt;/td&gt;
&lt;td&gt;Encrypt-then-MAC ordering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nonce reuse under AES-GCM&lt;/td&gt;
&lt;td&gt;The forbidden attack&lt;/td&gt;
&lt;td&gt;Unique nonces, or AES-GCM-SIV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App-layer encrypt with no MAC&lt;/td&gt;
&lt;td&gt;JWE and cookie oracles&lt;/td&gt;
&lt;td&gt;A committing AEAD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Use a vetted AEAD: AES-GCM with unique 96-bit nonces and the under-$2^{32}$-messages-per-key cap where AES hardware exists, or ChaCha20-Poly1305 where it does not. If you must keep CBC, negotiate RFC 7366 Encrypt-then-MAC with an independent MAC key and a constant-time verify performed first. Never ship SSL 3.0 or non-RFC-7366 CBC. That is the entire checklist, because the lesson is a single sentence.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Detection is cheap enough to wire into a pipeline, and you should, because content-difference oracles need no timing rig to find [@merget2019].&lt;/p&gt;

Point an open-source padding-oracle scanner at your own hosts. Craig Young&apos;s `padcheck` and the TLS-Attacker project&apos;s `TLS-Padding-Oracles` both probe for the invalid-padding-versus-invalid-MAC content differences that Zombie POODLE and GOLDENDOODLE exploit, and they run without a precise timing setup [@padcheck] [@tls_padding_oracles]. A clean result on a CBC endpoint is reassuring; any distinguishable response is a reportable finding, not a tuning opportunity.
&lt;p&gt;The checklist is short because the lesson is one sentence. Before restating it, clear the confident, wrong sentences that keep this bug alive in design meetings.&lt;/p&gt;
&lt;h2&gt;11. Misconceptions, Named and Corrected&lt;/h2&gt;
&lt;p&gt;The padding oracle survives mostly because a handful of confident, wrong sentences keep getting said in design meetings. Here they are, corrected.&lt;/p&gt;


The strength of AES is irrelevant to this attack, because the key is never attacked. A padding oracle recovers plaintext from the receiver&apos;s error handling -- a distinguishable answer to &quot;was the padding valid?&quot; -- combined with CBC&apos;s malleability [@vaudenay2002]. The ASP.NET break recovered authentication tickets and `web.config` with AES-256 fully intact [@rizzo_duong_woot2010]. &quot;The cipher is strong&quot; and &quot;the system is secure&quot; are different claims.


No. The same accept/reject bit re-emerges through the next-quietest channel. Once the error message was unified, it leaked through coarse timing (Canvel et al., 2003) and then through statistical timing under unified errors (Lucky Thirteen, 2013), and through unchecked structure entirely (POODLE, 2014) [@canvel2003] [@lucky13_2013] [@poodle_writeup]. Silencing one channel just moves the leak; only removing the precondition closes it.


No -- and the overstatement matters. Krawczyk proved MAC-then-encrypt conditionally secure for CBC and counter mode, so the real-world breaks are implementation, side-channel, and underspecified-padding failures, not refutations of a theorem [@krawczyk2001]. What is true is that MtE is *fragile in practice*: it leaves unauthenticated ciphertext reaching the parser, so constant-time MtE is a fight against the construction. The fix is to change the order, not to declare a theorem false.


It is a padding oracle; the downgrade is only the enabler that forces a client onto vulnerable SSL 3.0, whose pad bytes are unchecked by specification [@poodle_writeup] [@rfc6101]. The proof is TLS-POODLE (CVE-2014-8730), the same oracle against TLS stacks that copied the lax check, with no downgrade at all [@cve_2014_8730]. Frame POODLE as a padding oracle first, a downgrade second.


No. Bleichenbacher (1998) is an RSA PKCS #1 v1.5 oracle -- a different primitive with different arithmetic [@bleichenbacher1998]. Vaudenay (2002) is the first *CBC* instance [@vaudenay2002]. Bleichenbacher is the ancestor &quot;in spirit,&quot; because he first showed that a structural validity verdict is a decryption oracle, but calling his attack a CBC padding oracle confuses two branches of the family tree.


No. AES-GCM and ChaCha20-Poly1305 are counter-mode stream constructions with no block padding, and they verify the authentication tag before releasing any plaintext, so the Vaudenay atom has no surface to act on [@rfc8439]. GCM&apos;s own hazard is nonce reuse, which is a different problem -- the &quot;forbidden attack&quot; -- not a padding oracle [@bock_nonce_woot2016].


Only if authenticity is checked *first* and the unpadding is *also* constant-time. A constant-time compare on a MAC you verify *after* decrypting still leaves the padding check reachable, which is the whole class -- and a hand-written fast path can reintroduce the oracle anyway, as CVE-2016-2107 did, through a missing length check observable as a distinguishable alert rather than a timing leak [@cve_2016_2107]. The safe pattern is verify-then-decrypt, or an AEAD that gives you no other option.

&lt;p&gt;Every correction points at the same root: the padding was never the bug. Time to say the sentence the whole article was built to earn.&lt;/p&gt;
&lt;h2&gt;Decrypt, Then Confess&lt;/h2&gt;
&lt;p&gt;Return to that ASP.NET server in September 2010. AES-256 intact. The key never touched, never even approached. And the plaintext -- authentication tickets, &lt;code&gt;web.config&lt;/code&gt;, the site&apos;s master secrets -- gone, one byte at a time, because the server answered a question it should never have been asked before it authenticated the ciphertext [@rizzo_duong_woot2010].&lt;/p&gt;
&lt;p&gt;Line up the catalog and the shape is unmistakable. Bleichenbacher, Vaudenay, Canvel, ASP.NET, Lucky Thirteen, POODLE, CVE-2016-2107, Zombie POODLE: in every case the cipher did exactly what it promised, and the variable was always the &lt;em&gt;order of operations&lt;/em&gt;, leaking through a quieter channel each time it was silenced. A loud error became coarse timing became statistical timing became unchecked structure became a fix that re-created its own oracle. Five generations chased the bit; the bit kept escaping, because the precondition -- unauthenticated, malleable ciphertext reaching a padding check -- was never removed.&lt;/p&gt;
&lt;p&gt;The resolution the field finally deployed is a single move: verify authenticity &lt;em&gt;first&lt;/em&gt;. Encrypt-then-MAC proves it -- IND-CCA plus integrity of ciphertexts, the strongest of the three generic compositions, published two years &lt;em&gt;before&lt;/em&gt; Vaudenay&apos;s attack [@bellare_namprempre2000]. AEAD ships it as one primitive with no knob to misset, and TLS 1.3 makes it the only option a conformant stack can express [@rfc8446].&lt;/p&gt;
&lt;p&gt;This mirrors the running lesson of the series: Part 1&apos;s IND-CCA2 adversary is not a chalkboard abstraction but the exact adversary that walked out of that ASP.NET server, and Part 5&apos;s warning that confidentiality is not integrity is precisely the gap a padding oracle drives through.&lt;/p&gt;

When a ciphertext you did not create arrives, what does your receiver reveal about it before it has proven the ciphertext authentic? Encrypt-then-MAC and AEAD are the discipline of making the answer nothing.
&lt;p&gt;Carry that one question into every protocol you design or review. Drop Lucky Thirteen onto it, drop POODLE onto it, drop the next application-layer JWE oracle onto it: each is a non-empty answer, and the fix is always the same shape. The cipher was never the weak link, and no future cipher will be. That is why this is Part 6 of a field guide to &lt;em&gt;protocol design&lt;/em&gt;, not a chapter on block ciphers.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;padding-oracles-field-guide&quot; keyTerms={[
  { term: &quot;Padding oracle&quot;, definition: &quot;An attack class where a receiver&apos;s observable verdict on the padding of attacker-chosen ciphertext becomes a plaintext-recovery oracle, never touching the key.&quot; },
  { term: &quot;PKCS#7 padding&quot;, definition: &quot;Append n bytes each equal to n to fill the final block; a full extra block when already aligned (RFC 2315).&quot; },
  { term: &quot;CBC malleability&quot;, definition: &quot;Because each plaintext block is D_k(C_i) XOR C_(i-1), flipping a ciphertext byte flips the same plaintext byte deterministically.&quot; },
  { term: &quot;Chosen-ciphertext attack (IND-CCA2)&quot;, definition: &quot;An adversary that submits ciphertexts and learns from the receiver&apos;s reactions; a padding oracle is a deployed instance.&quot; },
  { term: &quot;Message authentication code (MAC)&quot;, definition: &quot;A keyed tag proving a message is authentic and unmodified; HMAC is the deployed instance.&quot; },
  { term: &quot;MAC-then-encrypt (MtE)&quot;, definition: &quot;MAC the plaintext, then encrypt; the receiver decrypts and unpads before verifying, so the padding verdict is observable by construction. SSL and TLS&apos;s original choice.&quot; },
  { term: &quot;Encrypt-then-MAC (EtM)&quot;, definition: &quot;MAC the ciphertext and IV, verify first, decrypt only authentic ciphertext; attains IND-CCA plus INT-CTXT. IPsec ESP and RFC 7366.&quot; },
  { term: &quot;INT-CTXT (integrity of ciphertexts)&quot;, definition: &quot;The adversary cannot produce any new ciphertext the receiver accepts; the property that closes the oracle.&quot; },
  { term: &quot;AEAD&quot;, definition: &quot;Authenticated Encryption with Associated Data: one primitive that verifies authenticity as part of decryption and returns nothing on failure (RFC 5116).&quot; },
  { term: &quot;Constant-time comparison&quot;, definition: &quot;A check whose running time does not depend on secret data or on where a difference occurs; the countermeasure Lucky Thirteen forced, whose hand-written implementation CVE-2016-2107 later showed to be fragile.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>cryptography</category><category>padding-oracle</category><category>cbc</category><category>tls</category><category>authenticated-encryption</category><category>aead</category><category>encrypt-then-mac</category><category>lucky-thirteen</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>