# The AEAD Decision Matrix: Seven Ciphers, Three Edges, One Choice

> AES-GCM, ChaCha20-Poly1305, CCM, OCB3, GCM-SIV, AEGIS, and Ascon, compared by the three sharp edges that decide every deployment: nonce, hardware, commitment.

*Published: 2026-07-08*
*Canonical: https://paragmali.com/blog/the-aead-decision-matrix-seven-ciphers-three-edges-one-choic*
*© Parag Mali. All rights reserved.*

---
<TLDR>
Every modern AEAD makes the same three promises, and they differ only at the sharp edges where those promises stop. Three edges decide a real deployment: the **nonce contract** (catastrophic on reuse, or misuse-resistant), the **performance and hardware profile** (AES-NI plus CLMUL, constant-time software, or a few thousand gates), and **commitment** (does one ciphertext bind to exactly one key?). "Which AEAD should I use?" is not a ranking from worst to best. It is a function: default to AES-GCM or ChaCha20-Poly1305, and escalate to AES-GCM-SIV, AES-CCM, Ascon, OCB3, or AEGIS only when a specific edge demands it. Every famous break -- invisible salamanders, nonce reuse on live TLS, `CCM_8` forgeries -- was a deployment stepping on an edge, not a broken cipher.
</TLDR>

## 1. Two Failures That Should Have Been Impossible

In 2018, a team of cryptographers handed Facebook a single encrypted file that decrypted to two completely different, perfectly meaningful images, and whose authentication tag verified correctly for *both*, under two different keys [@dodis2018-salamander]. The cipher was AES-GCM, the internet's default authenticated encryption. Nothing about it was broken. That is the unsettling part: AES-GCM did *exactly* what it promised. It had just never promised the thing everyone assumed it did.

The result defeated Facebook Messenger's abuse-reporting scheme, which relied on the encrypted attachment being *bound* to the key that produced it. The authors called their construction "invisible salamanders" [@dodis2018-salamander]. Your reflex on reading this -- "but it is *authenticated*, so how did the tag pass?" -- is the entire subject of this article. The word "authenticated" carries less than you think.

Now the second failure, because one break only shows one edge. In 2016, researchers scanning the live internet found 184 HTTPS servers reusing a `(key, nonce)` pair under AES-GCM [@bock2016]. A repeated nonce in GCM is not a hygiene slip that costs you a little margin. It instantly leaks the XOR of the two plaintexts, and -- via an attack Antoine Joux had described to NIST a decade earlier, in 2006 -- it lets an attacker forge arbitrary messages [@joux2006]. The confidentiality half of that failure is easy to see for yourself.

<RunnableCode lang="js" title="Why one repeated GCM nonce is catastrophic: the keystream cancels">{`
// A stream-cipher-style AEAD (GCM, ChaCha20-Poly1305) turns the key+nonce
// into a keystream, then XORs it with the plaintext. Reuse the nonce and
// you reuse the keystream -- so it cancels out of the XOR of two ciphertexts.
const keystream = [0x9e, 0x37, 0xb1, 0xf2, 0x4a];   // same (key, nonce) => same keystream
const xor = (a, b) => a.map((x, i) => x ^ b[i]);

const p1 = [...'HELLO'].map(c => c.charCodeAt(0));
const p2 = [...'WORLD'].map(c => c.charCodeAt(0));

const c1 = xor(p1, keystream);   // ciphertext 1
const c2 = xor(p2, keystream);   // ciphertext 2, SAME nonce

// Attacker sees only c1 and c2, never the key or keystream:
const leaked = xor(c1, c2);      // == p1 XOR p2, the keystream is gone
const recovered = xor(leaked, p2);  // and if p2 is ever guessed, p1 falls out
console.log('c1 XOR c2 leaks P1 XOR P2:', leaked.join(','));
console.log('recovered P1:', String.fromCharCode(...recovered));
`}</RunnableCode>

Neither of these was a broken cipher. AES-GCM met its specification in both cases. The salamander bound nothing to a key because AES-GCM was never designed to; the TLS servers leaked plaintext because they violated the one contract GCM cannot survive. Both failures were the same shape: a deployment reached for an AEAD and then stepped on the one sharp edge its designers had moved somewhere the deployment could not avoid.

That is the thesis of this field guide. Authenticated encryption with associated data (AEAD) fused confidentiality and integrity so completely that composing them by hand became a solved problem. The remaining hard problem is choosing *among* AEADs, and that choice turns on three edges: the **nonce contract**, the **performance and hardware profile**, and the **commitment** axis.

Part 1 of this series defined an AEAD's guarantees as [IND-CPA plus INT-CTXT](/blog/secure-against-whom-the-security-definitions-every-protocol-/); commitment is a robustness property *beyond* both. Part 6 showed the padding-oracle cost of the botched integrity AEAD was built to remove.<Sidenote>The nonce-reuse breaks are widely mis-cited to CVE-2016-0270. That CVE actually names IBM Domino, and the NVD entry itself warns it has been "incorrectly used for GCM nonce reuse issues in other products" [@cve-2016-0270].</Sidenote>

> **Key idea:** "Which AEAD should I use?" is not a ranking. It is a function over three edges: pick the construction whose failure mode your deployment can *guarantee* it will never trigger. The salamander triggered the commitment edge; the TLS servers triggered the nonce edge. Same lesson, two edges.

If "authenticated" does not mean "bound to one key," and "encrypted" does not survive a repeated nonce, then what *exactly* does an AEAD promise, and where does each promise stop? To answer that, we have to go back to the moment when "encrypt" and "authenticate" were still two separate calls.

## 2. From Two Calls to One

Here is a question that sounds trivial and is not: you have a cipher and you have a message authentication code (MAC). In which order do you apply them? Most engineers guess. The wrong guess shipped in SSL, IPsec, and SSH, and it took the field a decade of theory to sort out which guess was which.

There are three orderings. **Encrypt-and-MAC** authenticates the plaintext and appends the tag beside the ciphertext (SSH). **MAC-then-Encrypt** authenticates the plaintext, then encrypts plaintext and tag together (SSL and, for years, TLS). **Encrypt-then-MAC** encrypts, then authenticates the *ciphertext* (IPsec).

In 2000, Mihir Bellare and Chanathip Namprempre proved these are not interchangeable: only Encrypt-then-MAC generically preserves both privacy and integrity for *any* secure cipher and *any* secure MAC [@bn2000]. A year later, Hugo Krawczyk showed the authenticate-then-encrypt method used in SSL is not generically secure while Encrypt-then-MAC is [@krawczyk2001]. Part 6 is the sequel: MAC-then-encrypt is exactly the door a [padding oracle](/blog/they-read-your-plaintext-without-breaking-your-cipher-a-fiel/) walks through.

<Definition term="Authenticated Encryption with Associated Data (AEAD)">
One keyed call that provides confidentiality of the plaintext, integrity of the plaintext, and integrity (but not secrecy) of an extra header called the associated data. The uniform interface was standardized in RFC 5116 [@rfc5116].
</Definition>

The lesson cut deeper than "pick Encrypt-then-MAC." If two correct primitives can combine into an *insecure* whole, hand-composition is a footgun no matter how good the parts are. The fix was to make a *single* primitive own both goals, so no protocol designer could botch the join.

Charanjit Jutla showed the way in 2001 with IAPM and IACBC, modes that delivered message integrity in essentially one pass, almost for free [@jutla2001]. The same year, Phillip Rogaway and coauthors published OCB, a one-pass block-cipher mode built for exactly this [@ocb2001]. Then, in 2002, Rogaway named the primitive: real messages carry a header -- routing bytes, version numbers, sequence counters -- that must be *authenticated* but not *encrypted*, because intermediaries need to read it. His "Authenticated-Encryption with Associated-Data" formalized that extra input [@rogaway2002-ad].

<Definition term="Associated Data (AD)">
The header bytes an AEAD authenticates but does not encrypt: routing information, protocol versions, sequence numbers. Tampering with the associated data makes tag verification fail, but the associated data itself travels in the clear [@rogaway2002-ad].
</Definition>

By 2008, David McGrew closed the loop with RFC 5116, which defined the universal interface every construction in this article implements: `AEAD-Encrypt(key, nonce, associated_data, plaintext)` returns `ciphertext || tag`, and the matching decrypt either returns the plaintext or a single, uninformative failure [@rfc5116]. One call in, one call out, no way to reverse the order of two primitives because there is only one primitive.

<Definition term="Nonce (number used once)">
A value that must be unique for every encryption under a given key. The mode, not the label, sets the exact requirement: some AEADs tolerate only uniqueness, others tolerate randomness, and a few tolerate repetition. Nonce generation is the subject of Part 2 of this series.
</Definition>

