skip to content

When choosing between AES-CBC and AES-GCM in Java, what are the trade-offs, and what must you add to CBC to make it safe?

level: seniorimportance: should knowfreq 40%

answer

  1. GCM = confidentiality + integrity (AEAD); CBC = confidentiality only
  2. CBC alone → padding-oracle + bit-flipping
  3. Safe CBC = encrypt-then-MAC, separate MAC key
  4. Verify MAC in constant time before decrypt
  5. GCM nonce reuse is catastrophic; CBC IV must be unpredictable

basics

~20 s

GCM gives encryption plus built-in integrity in one step and is the default choice. CBC only encrypts — it has no integrity check — so by itself it is vulnerable to tampering and padding-oracle attacks. If you must use CBC, you have to add a separate MAC (encrypt-then-MAC). Both need a unique IV per message.

solid answer

~40 s

AES-GCM is authenticated encryption: one pass gives confidentiality and integrity, with a tag verified on decrypt, and it's parallelizable and fast. AES-CBC provides confidentiality only — no integrity — which exposes it to bit-flipping and, classically, padding-oracle attacks where decrypt-time padding errors leak plaintext. So CBC alone is unsafe for untrusted data. To use CBC securely you must add a MAC over the ciphertext using encrypt-then-MAC (compute HMAC over IV+ciphertext, verify it in constant time before decrypting), and use a separate MAC key. Both modes require a unique, unpredictable IV per message (16 bytes for CBC, 12-byte nonce for GCM); GCM's nonce-reuse penalty is far more catastrophic. CBC also needs padding (PKCS5), GCM uses NoPadding. Default to GCM; reach for CBC+HMAC only for legacy interop or specific constraints, and always authenticate.

code

java · 12 lines
java
// Legacy CBC done safely: encrypt-then-MAC with separate keys
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16];
SecureRandom.getInstanceStrong().nextBytes(iv);
c.init(Cipher.ENCRYPT_MODE, encKey, new IvParameterSpec(iv));
byte[] ct = c.doFinal(plaintext);

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(macKey);                 // SEPARATE key from encKey
mac.update(iv);
byte[] tag = mac.doFinal(ct);     // authenticate IV || ciphertext
// transmit: iv || ct || tag ; on receive verify tag (MessageDigest.isEqual) BEFORE decrypt

go deeper

for a junior

Knows GCM is the safer default and that CBC alone doesn't protect against tampering.

for a middle

Explains that CBC lacks integrity, picks GCM for new code, and knows both need a unique IV.

for a senior

Details padding-oracle/bit-flipping risks, implements CBC safely via encrypt-then-MAC with separate keys and constant-time verification, and reasons about IV/nonce rules.

for a principal

Defines org crypto standards (AEAD-by-default, key separation, nonce strategy, misuse-resistant modes) and reviews protocols for integrity and oracle exposure.

## The core distinction: integrity Both modes turn AES into something usable on multi-block messages, but they differ in **what guarantees** they give. - **CBC (Cipher Block Chaining)** — **confidentiality only.** Each plaintext block is XORed with the previous ciphertext block before encryption, seeded by a random **IV**. An attacker who can't read the data can still **modify** it: flipping a bit in ciphertext block *n* flips the corresponding bit in plaintext block *n+1* (with garbage in block *n*). CBC also requires **padding**, which opens the door to **padding-oracle attacks**: if the system behaves differently on a padding error vs. a valid-padding-but-wrong-content error, an attacker can decrypt the message byte by byte without the key. - **GCM (Galois/Counter Mode)** — **authenticated encryption (AEAD).** It encrypts (CTR-style, no padding) *and* produces a 128-bit **authentication tag** verified at decryption. Any tampering yields `AEADBadTagException` and no plaintext. It also supports **AAD** (authenticate-but-don't-encrypt extra context). ## Why GCM is the default - One construction, one key, integrity included — fewer ways to get it wrong. - Parallelizable and hardware-accelerated (AES-NI + PCLMULQDQ), so typically faster than CBC+HMAC. - Defeats bit-flipping and padding-oracle attacks because tampered ciphertext fails the tag check before decryption is trusted. ## Making CBC safe: encrypt-then-MAC If you genuinely need CBC (legacy interop, a protocol that mandates it), you must add integrity yourself. The correct, robust order is **encrypt-then-MAC (EtM)**: 1. Encrypt with AES-CBC and a random IV → ciphertext. 2. Compute `HMAC-SHA-256(IV || ciphertext)` with a **separate MAC key** (never the encryption key). 3. Transmit `IV || ciphertext || tag`. On receive: **verify the HMAC in constant time first**; only if it matches do you decrypt. This neutralizes padding oracles (you never reach the padding check on tampered data) and bit-flipping. Doing it in the wrong order (MAC-then-encrypt or encrypt-and-MAC) reintroduces oracle risks. Comparing the tag must be **constant-time** (`MessageDigest.isEqual`) to avoid timing leaks. ## IV / nonce rules - **CBC**: IV must be **random and unpredictable** per message (a predictable IV enables chosen-plaintext attacks like BEAST). 16 bytes. Not secret — prepend it. - **GCM**: 12-byte **nonce**, unique per (key); reuse is catastrophic (keystream reuse + tag forgery). Random or counter-based. ## Padding - **CBC** uses `PKCS5Padding`. - **GCM** uses `NoPadding` (it's a stream mode). ## Decision guide - New code, you control both ends → **AES-GCM** (or a misuse-resistant AEAD like AES-GCM-SIV if your provider offers it, when nonce uniqueness is hard to guarantee). - Must interop with a system that only speaks CBC → **AES-CBC + HMAC (encrypt-then-MAC), separate keys, constant-time verify, random IV.** - Never ship **CBC without a MAC** for data crossing a trust boundary.

  • What is a padding-oracle attack and why does GCM avoid it?
    In CBC, decryption checks padding validity; if the system reveals (via error, timing, or behavior) whether padding was valid, an attacker can iteratively recover plaintext byte by byte without the key. GCM has no padding and verifies an authentication tag before yielding plaintext, so tampered ciphertext is rejected outright — there's no padding step to probe.
  • Why must the MAC use a different key than the cipher, and why encrypt-then-MAC specifically?
    Key separation prevents interactions/attacks where reusing one key across two primitives weakens both. Encrypt-then-MAC authenticates the actual ciphertext, so you can reject tampering before any decryption/padding logic runs — the order proven to give the strongest (ciphertext-integrity) guarantee.
  • When might AES-GCM-SIV be preferable to AES-GCM?
    When you cannot guarantee nonce uniqueness (e.g. distributed encryptors, no shared counter). GCM-SIV is nonce-misuse-resistant: reusing a nonce only leaks whether two plaintexts are identical, instead of catastrophically breaking confidentiality and integrity.

saying these in an interview costs you the question

  • Shipping AES-CBC with no integrity protection
  • Using the same key for AES and the HMAC
  • MAC-then-encrypt or encrypt-and-MAC instead of encrypt-then-MAC
  • Comparing MAC/tags with a non-constant-time equals (timing leak)
  • Predictable or counter IVs for CBC
  • Believing CBC's IV provides integrity

context