Skip to main content
Security & Privacy

AES-GCM vs AES-CBC: Which Mode to Use and Why

What block cipher modes do, why GCM replaced CBC for new code, what nonce reuse actually leaks, and the NIST limits that make it a requirement rather than advice.

By 7 min read
Article title card. Two rows of cipher blocks on a dark grid, the lower row ending in an amber block labelled tag, with the line: one mode authenticates, one does not

AES encrypts 16 bytes. Everything longer needs a mode of operation wrapped around it, and the mode is where the security properties actually live.

Two of them turn up constantly: CBC and GCM. They are not interchangeable, and picking the wrong one produces code that passes every test and quietly loses a property nobody notices is missing.

Why modes exist at all

Split your data into 16-byte blocks, encrypt each independently, concatenate. That is ECB, and it fails visibly: identical plaintext blocks give identical ciphertext blocks, so structure survives encryption.

Every other mode exists to fix that, and then to fix what comes next.

  • CBC XORs each plaintext block with the previous ciphertext block before encrypting. An initialization vector breaks the pattern for the first block.
  • GCM runs AES as a counter-mode stream cipher and computes an authentication tag over the result.

What each mode puts on the wire

CBC emits an unpredictable IV plus padded ciphertext and needs a separately applied HMAC that a developer can forget. GCM emits a nonce, ciphertext the same length as the plaintext, and an authentication tag from the same construction
The difference is not cipher strength. It is how many pieces you have to assemble correctly.

CBC needs three things to be safe and gives you two. The IV must be unpredictable, not merely unique, because a predictable IV lets an attacker mount a chosen-plaintext attack. The plaintext must be padded to a multiple of 16, conventionally with PKCS#7. And the ciphertext must be authenticated by a separate HMAC in an encrypt-then-MAC construction, using a separate key, in a step nothing forces you to write.

Two failure modes follow directly:

Padding oracles. If the decrypt path reveals whether padding was valid, through an error message, a status code or a timing difference, an attacker recovers plaintext one byte at a time without the key. The canonical production case is the 2010 ASP.NET vulnerability3, and it was not the first.

Malleability. Without the MAC, flipping a bit in the ciphertext flips the corresponding bit in the plaintext. The recipient decrypts something the sender never wrote and has no way to know.

GCM has one moving part fewer. Counter mode means the ciphertext is exactly as long as the plaintext, so no padding exists to attack. The tag comes out of the same call as the ciphertext, so it cannot be forgotten. And on any modern CPU it is faster than CBC plus HMAC-SHA-256, because both halves are hardware accelerated.

For a working implementation, our AES Encrypt/Decrypt does GCM, CBC and CTR at 128, 192 or 256 bits, entirely in the page. It takes text rather than files, derives the key from your passphrase with PBKDF2, and returns one base64 blob containing the salt, the IV and the ciphertext rather than showing you the fields separately.

The one sharp edge

Encrypt two different messages with the same key and the same nonce and GCM does not weaken. It collapses.

Two messages encrypted with AES-256-GCM under the same key and nonce. The ciphertexts are identical except where the plaintexts differ, the XOR of the ciphertexts equals the XOR of the plaintexts, and knowing one message recovers the other
Run with Node's crypto module. Nothing here is a theoretical attack.

Because the keystream depends only on the key and the nonce, reusing both means XORing two plaintexts with the same keystream. The XOR of the ciphertexts is therefore the XOR of the plaintexts, with the key cancelled out entirely. We encrypted "Transfer 100 EUR to Alice" and "Transfer 900 EUR to Mallory" under one key and one nonce: the ciphertexts came out identical except at the single byte where the amounts differ, and XORing in the first message returned the second in plaintext.

Forgery follows too. Nonce reuse leaks enough about the GHASH subkey to let an attacker produce new messages that pass the tag check.

NIST states the requirement flatly: the probability of ever invoking the encryption function with the same IV and key must be no greater than 2^-32, and "in practice this requirement is almost as important as the secrecy of the key"1.

The equivalent CBC mistake is bad and survivable: reusing an IV reveals whether two messages share a prefix, and nothing more.

Staying on the right side of it

Two constructions, and you must pick exactly one per key1.

Random 96-bit nonces from a real CSPRNG. Collisions follow the birthday bound, so the ceiling is not "when you feel uncomfortable": NIST caps total invocations per key at 2^321. That is a hard limit, not a conservative one, and it belongs on your key-rotation trigger.