<Mermaid caption="Twenty-five years of authenticated encryption, from composition theorems to the modern portfolio">
timeline
    title The road to the AEAD portfolio
    2000 : Encrypt-then-MAC proven the safe order
    2001 : IAPM and OCB, single-pass native AE
    2002 : Rogaway names AEAD and adds associated data
    2003 : CCM standardized in RFC 3610
    2004 : GCM published by McGrew and Viega
    2006 : Joux forbidden attack, SIV misuse-resistance
    2008 : RFC 5116 fixes the universal interface
    2013 : CAESAR opens, AEGIS announced
    2016 : Nonce reuse found on live TLS servers
    2018 : Invisible salamanders break message franking
    2019 : CAESAR portfolio chosen, OCB2 broken
    2021 : Partitioning oracles weaponize non-commitment
    2025 : NIST standardizes Ascon-AEAD128
</Mermaid>

The interface was settled by 2008. But an interface is a promise about *shape*, not about *sharp edges*. Two constructions that satisfy `AEAD-Encrypt` to the letter can fail in completely different ways, and the very first AEADs to ship proved it. The one that reached the most devices did not even win on technical merit. It won because of a patent.

## 3. The Welded Modes: CCM and GCM

The first AEAD to reach a billion devices was not chosen by a cryptographer. It was chosen, in effect, by a patent lawyer. When IEEE 802.11i (the security amendment that became WPA2) needed an authenticated mode, the elegant candidate was OCB -- but OCB was patent-encumbered, and the working group would not build a wireless standard on it. So 802.11i standardized the plodding, unpatented alternative: **AES-CCM**. By device count, that decision made CCM one of the most widely deployed AEADs in the world.

**AES-CCM = Counter mode + CBC-MAC.** Doug Whiting, Russ Housley, and Niels Ferguson specified it in RFC 3610 in 2003, and NIST blessed it as SP 800-38C the next year [@rfc3610][@sp80038c]. It runs the message through CBC-MAC for the tag, then encrypts with [counter (CTR) mode](/blog/the-ciphertext-was-unbreakable-the-attacker-rewrote-it-anyw/): two passes, a strictly serial MAC, and the message length needed up front, which makes streaming awkward. What that price buys is frugality -- nothing but AES, a tiny code footprint, no second primitive to implement.

That profile is why CCM owns the constrained niche -- Bluetooth Low Energy [@bluetooth-core], Zigbee [@ieee802154], and the TLS `CCM_8` ciphersuites. IEEE 802.11i also made CCMP the mandatory data-confidentiality protocol for WPA2 [@ieee80211i], and CCM rode WPA2/CCMP into the overwhelming majority of Wi-Fi hardware over the following decade.<Sidenote>Zigbee and 802.15.4 use a variant called CCM\*, which additionally permits integrity-only or encryption-only operation, unlike the strict RFC 3610 CCM that always does both.</Sidenote> So the same plodding, all-AES mode anchors two very different worlds: the smallest constrained devices and the Wi-Fi layer that WPA2 secures. These are the building blocks from Part 5, welded to a MAC.

**AES-GCM = Counter mode + GHASH.** David McGrew and John Viega published Galois/Counter Mode in 2004, and NIST standardized it as SP 800-38D in 2007 [@mcgrew2004-gcm][@sp80038d]. GCM is everything CCM is not: one pass, fully parallelizable, and, on any CPU with AES-NI and CLMUL, blisteringly fast. It is the internet default, and AES-128-GCM is the single mandatory-to-implement (MUST) AEAD cipher suite in TLS 1.3, per RFC 8446 Section 9.1 -- a status the spec grants to no other AEAD [@rfc8446]. To understand every later failure, you need one fact about how its tag works.

<Definition term="Wegman-Carter one-time MAC">
An authenticator of the form $\text{tag} = H_k(\text{message}) + s$, where $H_k$ is a fast keyed universal hash and $s$ is a **one-time** secret mask. It is unforgeable only if $s$ is never reused. Repeat the mask and the algebraic structure of $H_k$ leaks. This is the shared root of both GHASH (AES-GCM) and Poly1305 (ChaCha20-Poly1305) [@bernstein-poly1305].
</Definition>

GCM's tag is a one-time Wegman-Carter MAC. GHASH evaluates a polynomial over the finite field $\mathrm{GF}(2^{128})$, with the ciphertext and associated-data blocks as coefficients, at a single secret point $H = \operatorname{AES}_k(0^{128})$. It then masks the result with a per-nonce keystream block:

$$T = \operatorname{GHASH}_H(A, C) \oplus \operatorname{AES}_k(J_0), \qquad H = \operatorname{AES}_k(0^{128})$$

where $J_0$ is the initial counter block derived from the nonce. The mask $\operatorname{AES}_k(J_0)$ is the one-time secret $s$. It is one-time *only because the nonce is unique*. Repeat the nonce and you repeat $J_0$, so you repeat the mask, and now two tags share it -- which turns GHASH's linear structure into a system of polynomial equations an attacker can solve.

<Definition term="GHASH">
The universal hash inside AES-GCM: a polynomial in the secret point $H = \operatorname{AES}_k(0^{128})$ evaluated over $\mathrm{GF}(2^{128})$. Because the polynomial is linear in its coefficients, recovering $H$ lets an attacker forge tags for chosen messages [@joux2006].
</Definition>

<Mermaid caption="AES-GCM in one picture: a counter-mode keystream for confidentiality, a one-time Wegman-Carter GHASH tag for integrity, both keyed from the same AES">
flowchart LR
    N["Nonce and counter"] --> CTR["AES counter mode"]
    K["Key"] --> CTR
    CTR --> KS["Keystream"]
    P["Plaintext"] --> X(("XOR"))
    KS --> X
    X --> C["Ciphertext"]
    C --> GH["GHASH polynomial at secret point H"]
    AD["Associated data"] --> GH
    K --> H["H is AES of the zero block"]
    H --> GH
    GH --> M(("XOR one-time mask"))
    K --> J["AES of the first counter block"]
    J --> M
    M --> T["Authentication tag"]
</Mermaid>

That single design choice hands GCM two sharp edges the rest of this article pays for. The first is the **nonce contract**: reuse is not a weakness, it is a detonator.

> **Note:** For every nonce-respecting AEAD -- AES-GCM, ChaCha20-Poly1305, AES-CCM, OCB3, AEGIS, and Ascon -- one repeated `(key, nonce)` pair is an immediate, total break of confidentiality for those two messages, and, with a second collision, of authenticity for the whole key [@joux2006].<Sidenote>One nonce collision leaks $P_1 \oplus P_2$ right away. Uniquely pinning the secret point $H$ for universal forgery generally needs at least two collisions, since a single pair of equations leaves multiple candidate roots. "One repeat is game over for those messages" is correct; "one repeat exposes $H$" is not quite [@bock2016].</Sidenote>

The second edge is quieter and just as dangerous, because it is two different numbers people constantly merge into one.

> **Note:** SP 800-38D fixes a **per-message** plaintext limit of $2^{39}-256$ bits (about 64 GiB), set by 32-bit counter-mode block-space exhaustion, and, separately, a **per-key** invocation cap of roughly $2^{32}$ messages when nonces are random 96-bit values, driven by the birthday bound on nonce collision [@sp80038d]. These are two different mechanisms, not two readings of one bound (the full derivation is in Section 8). The multi-user bounds that justify TLS 1.3's nonce randomization are tight [@htt2018-gcm]. Enforce both limits. Conflating them is the single most common accuracy error on this primitive.

GCM gave the internet a one-pass, hardware-fast AEAD, and in the same stroke handed it a mode where one repeated nonce is not a bug but a catastrophe. This is the same GCM negotiated inside shipping Windows protocols such as [Schannel TLS](/blog/rotating-every-cipher-schannel-and-the-twenty-year-algorithm/) and SMB 3 encryption [@ms-schannel-tls][@ms-smb-encryption]. Antoine Joux saw the danger in 2006 [@joux2006]. It took the rest of the world ten years, and a scan of the live internet, to believe him.

## 4. A Trunk With Branches

The family tree of AEAD is not a ladder from worst to best. Draw it that way and none of the modern constructions make sense, because none of them strictly dominates GCM. Draw it correctly and the whole field snaps into focus: it is a **trunk with branches**. The trunk is linear -- generic composition, then single-pass native AE, then the welded deployed modes CCM and GCM. Then, at GCM, the tree *splits*, because GCM's edges each forced a *separate* successor. No later generation wins. That is the entire point.

<Mermaid caption="The AEAD family tree: a linear trunk up to GCM, then a fan-out where each of GCM's edges forces its own successor">
flowchart TD
    G0["Generic composition, Encrypt-then-MAC"] --> G1["Single-pass native AE, IAPM and OCB"]
    G1 --> G2["Welded deployed modes, CCM and GCM"]
    G2 --> E1["Nonce edge"]
    G2 --> E2["Hardware edge"]
    G2 --> E3["Commitment edge"]
    E1 --> S1["SIV and AES-GCM-SIV, misuse-resistant"]
    E2 --> S2["ChaCha20-Poly1305, constant-time in software"]
    E2 --> S4["AEGIS and Ascon, hardware and footprint co-design"]
    E3 --> S3["Committing transforms, added on top"]
