AES-GCM vs AES-CBC
July 24, 2026 · 15 min read
AES encrypts fixed 128-bit blocks, but real data is longer. A mode of operation chains blocks together. CBC (Cipher Block Chaining) XORs each plaintext block with the previous ciphertext before encryption. GCM (Galois/Counter Mode) combines counter-mode encryption with built-in authentication (AEAD).
Modern applications prefer AES-GCM (or ChaCha20-Poly1305) because CBC alone does not detect tampering - you must add HMAC separately. Getting “encrypt-then-MAC” order wrong with CBC has caused high-profile vulnerabilities.
What block modes are
A raw AES block cipher maps 16 bytes to 16 bytes with a key. Modes repeat that operation across messages with IVs/nonces and chaining rules. Never reuse an IV/nonce with the same key - especially in GCM, where reuse can leak the authentication key and plaintext.
Key length: AES-128, AES-192, or AES-256. AES-256 is common for long-term secrets; AES-128 is often enough when keys rotate regularly.
AES-CBC
CBC needs a random, unpredictable IV for the first block. PKCS#7 padding extends plaintext to a multiple of 16 bytes. Decryption without authentication is dangerous - padding oracle attacks (Vaudenay, Lucky Thirteen) targeted TLS when MAC verification was mishandled.
CBC encryption:
C[0] = E(K, P[0] XOR IV)
C[i] = E(K, P[i] XOR C[i-1])
Requires separate MAC (e.g. HMAC-SHA256) for integrity.
AES-GCM
GCM is an AEAD: Authenticated Encryption with Associated Data. It outputs ciphertext plus an authentication tag (often 128 bits). Tampering fails verification before decryption returns plaintext. Associated data (headers, version bytes) can be authenticated without encrypting it.
import { randomBytes, createCipheriv } from "node:crypto";
const key = randomBytes(32);
const nonce = randomBytes(12); // 96-bit nonce for GCM
const cipher = createCipheriv("aes-256-gcm", key, nonce);
// ... update, final, cipher.getAuthTag()
Side-by-side comparison
- Integrity - GCM built-in; CBC needs separate MAC.
- Parallelism - GCM encrypts faster in parallel; CBC decryption is sequential.
- Nonce - GCM: unique nonce per message; CBC: random IV per message.
- TLS 1.3 - prefers AEAD suites (AES-GCM, ChaCha20-Poly1305).
Legacy systems (older PKCS#7 envelopes, some disk encryption) still use CBC. When you maintain them, enforce encrypt-then-MAC and use constant-time MAC verification.
What to choose
Default to AES-256-GCM for application-level encryption of tokens, PII fields, and session blobs. Use vetted libraries only; do not invent hybrid modes. For file encryption at rest, consider age, libsodium, or KMS envelope encryption rather than hand-rolled CBC.
If a standard mandates CBC (some HSM interfaces), add explicit HMAC over ciphertext and IV, document wire format, and test tamper rejection.
FAQ
- Is AES-CBC insecure?
- Not if you authenticate ciphertext (encrypt-then-MAC) and use random IVs. Unauthenticated CBC is risky.
- Can I reuse a GCM nonce with the same key?
- Never. Nonce reuse in GCM is catastrophic. Use random 96-bit nonces or a counter with a unique key per scope.
- GCM vs ChaCha20-Poly1305?
- Both are modern AEADs. ChaCha20-Poly1305 excels on devices without AES hardware acceleration.
- Do I need HMAC if I use GCM?
- No separate HMAC for the encrypted payload - GCM’s tag provides integrity. Still authenticate protocol metadata as needed.
Related: Encryption vs encoding