← Back to news
An encrypted data stream passing through a glowing authentication-tag gate

Why So Much Traffic Uses AES-GCM — and What Its Authentication Tag Proves

You have almost certainly used AES-GCM today. It protects traffic in TLS, IPsec, and many cloud APIs. It does double duty: it encrypts data and attaches an authentication tag that lets the receiver detect modification before accepting the plaintext. That integrity check is the whole point.

Part 1. What AES actually does (barely)

AES is a block cipher: a fixed transformation that turns 16 bytes of plaintext into 16 bytes of ciphertext using a secret key, and back again if you have the key. On its own it does exactly one block at a time. To encrypt a long message you need a mode that chains the blocks together — CBC with its IV, or CTR, the mode GCM is built on. CTR mode turns AES into a counter-based stream generator: encrypt counter block 1, XOR it with your first 16 bytes; encrypt counter block 2, XOR with the next 16 bytes; and so on. The result is malleable in the worst way: an attacker who can edit the ciphertext flips exactly the same bytes in the plaintext when it's decrypted.

That malleability is what CTR is for — random access and streaming make it a workhorse. But it means the ciphertext says nothing about its integrity. Nobody can tell whether the message arrived complete, unaltered, and from the party who signed it. That's the gap GCM closes.

Part 2. The trick: encrypt with CTR, tag with GHASH

GCM works in two layers simultaneously. The CTR stream encrypts the plaintext as usual. In parallel, a function called GHASH chugs through the ciphertext (and optionally some AAD you hand it), producing a 128-bit authentication tag appended to the end of the ciphertext. Decryption does the math in reverse and checks the tag before it trusts a single byte.

The tag isn't random noise. It's computed from a synthetic counter J0 derived from your nonce, then XORed in. That means the tag is bound to the key, the nonce, the ciphertext, and whatever AAD you bound in. Change one bit of any of those, the tag no longer matches and decryption aborts.

Part 3. AAD: the binding you never think about

Authenticated encryption has an underrated feature: additional authenticated data (AAD). You feed AAD into GHASH without encrypting it. The tag then guarantees the AAD wasn't tampered with, even though it was sent in the clear.

TLS uses AAD for the packet headers; JWTs use the signing header as AAD; protocol designers use it to bind version numbers, channel IDs, and session context into the tag. This is what stops a classic cut-and-paste attack: take a valid encrypted message from session A, replay it in session B. The header says session B, but the tag was computed for session A's header — it fails. AAD is the glue that keeps a ciphertext honest about where it belongs.

Part 4. The one rule: never reuse a nonce under the same key

Every authenticated-encryption scheme lives and dies by its nonce rule. GCM's nonce is typically 96 bits (12 bytes). J0 is derived from it, so reusing a nonce under the same key makes two ciphertexts share the same GHASH counter base. Two consequences follow:

  • CTR reuse gives the keystream: XOR two ciphertexts together and you recover the XOR of two plaintexts — a crib-dragging nightmare.
  • GHASH reuse gives the authentication key: two tags, one unknown key, one linear solve. Once you have the key, you can forge valid tags for anything under that key.

This is why real-world GCM implementations use a deterministic counter in the nonce (increment per message, never repeat) and rotate keys when the counter wraps. It's why a cloud API that reuses a nonce across requests is catastrophically broken. It's also why “nonce” must not be a timestamp or a random value you might repeat — it must be unique per key, period.

Part 5. Where you already meet it

TLS 1.3 requires compliant implementations to support TLS_AES_128_GCM_SHA256; it also defines AES-256-GCM, ChaCha20-Poly1305, and AES-CCM suites. The record sequence number contributes to the per-record nonce, while the record header is authenticated as AAD. Wi-Fi security and VPN protocols use several authenticated-encryption constructions depending on the profile. In IPsec ESP, RFC 4106 specifies AES-GCM and authenticates protocol context including the SPI and sequence number as AAD. The recurring pattern is the same: encrypt the payload, authenticate it, and bind the surrounding protocol context.

It's become the default because the 128-bit tag is fast to compute in hardware (GHASH maps beautifully onto AES-NI and GPU-style parallelism), it's a single pass over the data, and it composes cleanly with AAD. The old “encrypt-then-MAC” construction, where you run AES-CBC and then HMAC-SHA256 over the ciphertext, is still secure but costs two passes and a hash — and it's what GCM replaced.

The mental model

What the tag actually guarantees
  • The ciphertext is bound to a key, a nonce, and the AAD you supplied.
  • One bit flipped in the ciphertext or the tag and the math doesn't match — decryption aborts.
  • Change the AAD and the tag fails, even if the ciphertext is untouched. That's what stops replay and cut-and-paste.
  • Reusing a nonce under the same key breaks both the keystream and the tag — it's the one rule that matters more than the rest.
More from the wire

More on the way.