</Mermaid>

### The hardware edge: ChaCha20-Poly1305

GHASH is hard to make constant-time without the CLMUL instruction, and table-based AES is both slow and timing-leaky without AES-NI. Around 2013, that was the reality on most phones and ARM chips: no AES hardware, so GCM was either slow or a cache-timing side channel. Daniel Bernstein's answer kept GCM's exact nonce-respecting contract but threw out the parts that needed special silicon.

**ChaCha20** is an ARX cipher -- addition, rotation, XOR -- with no S-box tables to leak timing, so it is constant-time by construction [@bernstein-chacha]. **Poly1305** is a one-time Wegman-Carter MAC over a prime field rather than $\mathrm{GF}(2^{128})$, and its one-time key is derived from a ChaCha keystream block [@bernstein-poly1305].<Sidenote>Poly1305's one-time key comes from a ChaCha-derived block, not from AES. ChaCha20-Poly1305 never calls AES at all -- a common misconception, since GCM's mask does use AES.</Sidenote>

The IETF standardized the pair as an AEAD in RFC 8439 [@rfc8439], and it now protects TLS 1.3, WireGuard, OpenSSH, and the `age` file-encryption tool [@wireguard-protocol][@openssh-chacha][@age-spec]. Its normative status is widely overstated: in TLS 1.3, ChaCha20-Poly1305 is a *recommended* (SHOULD) cipher suite, not mandatory-to-implement, per RFC 8446 Section 9.1 -- a default by adoption, not by requirement [@rfc8446]. It is not weaker than GCM; it is the same nonce contract on a different, table-free engine.<Sidenote>XChaCha20-Poly1305 extends the nonce to 192 bits, large enough that random nonces essentially never collide. That is a *mitigation* of nonce-collision anxiety, not misuse-resistance -- reuse the full 192-bit nonce and it fails exactly like GCM.</Sidenote>

### The nonce edge: misuse-resistance and SIV

Every mode so far detonates on a repeated nonce, and reuse keeps happening in the real world: cloned virtual machines that resume with identical RNG state, counters reset by a crash, embedded devices with weak entropy at first boot. If the operator cannot guarantee uniqueness, the fix is a mode that *survives* the operator's mistake. In 2006, Phillip Rogaway and Thomas Shrimpton formalized exactly that goal and built the first construction for it [@rs2006].

<Definition term="Nonce-misuse-resistant AE (MRAE)">
An AEAD whose failure under a repeated nonce is graceful, not catastrophic. Repeating a `(key, nonce, associated_data, plaintext)` tuple leaks only whether two encryptions were of the *same* message -- message equality -- and nothing else. It never leaks a plaintext XOR and never hands over the authentication subkey [@rs2006][@rfc8452].
</Definition>

The mechanism is a single clean idea: derive the initialization vector *synthetically*, as a pseudorandom function of the entire message, rather than accepting it from the caller. The tag *is* the IV.

<Definition term="Synthetic IV (SIV)">
A construction in which the initialization vector is computed as a MAC over the associated data and the full plaintext, then reused as the authentication tag. Two different messages under a repeated nonce produce different synthetic IVs, so their keystreams differ and nothing leaks [@rs2006].
</Definition>

<Mermaid caption="The SIV construction: the IV is a MAC of the whole message, so identical nonces on different messages still produce different keystreams">
flowchart TD
    K["Key"] --> MAC["MAC over associated data and full plaintext"]
    AD["Associated data"] --> MAC
    N["Nonce"] --> MAC
    P["Plaintext"] --> MAC
    MAC --> IV["Synthetic IV, which is also the tag"]
    IV --> CTR["Counter-mode encryption"]
    K --> CTR
    P --> CTR
    CTR --> C["Ciphertext"]
    IV --> T["Tag sent alongside ciphertext"]
</Mermaid>

That picture also explains the price, which returns as a theorem in Section 8: to compute the IV you must read the whole message first, so SIV cannot emit its first ciphertext byte until it has seen the last plaintext byte. It is inherently two-pass.

Two deployable forms exist. **AES-SIV**, standardized by Dan Harkins in RFC 5297, targets deterministic authenticated encryption and key wrapping [@rfc5297]. **AES-GCM-SIV**, from Shay Gueron, Adam Langley, and Yehuda Lindell in RFC 8452, keeps AES-NI and CLMUL speed while adding misuse-resistance, building on the Gueron-Lindell GCM-SIV design [@rfc8452][@gl2015-gcmsiv].<Sidenote>AES-GCM-SIV hashes with POLYVAL, a little-endian sibling of GHASH, and derives a fresh message-authentication and encryption key per nonce -- a structure whose tight multi-user bounds were later established by Bose, Hoang, and Tessaro [@bht2018].</Sidenote>

<PullQuote>
"...two authenticated encryption algorithms that are nonce misuse resistant -- that is, they do not fail catastrophically if a nonce is repeated." -- RFC 8452 [@rfc8452]
</PullQuote>

Read that phrasing carefully, because it is the most misquoted sentence about SIV. "Do not fail catastrophically" is not "do not fail." A repeated nonce in AES-GCM-SIV still leaks message equality: an attacker learns that two ciphertexts encrypt the same plaintext, which is a real and sometimes serious leak. SIV makes reuse *survivable*, never *free*.

### The elegance detour: OCB3 and the patent that chose a standard

Two edges now had answers, each on its own branch. A third construction sits off to the side -- not because it is worse, but because history was unkind to it. **OCB3**, finalized by Ted Krovetz and Phillip Rogaway in 2011 and standardized as RFC 7253, is arguably the most elegant AEAD ever standardized: one block-cipher key, one pass, fully parallel, roughly one cipher call per block [@kr2011-ocb3][@rfc7253].

Its mechanism is where the elegance lives. Each block is masked by a key-derived offset -- $\text{Offset}_i = \text{Offset}_{i-1} \oplus L_{\text{ntz}(i)}$, a Gray-code walk over precomputed $L$ values -- and wrapped as $C_i = \text{Offset}_i \oplus \operatorname{ENCIPHER}(K, P_i \oplus \text{Offset}_i)$, while a *single* running plaintext checksum, $\text{Checksum} = P_1 \oplus P_2 \oplus \cdots$, produces the tag in the *same pass* [@rfc7253]. No second key, no separate MAC. It matches or beats GCM in software. And it lost anyway -- not for a technical reason.<Sidenote>A widely repeated claim is that OCB3 is *inverse-free*. It is not. OCB-DECRYPT recovers each block as $P_i = \text{Offset}_i \oplus \operatorname{DECIPHER}(K, C_i \oplus \text{Offset}_i)$, calling the block-cipher inverse $E_K^{-1}$ (RFC 7253 Section 4.3), so a hardware implementation needs both the AES encrypt *and* decrypt circuits [@rfc7253]. Inverse-free is the property of the CTR, stream, and sponge modes -- AES-GCM, AES-CCM, ChaCha20-Poly1305, AEGIS, and Ascon -- and OCB is precisely the lineage that trades it away for single-primitive elegance.</Sidenote>

<Aside label="The patent that chose a standard">
OCB was patented from birth. When the 802.11i working group picked WPA2's cipher in 2003, it passed over OCB precisely because of those patents and chose the unencumbered CCM instead. Rogaway later granted free licenses for open-source and non-military use, but the damage was done: every major protocol had already standardized on GCM and ChaCha20-Poly1305 in the years the patents were live. In 2021 Rogaway released OCB into the public domain outright -- too late to matter [@kr2021-ocb]. The honest answer to "when should I reach for OCB3 in 2026?" is "almost never, and the reason is a patent grave, not a design flaw."
</Aside>

### The dead end: OCB2 and the limits of "provably secure"

There is one more branch, and it is a warning. Between OCB1 and OCB3 sat OCB2, an ISO-standardized refinement with a security proof. In 2019, Akiko Inoue, Tetsu Iwata, Kazuhiko Minematsu, and Bertram Poettering broke it outright: universal forgery *and* full plaintext recovery, because OCB2 used the XEX\* tweakable cipher outside the regime its proof actually covered [@inoue2019-ocb2].

<Aside label="Standardized and proven is not the same as safe">
The OCB2 break is the cautionary counterpoint to every "but it has a proof" argument. OCB2 was standardized by ISO/IEC and carried a published security proof, and it was still broken end to end. A proof secures a *model*; if the construction steps outside the model's assumptions, the proof guarantees nothing. Tellingly, the same attack left OCB1 and OCB3 untouched [@inoue2019-ocb2] -- a dead-end twig on a branch whose siblings survived.
</Aside>

Two of GCM's three edges now had dedicated successors, and the family tree looked complete. But every construction so far -- GCM, ChaCha20-Poly1305, even the misuse-resistant SIV family -- quietly shared a third assumption nobody had thought to check: that "authenticated" meant "bound to one key." In 2018, that assumption broke in production, on the desk of a Facebook security engineer holding a single file with two faces.