Counter-based nonces, where a fixed field identifies the device and an invocation field increments per message. Never reset the counter without rotating the key. For clients that retry over bad networks, this is the more defensible choice, because a retry that re-encrypts is exactly how random-nonce systems accidentally repeat.

Generate keys and nonces from a cryptographic source: crypto.randomBytes in Node, secrets.token_bytes in Python, SecureRandom in Ruby. Our Random String Generator uses crypto.getRandomValues, the same primitive WebCrypto uses internally.

Choosing

  • GCM for new work. Network protocols, file encryption, anything where you want confidentiality and integrity from one primitive.
  • CBC plus HMAC-SHA-256 only to interoperate with something that already speaks it, or where compliance pins you.
  • Never CBC alone across a trust boundary.
  • Never ECB.

The honest summary is a footgun count. CBC has three: predictable IVs, padding oracles, and a MAC someone forgot. GCM has one, and unlike the others it is loud once you know to look for it.

Key sizes

AES takes 128, 192 or 256-bit keys, and both modes accept any of them unchanged. AES-128 is sound against classical attacks. Grover's algorithm would halve effective symmetric security, notionally putting AES-128 at 64 bits and AES-256 at 128 against a large quantum computer that does not exist yet. The cost difference between them is small enough that AES-256 is the sensible default, and several compliance regimes require it regardless.

Rotate when the invocation ceiling approaches, when a device or credential is compromised, or on a schedule. A year is typical for long-lived keys; session keys should be ephemeral.

For comparing fingerprints rather than decrypting anything, the Hash Generator covers SHA-256 and its relatives. Different primitive, adjacent job.

What the protocols decided

You rarely choose a mode by hand, because the protocol chose already.

  • TLS 1.3 removed CBC entirely. Every cipher suite it defines is AEAD2.
  • TLS 1.2 still permits AES-CBC suites, and they are being disabled steadily.
  • OpenSSH defaults to GCM and ChaCha20-Poly1305 for modern connections.
  • Cloud KMS services use authenticated modes internally.

Every protocol that has revisited this question has landed on authenticated encryption. That convergence is a better argument than any individual property.

The bottom line

CBC is a mode that needs three things done right and lets you ship with two. GCM needs one thing done right and complains loudly about the rest. Pick GCM, put nonce management on the checklist next to key rotation, and leave working CBC-plus-HMAC code alone until a planned rotation gives you a clean moment to migrate.

Sources

Every number in this article traces to a source below. Where a claim could not be sourced, it was cut rather than softened.

  1. Primary sourceNIST

    The uniqueness requirement in section 8, that the probability of ever invoking the encryption function with the same IV and key shall be no greater than 2 to the minus 32 and that this is almost as important as the secrecy of the key; the constraint in section 8.3 capping invocations per key at 2 to the 32nd; and the 96-bit IV construction in which the counter block is the IV followed by the counter.

  2. Primary sourceIETF

    That TLS 1.3 cipher suites are all AEAD constructions, with AES-GCM and ChaCha20-Poly1305 defined and CBC-based suites removed entirely.

  3. Primary sourceMicrosoft

    The 2010 ASP.NET padding oracle vulnerability, which is the best-known production instance of a decrypt path leaking whether CBC padding was valid.

Topics

Tools mentioned in this article

Get new tools by email

New tools and the occasional deep-dive, about once a month. No spam, no sharing your address, unsubscribe in one click.

Related articles

Article title card. Two pairs of boxes, the upper joined by a single amber arrow and the lower by arrows in both directions, with the line: one of these has no way back
Security & Privacy

Hashing vs Encryption vs Encoding: What People Keep Confusing

Three transformations that all produce gibberish and solve different problems, with the measured cost of picking the wrong one for passwords.

Article title card. A shield with its right half filled in amber, with the line: what leaves the machine, and when
Security & Privacy Guide

Online Privacy Guide: Threat Models for Browser-Based Work

Threat models worth naming, the thirty-second check that beats any privacy policy, and an honest list of which of our own tools upload your file.

Article title card. Six small grey dots standing for a typed password beside a set of amber concentric rings, with the line: nothing to type, nothing to steal
Security & Privacy

Passkeys vs Passwords: How WebAuthn Actually Replaces the Password

How passkeys, FIDO2 and WebAuthn actually work, why origin scoping ends phishing, and the tradeoffs around recovery and syncing that still bite.