🔐 encrypt.tools
SYMMETRIC · AES

AES-GCM vs CBC vs CTR vs ECB: Which AES Mode Should You Use?

AES is only as safe as its mode. Compare ECB, CBC, CTR and GCM — how each works, how each fails, and why AES-GCM (or ChaCha20-Poly1305) is the right default in 2026.

By ··7 min read

Key takeaways

  • Use AES-GCM (or ChaCha20-Poly1305) for new designs. Both are authenticated: they encrypt *and* detect tampering in one step.
  • Never use ECB — identical plaintext blocks produce identical ciphertext blocks, leaking patterns.
  • CBC and CTR are not authenticated. CBC without a MAC enables padding-oracle attacks; CTR ciphertext can be edited bit by bit. Only use them with a separate MAC, or for compatibility.
  • GCM's one hard rule: never reuse a nonce with the same key. Reuse leaks the XOR of the two plaintexts and lets an attacker forge messages. If you can't guarantee unique nonces, use AES-GCM-SIV or XChaCha20-Poly1305.
  • AES-128 and AES-256 are both unbroken. AES-256 gives extra margin against future quantum computers and costs only ~40% more time.

AES itself only knows how to encrypt one 16-byte block with a key. Real messages are longer than 16 bytes, so every use of AES wraps it in a mode of operation that decides how blocks are chained, whether padding is needed, and whether tampering is detected. Most real-world AES failures — from leaked images to decrypted cookies — come from the mode, not from AES.