## 5. The Commitment Reckoning and the CAESAR Crucible

Now we can explain the salamanders. Recall the mechanism from Section 3: a GCM tag is a one-time Wegman-Carter value, $\operatorname{GHASH}_H(A,C) \oplus \operatorname{AES}_k(J_0)$, and GHASH is *linear* in its coefficients. An attacker who gets to pick two keys, $k_1$ and $k_2$, can treat "make the tag verify under both" as a system of linear equations over $\mathrm{GF}(2^{128})$ and simply solve it, producing one ciphertext that decrypts to two chosen, meaningful plaintexts and passes verification under each key [@dodis2018-salamander].

Nothing is broken. GCM guarantees confidentiality and integrity; it never promised that a ciphertext binds to a single key. That promise has a name, and until 2018 almost nobody was asking for it.

<Definition term="Key commitment (CMT-1 through CMT-4)">
A graded robustness property beyond confidentiality and integrity. CMT-1 means a ciphertext binds to exactly one *key*; CMT-4 means it binds to the full *context* -- key, nonce, associated data, and message. Bellare and Hoang proved that CMT-1 does not imply CMT-4: committing to the key is strictly weaker than committing to everything [@bh2022-commit]. RFC 9771 standardized the vocabulary [@rfc9771].
</Definition>

> **Key idea:** "Authenticated" never meant "committed." An AEAD's guarantees -- IND-CPA plus INT-CTXT -- say nothing about binding a ciphertext to one key. Commitment is a third, orthogonal axis. That is why every default AEAD was non-committing and nobody noticed for fifteen years: the property was simply outside the definition everyone was proving.

Two ideas define the modern state of the art, and both come from *refusing* to treat "cipher plus separate hash" as the end of the design space.

The first is **robustness as an explicit goal** -- against the operator and against the adversary who supplies the key. The operator side is MRAE from Section 4, elevated from a mode into a principle. The adversary side is committing AEAD, and its timeline is a tidy example of a theoretical curiosity becoming an operational threat.

Invisible salamanders (2018) showed a non-committing AEAD could defeat message franking [@dodis2018-salamander]. Then, in 2021, Julia Len, Paul Grubbs, and Thomas Ristenpart turned it into a weapon: **partitioning oracle attacks** use the missing commitment to recover passwords and other low-entropy keys, crafting one ciphertext that decrypts under many candidate keys and using each success or failure to bisect the key space [@len2021-partition].

Mihir Bellare and Viet Tung Hoang then built the graded CMT-1 through CMT-4 theory and cheap transforms that add full commitment with no ciphertext-size increase [@bh2022-commit]; Ange Albertini and coauthors independently catalogued the abuses and a padding-based fix [@albertini2022], with further theory from John Chan and Phillip Rogaway [@chan2022]. Sanketh Menda and coauthors then showed the gap is portfolio-wide, with context-discovery attacks against CCM, EAX, SIV, GCM, and OCB3 [@menda2023]. RFC 9771 (2025) finally fixed the vocabulary the field had been improvising [@rfc9771].

<PullQuote>
A vetted AEAD gives you confidentiality and integrity and stops there. Commitment is a third axis nobody put in the definition -- which is exactly why one ciphertext could wear two faces.
</PullQuote>

The second idea is **native co-design**: stop bolting a cipher to a hash and instead build the AEAD *around* the hardware or footprint you actually have. Hongjun Wu and Bart Preneel's AEGIS (2013) is the AES-hardware extreme [@wu2013-aegis].

It keeps a large internal state -- eight 128-bit words in AEGIS-128L -- seeded directly from the key and nonce; the **AES round function** updates that state as it absorbs associated data and plaintext, encryption *squeezes* a keystream out of the state, and the tag comes from the *finalized* state. One primitive, one pass, no separate hash, and the IETF draft records that all variants are inverse-free and built from the AES encryption round [@aegis-draft18].

That structure is *why* AEGIS outruns GCM on AES silicon, and *why* nonce reuse is catastrophic: the whole state is a function of `(key, nonce)`, so a repeat lets an attacker unwind it. Its commitment story is a nuance, not a headline -- a 128-bit AEGIS tag delivers only about 64-bit committing security, while a 256-bit tag pushes cross-key collisions out of reach, so AEGIS is *partially* committing by tag length, neither fully committing nor flatly broken [@aegis-draft18].

At the other extreme, Ascon -- by Christoph Dobraunig, Maria Eichlseder, Florian Mendel, and Martin Schläffer -- uses a single lightweight permutation in a sponge, giving a tiny gate count and a side-channel-friendly structure for constrained hardware [@ascon2021].

<Mermaid caption="AEGIS in one picture: a large state seeded from key and nonce, updated by the AES round function as it absorbs data, squeezed for keystream, and finalized into the tag">
flowchart LR
    KN["Key and nonce"] --> ST["Large internal state, eight 128-bit words"]
    ST --> UP["AES round function update"]
    AD["Associated data"] --> UP
    P["Plaintext"] --> UP
    UP --> KS["Squeezed keystream"]
    P --> X(("XOR"))
    KS --> X
    X --> C["Ciphertext"]
    UP --> FIN["Finalized state"]
    FIN --> T["Authentication tag"]
</Mermaid>

<Definition term="Sponge construction">
A mode built from one public permutation whose state is split into a "rate" (absorbs input and is squeezed for output) and a "capacity" (the hidden security margin). A single permutation absorbs the key, nonce, associated data, and plaintext, then squeezes keystream and a tag -- no separate cipher and hash. Ascon is a sponge [@ascon2021].
</Definition>

What forced this whole portfolio into existence was a contest. The **CAESAR competition** (2013-2019), organized by Daniel Bernstein, was a public, multi-year, break-it-in-the-open bake-off [@caesar-home]. Its most important decision was structural: rather than crown a single winner, it selected a *portfolio across three use cases* -- itself the thesis of this article. The winners were Ascon and ACORN for lightweight use, AEGIS-128 and OCB for high-performance use, and Deoxys-II (first choice) and COLM for defense in depth [@caesar-portfolio].<Sidenote>Deoxys-II is built on the TWEAKEY framework for tweakable block ciphers, by Jérémy Jean, Ivica Nikolić, Thomas Peyrin, and Yannick Seurin [@caesar-portfolio].</Sidenote>

Note carefully: **Deoxys-II is a CAESAR winner, not an also-ran** -- it simply was never deployed at scale. The real also-rans are the candidates eliminated during the competition, including MORUS, which took a certificational break from Tomer Ashur, Maria Eichlseder, and coauthors and did not make the final portfolio [@morus2018].

The competition ended in 2019 with no single champion, on purpose. So where does that leave a working engineer in 2026, staring at seven names in a crypto library's documentation? To choose well, you need the current map: exactly what each construction is, where it wins, and where it bites.

## 6. The 2026 Portfolio, Precisely

The current portfolio has a stable shape: two defaults and five specialists. By deployment, the two internet defaults are AES-GCM and ChaCha20-Poly1305 -- but normatively they are not equals. In TLS 1.3 only AES-128-GCM is mandatory-to-implement (MUST); AES-256-GCM and ChaCha20-Poly1305 are both *recommended* (SHOULD), the same normative level as each other, per RFC 8446 Section 9.1 [@rfc8446]. Everything else is a deliberate escalation. Here is each construction on its edges.

**AES-GCM.** Counter mode plus a one-time GHASH tag; one pass, parallel, `O(1)` online state [@mcgrew2004-gcm]. Excels on any CPU with AES-NI and CLMUL, which is every server and most modern clients. Struggles on hardware without those instructions and, above all, on nonce discipline: reuse is fatal and the two ceilings are easy to breach [@sp80038d]. Adoption: the internet default.

**ChaCha20-Poly1305.** ARX stream cipher plus a prime-field one-time MAC; constant-time in pure software with no lookup tables [@rfc8439]. Excels precisely where GCM struggles -- phones, embedded ARM, any target without AES hardware. Same nonce contract as GCM, so it struggles on the exact same reuse cliff. Adoption: TLS 1.3, WireGuard, OpenSSH [@wireguard-protocol][@openssh-chacha].

**AES-CCM.** Counter mode plus CBC-MAC; two passes, serial, needs the length up front, but all-AES and tiny [@rfc3610]. Excels in constrained stacks (BLE [@bluetooth-core], Zigbee [@ieee802154]) and inside WPA2 [@ieee80211i]. Struggles on throughput and streaming, and the truncated `CCM_8` tag trades a real forgery budget for eight bytes [@rfc3610]. Adoption: enormous by device count.

