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.
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 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.
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.
- 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.
- 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.
- 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
- AES
- Encryption
- Cryptography
- GCM
- CBC
Tools mentioned in this article
- AES-256 Encrypt / Decrypt Online - Free, In-Browser - Encrypt and decrypt text with AES-128, AES-192, or AES-256 in GCM, CBC, or CTR mode. PBKDF2 key derivation, entirely in your browser.
- Hash Generator - Generate SHA-1, SHA-256, SHA-384 and SHA-512 hashes from text.
- Random String Generator - Generate random strings with configurable length and character set.
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.