AES modes compared
ModeAuthenticated?Needs padding?IV / nonce ruleVerdict
ECBNoYesNone (that's the problem)Never use
CBCNoYes (PKCS#7)Random and unpredictableLegacy; only with encrypt-then-MAC
CTRNoNoUnique per key, never repeatBuilding block; add a MAC
GCMYes (128-bit tag)NoUnique 96-bit nonce per keyRecommended default
GCM-SIVYesNoRepeat is survivableUse when nonces may repeat

ECB: the mode you should never use

Electronic Codebook mode encrypts each 16-byte block independently with the same key. It is the obvious, naive construction — and it is broken by design: identical plaintext blocks always produce identical ciphertext blocks. Encrypt a bitmap image with ECB and the outline of the image remains clearly visible in the ciphertext, because every run of identical pixels encrypts to the same pattern.

ECB also lets attackers cut and paste blocks between messages. If a token encrypts role=user in one block, swapping in a block from another token can change it. There is no legitimate reason to use ECB for data longer than one block. If a library defaults to ECB (some Java and PHP APIs historically did when you asked for plain "AES"), override it.

CBC: chained blocks, no integrity

Cipher Block Chaining XORs each plaintext block with the previous ciphertext block before encrypting it. The first block is XORed with a random initialization vector (IV). Chaining hides repeated blocks, which fixes ECB's leak.

CBC has three practical weaknesses:

  • Padding. Messages must be padded to a multiple of 16 bytes (usually PKCS#7). If a server reveals — through an error message or even a timing difference — whether the padding was valid after decryption, an attacker can decrypt the whole message one byte at a time. This padding oracle attack (Vaudenay, 2002) broke ASP.NET, Java Server Faces and others, and variants like POODLE and Lucky Thirteen hit TLS.
  • No integrity. Flipping a bit in ciphertext block *n* flips the same bit in plaintext block *n+1*, letting attackers make targeted edits.
  • Predictable IVs are dangerous. TLS 1.0 used the last ciphertext block as the next IV, which enabled the BEAST attack. The IV must be random and unpredictable.

CBC is still safe when combined with a MAC computed over the ciphertext (encrypt-then-MAC), and verified before any decryption happens. But at that point you are hand-assembling what GCM gives you for free.

CTR: a stream cipher made from AES

Counter mode encrypts a sequence of counter values — nonce‖0, nonce‖1, nonce‖2… — to produce a keystream, then XORs the keystream with the plaintext. It needs no padding, encryption and decryption are the same operation, and blocks can be processed in parallel.

Like every stream cipher, CTR has two sharp edges. First, a nonce must never repeat under the same key: two messages encrypted with the same keystream XOR together to cancel it, leaving P1 ⊕ P2, which is often enough to recover both. Second, it is fully malleable: flipping bit *i* of the ciphertext flips exactly bit *i* of the plaintext. If an attacker knows a message says amount=0100, they can change it to amount=9100 without the key. CTR needs a MAC.

GCM: CTR plus authentication

Galois/Counter Mode is CTR-mode encryption combined with GHASH, a fast polynomial MAC, producing a 128-bit authentication tag. On decryption the tag is checked first; if a single bit of the ciphertext, the nonce or the associated data has changed, decryption fails instead of returning tampered plaintext. That is what AEAD — authenticated encryption with associated data — means.

GCM is the default in TLS 1.3 (TLS_AES_128_GCM_SHA256 and TLS_AES_256_GCM_SHA384), in SSH, IPsec, and most cloud KMS services. On CPUs with AES-NI and carry-less multiply instructions it runs at several gigabytes per second per core.

The nonce rule, and what happens if you break it

GCM uses a 96-bit nonce. If the same key and nonce ever encrypt two different messages, the consequences are worse than for CTR: the attacker learns P1 ⊕ P2 *and* can solve for the GHASH authentication key, after which they can forge valid tags for arbitrary ciphertexts. This "forbidden attack" has been found in real TLS servers that reused nonces.

Two safe ways to generate nonces:

  • Random 96-bit nonces — fine as long as you stay under about 2³² messages per key (NIST SP 800-38D's limit). At that point the chance of any collision is around 1 in 10 billion; past it, the birthday bound starts to bite. Rotate keys well before.
  • A counter — guaranteed unique, but you must never lose state (a VM snapshot restore or two servers sharing a key can repeat counters).

Other GCM limits worth knowing: a single message can be at most about 64 GB, and you should keep the full 128-bit tag — truncated tags weaken forgery resistance.

AES-128 vs AES-256

Both key sizes are unbroken; the best known attacks shave only a couple of bits off. AES-256 uses 14 rounds instead of 10, so it is roughly 40% slower — usually irrelevant next to network or disk speed. The main reason to choose AES-256 today is quantum margin: Grover's algorithm would, in theory, halve the effective key length, leaving AES-256 at a comfortable 128-bit security level. See our post-quantum cryptography guide for why symmetric crypto is the part that *doesn't* need replacing.

What about ChaCha20-Poly1305?

ChaCha20-Poly1305 is the other AEAD in TLS 1.3. It offers the same security level as AES-256-GCM, is faster on devices without AES hardware (older phones, small microcontrollers), and is naturally constant-time in software. Its nonce rules are the same as GCM's; the extended XChaCha20 variant removes the nonce-size worry. If you are choosing between AES-GCM and ChaCha20-Poly1305, either is a good answer.

A practical decision guide

  • Writing new code? Use your platform's AEAD: AES-256-GCM via Web Crypto, libsodium's crypto_aead_xchacha20poly1305_ietf, or Go's crypto/cipher.NewGCM. Better still, use a high-level library (libsodium, Tink, age) that makes the nonce choice for you.
  • Interoperating with a legacy system that requires CBC? Use a random IV, encrypt-then-MAC with HMAC-SHA-256, compare tags in constant time, and return a single generic error on any failure.
  • Encrypting disks or storage sectors? Use XTS mode — it is designed for fixed-size sectors where there is nowhere to store a nonce or tag.
  • Deriving the key from a password? Never use the password directly as a key. Run it through a KDF such as PBKDF2, scrypt or Argon2id with a random salt.

In Web Crypto, an authenticated encryption looks like this. The tag is appended to the ciphertext automatically:

const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
const iv = crypto.getRandomValues(new Uint8Array(12)); // 96-bit nonce, never reuse
const ct = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv }, key, new TextEncoder().encode("attack at dawn"));
// Store iv alongside ct — it is not secret, only unique.

How the encrypt.tools AES tool handles this

Our AES encryption tool defaults to AES-256-GCM. It derives the key from your password with PBKDF2-SHA-256 (310,000 iterations), generates a fresh random salt and a fresh random IV for every encryption, and packs them with the ciphertext into one Base64 string, so the nonce-reuse problem cannot arise. CBC and CTR are available for interoperability testing, but GCM is the only mode that will refuse to decrypt tampered data. Everything runs in your browser through the Web Crypto API.

FREQUENTLY ASKED

Frequently asked questions

Is AES-GCM better than AES-CBC?

+

Yes, for almost all purposes. GCM is authenticated, so it detects tampering, needs no padding, and is immune to padding-oracle attacks. CBC only provides confidentiality and must be paired with a separate MAC to be safe.

Why is AES-ECB insecure?

+

ECB encrypts each 16-byte block independently, so identical plaintext blocks produce identical ciphertext blocks. Patterns in the data, such as the shapes in an image, remain visible, and blocks can be swapped between messages.

What happens if I reuse a nonce with AES-GCM?

+

An attacker who sees two messages with the same key and nonce learns the XOR of the plaintexts and can recover the authentication key, allowing them to forge messages. Nonces must be unique per key; use AES-GCM-SIV or XChaCha20-Poly1305 if you cannot guarantee that.

Does the IV need to be secret?

+

No. The IV or nonce is normally stored or sent in the clear alongside the ciphertext. For GCM and CTR it must be unique; for CBC it must also be unpredictable.

Is AES-256 quantum-safe?

+

Largely, yes. Grover's algorithm would at best halve the effective key strength, leaving AES-256 with about 128 bits of security, which is considered sufficient. Public-key algorithms such as RSA and ECC are the ones that quantum computers threaten.

TOOLS IN THIS GUIDE

Tools used in this guide

KEEP READING