**AES-GCM-SIV and AES-SIV.** Synthetic-IV misuse-resistant modes; two-pass by necessity [@rfc8452][@rfc5297]. Excel when nonce uniqueness cannot be guaranteed: reuse degrades to leaking message equality rather than catastrophe. Struggle on streaming (they must buffer) and still leak equality, so they are survivable, not free. AES-GCM-SIV runs near AES-GCM speed on server hardware, around 0.92 cycles per byte on Broadwell in the original design [@gl2015-gcmsiv]. Adoption: growing where reuse risk is real.

**OCB3.** One block-cipher key, one pass, fully parallel, roughly one cipher call per block -- technically superb [@kr2011-ocb3][@rfc7253]. Excels on elegance and software speed. Struggles on adoption, for the patent reasons in Section 4; it is nonce-respecting like GCM; and, unlike the CTR and stream modes, it is **not** inverse-free -- decryption calls the AES inverse circuit (RFC 7253 Section 4.3), a genuine hardware cost [@rfc7253]. Adoption: minimal, despite standardization.

**AEGIS.** Keystream and authentication driven straight from the AES round function over a large nonce-seeded state; the throughput frontier, around 0.48 cycles per byte for AEGIS-128L on 4 KB messages, faster than CCM, GCM, and OCB [@wu2013-aegis][@aegis-v11]. Excels on raw speed when you control both endpoints. Struggles on maturity and contract: nonce-respecting (catastrophic on reuse, since its whole state is nonce-seeded) and only *partially* committing -- about 64-bit committing security at a 128-bit tag, stronger at a 256-bit tag [@aegis-draft18].

Critically, **AEGIS is still an active Internet-Draft, `draft-irtf-cfrg-aegis-aead-18` from October 2025, not an RFC** -- it states plainly that it "is not an IETF product and is not a standard," and it expires on 8 April 2026 [@aegis-draft18].

**Ascon-AEAD128.** A single 320-bit lightweight permutation in a sponge; tiny state, side-channel-friendly [@ascon2021]. Excels on constrained hardware and gate count. Struggles on server throughput, where AEGIS and GCM win. It is nonce-respecting, but -- unlike the CTR and stream modes -- it commits to its inputs *without* any added transform: the tag is squeezed from the sponge's large hidden capacity after that capacity has already absorbed the key, so one ciphertext binds natively to the key it was produced under. RFC 9771 lists Ascon-AEAD128 as both key-committing and full-committing as-is, not merely as a candidate for a bolt-on fix [@rfc9771]. The currency fact matters here: **NIST SP 800-232 is final (August 2025) and standardizes Ascon-AEAD128**, a *tweaked* variant of CAESAR Ascon-128 using a larger data-absorption rate -- widely reported as 128-bit, up from the CAESAR design's 64-bit, with the exact parameter in the SP 800-232 body [@sp800232][@nist-ascon-2023]. It is not byte-identical to CAESAR Ascon [@ascon-site].

A profile only helps if you can actually call the construction, so here is where each one ships as of mid-2026, with each cell cited to that project's official documentation.

| Construction | Where it ships (libraries and frameworks) |
|---|---|
| AES-GCM | OpenSSL/BoringSSL [@openssl-aes][@boringssl-aead], Go `crypto/cipher` [@go-cipher], Java JCA [@java-jca], .NET CNG [@dotnet-aesgcm], WebCrypto (the only AEAD in the browser) [@webcrypto], libsodium (hardware-gated) [@libsodium-aegis] |
| ChaCha20-Poly1305 / XChaCha20 | OpenSSL/BoringSSL [@openssl-chacha][@boringssl-aead], libsodium (default for random-nonce APIs) [@libsodium-aegis], Go `x/crypto` [@go-chacha], WireGuard [@wireguard-protocol], OpenSSH [@openssh-chacha], `age` [@age-spec] |
| AES-CCM | mbedTLS [@mbedtls-ccm], wolfSSL [@wolfssl-ccm], Wi-Fi [@ieee80211i] / BLE [@bluetooth-core] / Zigbee [@ieee802154] firmware |
| AES-GCM-SIV | BoringSSL/OpenSSL [@boringssl-aead][@openssl-aes] and several bindings; less universal than the defaults |
| AES-SIV | `miscreant`-lineage (deterministic / key-wrap) libraries [@miscreant] |
| OCB3 | some libraries (public domain since 2021 [@kr2021-ocb]); rarely a default |
| AEGIS | libsodium (`crypto_aead_aegis128l` / `aegis256`) [@libsodium-aegis] and a growing set of high-performance libraries; not a TLS suite |
| Ascon-AEAD128 | reference and third-party implementations [@ascon-site]; adoption ramping since SP 800-232 [@sp800232] |

Two entries on that map decide real architectures. **In the browser, AES-GCM is the only AEAD you can call.**<Sidenote>WebCrypto's `SubtleCrypto.encrypt` recognizes RSA-OAEP, AES-CTR, AES-CBC, and AES-GCM, and AES-GCM is the only one of those that authenticates. Browser JavaScript that needs an AEAD without bundling a crypto library therefore has exactly one option [@webcrypto].</Sidenote> And AEGIS, still pre-RFC, is nonetheless callable in production today through libsodium's `crypto_aead_aegis128l` and `crypto_aead_aegis256` APIs -- deployability and standardization are not the same axis [@libsodium-aegis].

> **Note:** Eight constructions -- the seven cipher families, with the SIV line counted in its two deployable forms (AES-GCM-SIV and AES-SIV) -- all linear-time, all vetted, and not one strictly dominates the others. CAESAR chose a portfolio across three use cases on purpose, and NIST added Ascon for the constrained end. There is no "best AEAD," and any article or vendor that names one is hiding an assumption about your deployment [@caesar-portfolio].

Two more items complete the 2026 map. The CAESAR defense-in-depth winners, Deoxys-II and COLM, remain excellent and essentially undeployed [@caesar-portfolio]. And committing transforms -- the fix for the commitment edge -- exist and are cheap, but as of mid-2026 none is *mandated* in a shipping standard; RFC 9771 supplies vocabulary, not a required construction [@rfc9771][@bh2022-commit].

Laid side by side, those eight look interchangeable. They are not, and the tool that makes the difference legible is a single table built on the three edges.

## 7. The Decision Matrix

This is the one screen to memorize. Everything in the previous six sections collapses into two tables and a flowchart, all built on the same three edges.

The first table answers the only question that matters at selection time: for each construction, what happens on the *first repeated nonce*, what hardware does it want, and does one ciphertext bind to one key?

| Construction | First repeated nonce | Hardware profile | Commitment |
|---|---|---|---|
| AES-GCM | Catastrophic: leaks P1 XOR P2, enables forgery | AES-NI + CLMUL fast | Not committing |
| ChaCha20-Poly1305 | Catastrophic: same one-time-MAC cliff | Constant-time in software | Not committing |
| AES-CCM | Catastrophic | All-AES, tiny footprint | Not committing |
| AES-GCM-SIV | Graceful: leaks message equality only | AES-NI + CLMUL | Not committing |
| AES-SIV | Graceful: leaks message equality only | All-AES, two-pass | Not committing |
| OCB3 | Catastrophic | Fast one-pass software | Not committing |
| AEGIS | Catastrophic | AES round function, fastest | Not fully committing |
| Ascon-AEAD128 | Catastrophic | A few thousand gates | Committing from the sponge, no transform |

Read down the commitment column and the reckoning of Section 5 gets sharper than a flat "nobody commits." Every deployed CTR, stream, and welded construction -- AES-GCM, ChaCha20-Poly1305, AES-CCM, the SIV family, and OCB3 -- is non-committing by default, which is exactly what the salamander and the portfolio-wide context-discovery attacks exploit [@dodis2018-salamander][@menda2023]. Two constructions break the pattern, and it is no accident that both fuse the tag with the cipher state instead of bolting on a separate hash: AEGIS partially commits through tag length, and Ascon commits natively from its sponge [@aegis-draft18][@rfc9771]. So commitment is not a uniform failure across the portfolio -- the commitment edge is a real axis of variation, with Ascon at the strong end, AEGIS in between, and the CTR, stream, and welded modes needing a bolt-on transform. Read the nonce column and only the SIV family survives a repeat, and only by leaking equality [@rfc8452]. The second table adds the structural and performance facts you need once the edges are settled.

| Construction | Passes / parallel | Online state | Nonce | Tag | Reported speed | Inverse-free? | Best suited for |
|---|---|---|---|---|---|---|---|
| AES-GCM | 1 pass, parallel | `O(1)` | 96-bit | 128-bit | ~1 cpb with AES-NI | Yes | The default, server and client |
| ChaCha20-Poly1305 | 1 pass | `O(1)` | 96-bit | 128-bit | Fast in pure software | Yes | Targets without AES hardware |
| AES-CCM | 2 pass, serial | `O(1)` | 7 to 13 byte | 128-bit (`CCM_8`: 64) | Modest | Yes | Constrained stacks, WPA2 |
| AES-GCM-SIV | 2 pass | `O(n)` buffered | 96-bit | 128-bit | ~0.92 cpb on Broadwell | Yes | Nonce-reuse risk |
| AES-SIV | 2 pass | `O(n)` buffered | None or supplied | 128-bit | Modest | Yes | Key wrap, deterministic AE |
| OCB3 | 1 pass, parallel | `O(1)` | up to 120-bit | up to 128-bit | Fast in software | No (needs AES decrypt) | Elegance (now patent-clear) |
| AEGIS | 1 pass, parallel | `O(1)` | 128 or 256-bit | 128 or 256-bit | ~0.48 cpb (AEGIS-128L) | Yes | Maximum throughput, both endpoints |
| Ascon-AEAD128 | 1 pass | `O(1)` | 128-bit | 128-bit | Small, not server-fast | Yes | New constrained designs |

