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 Abdessamad Bettal··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.
| Mode | Authenticated? | Needs padding? | IV / nonce rule | Verdict |
|---|---|---|---|---|
| ECB | No | Yes | None (that's the problem) | Never use |
| CBC | No | Yes (PKCS#7) | Random and unpredictable | Legacy; only with encrypt-then-MAC |
| CTR | No | No | Unique per key, never repeat | Building block; add a MAC |
| GCM | Yes (128-bit tag) | No | Unique 96-bit nonce per key | Recommended default |
| GCM-SIV | Yes | No | Repeat is survivable | Use 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'scrypto/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 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 used in this guide
AES Encryption
Encrypt text with AES-256 in GCM, CBC, or CTR mode
CHACHA20 · AEADChaCha20-Poly1305
Modern authenticated stream cipher, password-based
PBKDF2 · HMAC-SHA-2PBKDF2 Derivation
Derive keys from passwords with salt and iterations
HMAC · SHA-2HMAC Generator
Keyed message authentication codes
Encoding vs Encryption vs Hashing: The Difference, With Examples
Encoding, encryption and hashing all turn data into gibberish, but only one keeps secrets. Learn the difference with real Base64, AES and SHA-256 examples and when to use each.
6 MIN READKDF · PASSWORDSArgon2id vs bcrypt vs scrypt vs PBKDF2: Password Hashing in 2026
Which password hashing algorithm should you use? A practical comparison of Argon2id, bcrypt, scrypt and PBKDF2 with OWASP-recommended parameters, hash formats, pitfalls and migration steps.
6 MIN READHASHING · SECURITYIs MD5 Still Safe? When MD5 and SHA-1 Are (and Aren't) OK to Use
MD5 and SHA-1 are broken — but not for everything. Learn exactly which attacks exist, where MD5 and SHA-1 are still acceptable, where they are dangerous, and what to use instead.
5 MIN READ