Reported speeds are platform-dependent and should be read against live cross-platform benchmarks rather than a single headline number; the AEGIS and GCM-SIV figures come from their design papers, and the ECRYPT benchmarking project tracks the rest across many CPUs [@wu2013-aegis][@gl2015-gcmsiv][@bench-aead]. One column earns a second look: OCB3 is the only full-treatment construction that is *not* inverse-free, so it alone needs the AES decrypt circuit in hardware -- the honest cost behind its elegance [@rfc7253].

The tables classify. To *choose*, turn them into a procedure. The flowchart below is the thesis rendered as a decision tree: branch on the nonce guarantee first (it is the edge that fails hardest), then on hardware, and treat commitment as an orthogonal final step because no default provides it.

<Mermaid caption="The which-AEAD decision procedure: branch on the nonce guarantee, then hardware, then handle commitment as a separate add-on">
flowchart TD
    Q1&#123;"Can you guarantee a unique nonce per key?"&#125;
    Q1 -->|No| SIV["AES-GCM-SIV: move on the nonce edge"]
    Q1 -->|Yes| Q2&#123;"AES-NI and CLMUL on both endpoints?"&#125;
    Q2 -->|Yes| GCM["AES-GCM"]
    Q2 -->|No| Q2b&#123;"Server or mobile software, or a constrained device?"&#125;
    Q2b -->|Software| CC["ChaCha20-Poly1305"]
    Q2b -->|Constrained| ASC["Ascon-AEAD128"]
    SIV --> Q3&#123;"Must one ciphertext bind to exactly one key?"&#125;
    GCM --> Q3
    CC --> Q3
    ASC --> Q3
    Q3 -->|Yes| ADD["Add a key-commitment transform, unless it already commits like Ascon"]
    Q3 -->|No| DONE["Ship it"]
</Mermaid>

The argument is now explicit and testable. "Which AEAD?" reduces to "which edge can your deployment *guarantee* it never triggers?" If you cannot guarantee nonce uniqueness, move right on the nonce edge to the SIV family. If you have no AES hardware, move on the hardware edge to ChaCha20-Poly1305 or, for a constrained device, Ascon. If a ciphertext must bind to exactly one key, you must *add* something on the commitment edge, because none of the defaults gives it to you. You can even write the function down.

<RunnableCode lang="js" title="The thesis as code: three edges in, one AEAD out">{`
// "Which AEAD?" is a function of three edges, not a ranking.
function chooseAEAD({ nonceUnique, hasAesHardware, constrained, mustCommitToKey }) {
  let pick;
  if (!nonceUnique) {
    pick = 'AES-GCM-SIV';        // edge 1: cannot guarantee unique nonces
  } else if (hasAesHardware) {
    pick = 'AES-GCM';            // the internet default when AES-NI + CLMUL are present
  } else if (constrained) {
    pick = 'Ascon-AEAD128';      // edge 2: no AES hardware, only a few thousand gates
  } else {
    pick = 'ChaCha20-Poly1305';  // edge 2: no AES hardware, constant-time in software
  }
  // edge 3 is orthogonal: most picks do not commit, so you must ADD a transform --
  // except Ascon, which already commits natively from its sponge (RFC 9771).
  const alreadyCommits = pick === 'Ascon-AEAD128';
  return (mustCommitToKey && !alreadyCommits)
    ? pick + ' + key-commitment transform (this construction does not bind to one key)'
    : pick;
}

console.log(chooseAEAD({ nonceUnique: true,  hasAesHardware: true,  constrained: false, mustCommitToKey: false }));
console.log(chooseAEAD({ nonceUnique: false, hasAesHardware: true,  constrained: false, mustCommitToKey: false }));
console.log(chooseAEAD({ nonceUnique: true,  hasAesHardware: false, constrained: false, mustCommitToKey: false }));
console.log(chooseAEAD({ nonceUnique: true,  hasAesHardware: true,  constrained: false, mustCommitToKey: true  }));
`}</RunnableCode>

<PullQuote>
"Which AEAD should I use?" is not a ranking from worst to best. It is a function: pick the one whose failure mode your deployment can guarantee it will never trigger.
</PullQuote>

The table tells you which edge to move. It does not tell you why you sometimes *cannot* move all of them at once -- why there is no row that is graceful on reuse *and* single-pass *and* fully committing *and* fastest. That absence is not a gap in the engineering. It is a theorem.

## 8. The Limits Are Theorems

Everything so far has been a design choice: move an edge here, pay for it there. Now the hard walls -- the places where no cleverness helps, because a proof says so. There are four, and each maps to an edge; the standard graduate references develop these bounds in full [@boneh-shoup][@katz-lindell].

**GCM's two ceilings, correctly attributed (the nonce edge).** GCM's two limits from SP 800-38D are not conservative engineering guesses; they are where the security proof runs out -- and they come from two *different* mechanisms people constantly merge into one.

The per-message limit of $2^{39}-256$ bits (about 64 GiB) is **32-bit counter-mode block-space exhaustion**, not a GHASH property: with a 96-bit nonce GCM forms the initial counter block $J_0 = \mathrm{IV} \parallel 0^{31} \parallel 1$, the increment function advances only the low 32 bits, so counter mode emits at most $2^{32}-2$ keystream blocks, and $(2^{32}-2)\times 128$ bits $= 2^{39}-256$ bits; exceed it and the counter wraps, repeating a keystream block -- a two-time pad (SP 800-38D Section 5.2.1.1) [@sp80038d].

The per-key cap of roughly $2^{32}$ messages under random 96-bit nonces is a different quantity entirely: the birthday bound on nonce collision, where with $q$ messages the probability of a repeat scales as $q^2 / 2^{96}$, so $q \approx 2^{32}$ keeps it negligible (SP 800-38D Section 8.3) [@sp80038d]. Hoang, Tessaro, and Thiruvengadam proved these multi-user bounds tight, validating the nonce-randomization mechanism TLS 1.3 uses [@htt2018-gcm].

Tag length obeys its own bound: for a one-time Wegman-Carter MAC, forgery probability grows with the number of attempts and shrinks with tag length -- exactly why a 64-bit `CCM_8` tag is a genuine, quantifiable forgery budget rather than a free optimization [@rfc3610].

**Misuse-resistance cannot be online (the nonce edge, again).** This is the deepest limit in the article, and it explains a design decision that otherwise looks like laziness. Rogaway and Shrimpton proved that a deterministic, nonce-misuse-resistant AEAD *cannot* be online or single-pass [@rs2006]. The reason is forced by the definition: to be misuse-resistant, the ciphertext must depend on the *entire* plaintext (otherwise two messages sharing a prefix under a repeated nonce would leak that prefix), so the encryptor cannot emit even the first ciphertext byte until it has read the last plaintext byte. There is no implementation trick around it.

> **Key idea:** You cannot have both streaming and misuse-resistance. It is a theorem, not a missing feature: a misuse-resistant AEAD must read the whole message before it can output any ciphertext. That single impossibility is *why* AES-GCM-SIV is two-pass, and why "just make GCM misuse-resistant without slowing it down" is a request for something that provably does not exist [@rs2006].

**Commitment is an orthogonal axis (the commitment edge).** A conventional CTR-based AEAD like GCM is provably not key-committing -- the property is simply absent from [IND-CPA and INT-CTXT](/blog/secure-against-whom-the-security-definitions-every-protocol-/), so no amount of using GCM "correctly" produces it. Worse, commitment is not one property but a lattice: Bellare and Hoang proved CMT-1 (bind to the key) does not imply CMT-4 (bind to the full context), a separation RFC 9771 later codified [@bh2022-commit][@rfc9771].

And the attacks are cheaper than the naive birthday intuition suggests: Menda and coauthors found context-discovery attacks against CCM, EAX, SIV, GCM, and OCB3, including an $O(2^{n/3})$ attack on SIV using Wagner's k-tree algorithm -- well below the $2^{n/2}$ a birthday bound would suggest [@menda2023].

**Releasing plaintext early is a strictly weaker world (all edges).** The fourth limit is about what your decrypt function is allowed to do before it finishes.

<Definition term="Release of Unverified Plaintext (RUP)">
What an implementation exposes if it emits decrypted plaintext before checking the authentication tag. The formal integrity notion for this setting, INT-RUP, is codified in RFC 9771 Section 4.3.10; security that survives releasing unverified plaintext is strictly stronger than standard AEAD security, and most fast one-pass modes satisfy it only weakly -- which is why the safe API contract is verify-then-release: never act on plaintext until the tag checks out [@rfc9771].
</Definition>

Now assemble the thought experiment. Imagine the ideal AEAD: graceful on nonce reuse *and* fully committing *and* online/single-pass *and* fastest at both the server and constrained extremes. The second limit rules out "misuse-resistant and online" together. The third makes commitment an add-on that the CTR, stream, and welded defaults lack -- Ascon, uniquely, commits natively. The performance extremes pull in opposite directions -- AES round function for servers, a few thousand gates for sensors. You cannot have all of it in one construction, and this is not because nobody has been clever enough. It is because the properties provably conflict.

> **Note:** No single construction closes all three edges at once. That is not a temporary state of the art -- it is a set of theorems about online-ness, commitment, and hardware. The portfolio is not a failure to converge on a winner; it is the mathematically necessary shape of the solution [@rs2006][@bh2022-commit].

So that is settled, provably. Which turns the interesting question inside out. Not "which mode wins?" but "can we make the *robustness* the default instead of the expert's opt-in?" That is exactly where the field is fighting right now.

## 9. Where AEAD Still Bites

The classical problem is closed. For confidentiality and integrity, the bounds are tight and the constructions are vetted. The entire live frontier is about robustness: turning the properties nobody used to ask for into defaults nobody has to remember. Six problems are open, and every one of them has the same shape.

**Committing AEAD by default.** Salamanders and partitioning oracles still bite wherever a committing transform is omitted, which today means almost everywhere [@dodis2018-salamander][@len2021-partition]. The frustrating part is that the fix is cheap: Bellare and Hoang give transforms that add full commitment with no ciphertext-size increase, and Albertini and coauthors give a padding-based alternative [@bh2022-commit][@albertini2022]. Yet as of mid-2026, none is *mandated* by a shipping standard. RFC 9771 gives the field a shared vocabulary for the property but does not require any construction to have it [@rfc9771]. The open question is not "how?" but "why is it still opt-in?"

**Misuse-resistance by default.** If nonce reuse is a recurring operational reality, why is the misuse-resistant mode the escalation rather than the default? The answer is the theorem from Section 8: defaulting to SIV means defaulting to two-pass, non-streaming encryption, and a great deal of infrastructure assumes it can encrypt a stream as it arrives [@rs2006]. Whether that trade is worth making by default is an active argument, not a settled one.

**The release-of-unverified-plaintext trade space.** Between "buffer everything and verify first" and "stream plaintext out immediately" is a design space that streaming media, large-file transfer, and constrained receivers all care about, and the security definitions there -- INT-RUP and its relatives -- are still maturing [@rfc9771].

**Hardware co-design versus conservative margin.** AEGIS already beats AES-GCM on AES-NI hardware, and the appetite for line-rate encryption keeps growing [@wu2013-aegis]. Newer AES-round designs push the throughput frontier even higher, but they trade cryptanalytic maturity for speed, and their standardization status is unsettled -- AEGIS itself is still only an Internet-Draft, not an RFC [@aegis-draft18]. How much margin to spend for how much throughput is an open judgment call.

**[Post-quantum reality](/blog/post-quantum-cryptography-on-windows-the-thirty-year-migrati/), minus the myth.** This one is mostly a matter of correcting a widespread misconception.

<Aside label="Do quantum computers break your AEAD? No.">
For symmetric authenticated encryption the honest answer is: no, and you mostly need to change nothing. Grover's algorithm offers at most a square-root speedup on key search, which halves the effective key length [@grover1996], so a 128-bit key gives about 64 bits of margin against a hypothetical quantum attacker. The remedy is simply to prefer 256-bit keys -- ChaCha20 already uses one, and AES-256 is a configuration flag -- and to size tags with a margin. The post-quantum upheaval lives in key exchange and signatures, not the AEAD record layer, as developed in the post-quantum-cryptography-on-Windows post in this collection. Your record encryption survives the transition largely intact.
</Aside>

**Constant-time without special hardware.** GHASH is hard to implement in constant time without CLMUL, and table-based AES leaks timing without AES-NI -- the exact side-channel pressure that motivated both ChaCha20-Poly1305 and Ascon [@bernstein-chacha][@ascon2021]. On the smallest devices, where neither special instruction exists and power analysis is a live threat, side-channel-resistant AEAD is still an open engineering problem, and it is much of the reason NIST ran a lightweight competition at all.

None of these has a finished answer. But notice the shape of every one: they are all attempts to move an *edge* to a place where the deployer cannot step on it by mistake -- misuse-resistance you do not have to remember, commitment you do not have to add, side-channel safety you do not have to hand-tune. Which brings us back to the only rule that actually travels.

## 10. The Field Guide: Rules and Parameters

Everything above collapses into one default and a short list of deliberate escalations. Follow the ladder and you will never again pick an AEAD by folklore.

> **Note:** Default to **AES-GCM** with a 96-bit nonce that is unique per key (prefer a counter over a random value), a hard cap well under $2^{32}$ messages per key, at most 64 GiB per message, and a full 128-bit tag. Use **ChaCha20-Poly1305** under the same contract when you lack AES hardware. Leave the default only when a specific edge forces you, and only in the direction that edge points [@sp80038d][@rfc8439].

The escalation ladder, each rung mapped to the edge it moves:

- **Cannot guarantee a unique nonce?** Escalate on the nonce edge to **AES-GCM-SIV** [@rfc8452]. Cloned VMs, counters that reset on crash, weak first-boot entropy -- if any of these is in your threat model, the graceful failure is worth the second pass.
- **A stack mandates it, or the device is tiny?** Use **AES-CCM** where WPA2, BLE, or Zigbee require it [@rfc3610], and **Ascon-AEAD128** for *new* constrained designs, now that it is a NIST standard [@sp800232].
- **Deterministic encryption or key wrapping?** Use **AES-SIV**, which needs no nonce at all and is built for exactly this [@rfc5297].
- **You want one-pass, single-primitive elegance?** **OCB3** is now patent-clear, though rarely the right call given how entrenched the defaults are [@rfc7253][@kr2021-ocb].
- **You control both endpoints and need maximum throughput?** **AEGIS** is the fastest option, if you can accept a pre-RFC specification [@aegis-draft18][@wu2013-aegis].
- **Must a ciphertext bind to exactly one key?** *Add* a key-commitment transform -- for password-based encryption, key rotation, message franking, or multi-recipient encryption -- because no default provides it [@bh2022-commit].

[Nonce generation](/blog/predictable-or-repeated-the-only-two-ways-cryptographic-rand/) itself is the subject of Part 2 of this series; do not re-derive it here, but do treat "unique per key" as a hard contract, not a hope. On Windows, the [CNG architecture](/blog/cng-architecture-bcrypt-ncrypt-ksps/) post in this collection shows AES-GCM exposed through the `BCryptEncrypt` API with an authenticated-cipher-mode information structure -- a concrete example of the parameters below appearing in a real API.

Pair the ladder with the support map from Section 6 when you check feasibility: browser JavaScript means AES-GCM through WebCrypto, and a target with no AES hardware means ChaCha20-Poly1305 or, if it is also tiny, Ascon-AEAD128 [@webcrypto].

The exact operational contract, per construction:

| Construction | Nonce | Tag | Per-key limit | Per-message limit | On nonce reuse |
|---|---|---|---|---|---|
| AES-GCM | 96-bit, unique | 128-bit | ~`2^32` msgs (random nonce) | `2^39 - 256` bits, ~64 GiB | Catastrophic |
| ChaCha20-Poly1305 | 96-bit, unique | 128-bit | ~`2^32` msgs (random nonce) | ~256 GiB | Catastrophic |
| AES-CCM | 7 to 13 byte | up to 128-bit (`CCM_8`: 64) | Set by nonce length | Set by length field | Catastrophic |
| AES-GCM-SIV | 96-bit | 128-bit | Improved (per-nonce derived keys) | ~64 GiB | Graceful: message equality |
| AES-SIV | None or supplied | 128-bit | Large | Large | Graceful: message equality |
| OCB3 | up to 120-bit | up to 128-bit | Large | Large | Catastrophic |
| AEGIS | 128 or 256-bit | 128 or 256-bit | Large (wide nonce) | Large | Catastrophic |
| Ascon-AEAD128 | 128-bit | 128-bit | Per SP 800-232 | Per SP 800-232 | Catastrophic |

The only two numeric limits you must hard-code are GCM's, because they are the ones people breach silently: cap messages per key well under $2^{32}$ and messages under 64 GiB each [@sp80038d]. ChaCha20-Poly1305's own ~256 GiB per-message ceiling comes the same way, from its 32-bit block counter over 64-byte blocks ($2^{32}\times 64$ bytes $= 2^{38}$ bytes), per RFC 8439 [@rfc8439]. AES-GCM-SIV's per-nonce key derivation buys better multi-user bounds, which is the whole reason RFC 8452 derives fresh keys rather than reusing one [@bht2018][@rfc8452].

Every rung of that ladder has a mirror image: a misuse pattern that punishes the deployment for stepping on the edge it ignored. Each row below maps a real-code mistake to the named break that catches it.

| Misuse seen in real code | Edge it triggers | Named break |
|---|---|---|
| Reusing a `(key, nonce)` in GCM or AEGIS | Nonce | Nonce-Disrespecting Adversaries, 2016 |
| Assuming an AEAD binds a ciphertext to one key | Commitment | Invisible salamanders; partitioning oracles |
| Truncating the tag to save bytes (`CCM_8`) | Integrity budget | Wegman-Carter forgery bound |
| Treating AES-GCM-SIV reuse as "free" | Nonce | SIV leaks message equality |
| Hand-rolling Encrypt-and-MAC | Composition | Bellare-Namprempre; Krawczyk |
| Conflating GCM's two ceilings | Nonce | The two SP 800-38D limits |

The evidence for each is in the sections above: nonce reuse on live servers [@bock2016], the salamander and its weaponization [@dodis2018-salamander][@len2021-partition], the tag-length forgery budget [@rfc3610], the SIV equality leak [@rfc8452], the composition theorems [@bn2000][@krawczyk2001], and the two ceilings [@sp80038d]. One extra caution on attribution: the live-TLS nonce-reuse break is repeatedly mis-cited to CVE-2016-0270, which actually names IBM Domino and which the NVD itself flags as commonly misapplied to other products [@cve-2016-0270].

<Spoiler kind="hint" label="A five-minute self-audit for the commitment edge">
Search your codebase for any AEAD decryption that runs under an attacker-influenced key: password-based encryption, key wrapping, token decryption, or multi-recipient envelopes. If a decrypt path lets the caller supply or guess the key and then branches on whether decryption succeeded, you are exposed to a partitioning oracle and need a key-commitment transform on top of the AEAD [@len2021-partition][@bh2022-commit].
</Spoiler>

That ladder is your inoculation against folklore. But folklore is sticky, so let us take the most common misconceptions head-on.

## 11. Seven Beliefs That Get Deployments Broken

<FAQ title="Frequently asked questions about choosing an AEAD">
<FAQItem question="Reusing a nonce just weakens things a bit, right?">
No. For every nonce-respecting mode -- AES-GCM, ChaCha20-Poly1305, AES-CCM, OCB3, AEGIS, and Ascon -- a single repeated `(key, nonce)` is an immediate, total break: it leaks the XOR of the two plaintexts, and a second collision hands over the authentication subkey for universal forgery [@joux2006][@bock2016]. Only the SIV family degrades gracefully, and only to leaking message equality [@rfc8452].
</FAQItem>
<FAQItem question="Does AES-GCM-SIV make nonce reuse totally safe?">
No. It makes reuse *survivable*, not free. A repeated nonce still leaks message equality -- an attacker learns that two ciphertexts encrypt the same plaintext -- which can matter a great deal in the right context. Use it as a safety net, not a license to stop managing nonces [@rfc8452][@rs2006].
</FAQItem>
<FAQItem question="Isn't ChaCha20-Poly1305 weaker than AES-GCM, or a mandatory TLS 1.3 cipher?">
No to both misreadings. It is a different trade-off on the hardware edge, not a weaker cipher: constant-time in pure software with no lookup tables, which makes it the *stronger* choice on hardware without AES-NI, where table-based AES leaks timing. And it is not mandatory-to-implement in TLS 1.3 -- it is a *recommended* (SHOULD) cipher suite, while only AES-128-GCM is the MUST, per RFC 8446 Section 9.1 [@rfc8446]. Recommended, not weaker, not mandatory.
</FAQItem>
<FAQItem question="Are random 96-bit GCM nonces safe forever?">
No. Random 96-bit nonces are collision-safe only up to roughly $2^{32}$ messages per key, by the birthday bound. That per-key invocation cap is a different number from the per-message limit of about 64 GiB; enforce both, and prefer a counter over a random nonce when you can [@sp80038d][@htt2018-gcm].
</FAQItem>
<FAQItem question="Doesn't authenticated mean a ciphertext decrypts only one way?">
No. Most AEADs are not key-committing. One AES-GCM ciphertext can be built to decrypt to two different meaningful plaintexts under two different keys, with the tag valid both times -- the invisible-salamanders result. If a ciphertext must bind to one key, add a commitment transform [@dodis2018-salamander][@bh2022-commit].
</FAQItem>
<FAQItem question="Is AEGIS the best because it is the newest and fastest?">
No. AEGIS leads on raw throughput, but it is nonce-respecting (catastrophic on reuse), not fully key-committing, and still an active Internet-Draft rather than an RFC -- it states plainly that it "is not a standard" and expires on 8 April 2026. Fastest is not the same as best for your deployment [@aegis-draft18][@wu2013-aegis].
</FAQItem>
<FAQItem question="Do I need to replace my AEAD for post-quantum security?">
No. Symmetric authenticated encryption survives the quantum transition. Grover's algorithm only halves effective key length [@grover1996], so prefer 256-bit keys and size tags with margin. The post-quantum upheaval is in key exchange and signatures, not the AEAD record layer. Separately, note that NIST's Ascon-AEAD128 is a tweaked variant of the CAESAR Ascon-128, not byte-identical [@sp800232].
</FAQItem>
</FAQ>

## The Function, Not the Ranking

Seven ciphers, one interface, three edges. Every break here was a deployment triggering an edge its designers deliberately moved elsewhere. The invisible salamanders triggered the commitment edge that AEAD never promised to close [@dodis2018-salamander]. The 184 TLS servers triggered the nonce edge that GHASH cannot survive [@bock2016]. The `CCM_8` forgery budget is the tag-length edge priced in bits [@rfc3610]. The SIV equality leak is the residue of the one edge SIV *does* close -- even the fix has a seam [@rfc8452]. And OCB3's near-total absence is the patent grave, an edge that was never technical at all [@kr2021-ocb].

Put them together and the thesis is earned rather than asserted. "Which AEAD should I use?" is not a ranking from worst to best, because Section 8 proved there is no best -- no single construction can be misuse-resistant *and* single-pass *and* fully committing *and* fastest at once. It is a function: pick the construction whose failure mode your deployment can *guarantee* it will never trigger.

Master the three edges and you can place any construction on the map, predict any misuse before it ships, and evaluate whatever the next competition invents -- key-derivation-bound AEADs, the TLS record layer's next mode, or a lightweight winner that does not exist yet. The names will change. The edges will not.

<StudyGuide slug="the-aead-decision-matrix" keyTerms={[
  { term: "AEAD", definition: "One keyed call giving confidentiality, plaintext integrity, and associated-data integrity" },
  { term: "Associated Data", definition: "Header bytes authenticated but not encrypted, travelling in the clear" },
  { term: "Nonce", definition: "A value that must be unique per key for a nonce-respecting mode" },
  { term: "MRAE", definition: "Misuse-resistant AE, where nonce reuse leaks only message equality" },
  { term: "Wegman-Carter one-time MAC", definition: "A tag of the form keyed-hash plus one-time mask, the shared root of GHASH and Poly1305" },
  { term: "GHASH", definition: "GCM's linear universal hash at a secret point, recovering which forges tags" },
  { term: "Synthetic IV (SIV)", definition: "An IV derived as a MAC of the whole message, so the tag is the IV" },
  { term: "Key commitment", definition: "Binding a ciphertext to one key (CMT-1) up to the full context (CMT-4)" },
  { term: "Sponge", definition: "One permutation that absorbs input and squeezes keystream and tag, as in Ascon" },
  { term: "Inverse-free", definition: "A decryption path that never calls the block-cipher inverse, true of the CTR, stream, and sponge modes but not OCB3" },
  { term: "RUP", definition: "Release of Unverified Plaintext, emitting plaintext before the tag is checked" }
]} questions={[
  { q: "What are the three edges that decide an AEAD choice?", a: "The nonce contract, the performance and hardware profile, and commitment." },
  { q: "Why is a repeated nonce catastrophic in AES-GCM?", a: "It reuses the one-time Wegman-Carter mask, leaking the plaintext XOR and, with a second collision, the GHASH subkey for forgery." },
  { q: "Why can a misuse-resistant AEAD not be single-pass?", a: "Its ciphertext must depend on the whole message, so it must read the last plaintext byte before emitting any ciphertext, a Rogaway-Shrimpton theorem." },
  { q: "Does authenticated mean a ciphertext binds to one key?", a: "No. Commitment is an orthogonal axis, and most AEADs are not key-committing by default." }
]} />
