Learn · Technologies we use
Block cipher modes of operation: ECB, CBC, CTR, OFB and GCM
Why a good cipher in a bad mode leaks, with the ECB picture demo on your own image, a diagram of each mode and a table to choose from.
A block cipher such as AES encrypts exactly 16 bytes at a time. Real messages are longer, and the way you string the blocks together matters as much as the cipher. That recipe is the mode of operation. A good cipher in a bad mode leaks the patterns in your data, or lets an attacker change your message undetected. NIST's SP 800-38A defines five modes, ECB, CBC, CFB, OFB and CTR, and GCM (SP 800-38D) adds authentication on top of CTR. Below we show what each does, draw it, and let you watch the worst one at work on a picture of your own.
ECB: the mode you must not use
Electronic Codebook mode encrypts every 16-byte block separately under the same key. It's the obvious thing to do, and it has a fatal property: equal plaintext blocks give equal ciphertext blocks, so the structure of the message shows straight through the encryption.
The demo below shows what that means. It encrypts a picture with AES-128 twice, once in ECB mode and once in CBC mode, each time with a new random key. Press the sample button or drop in a picture of your own (it never leaves your browser).
PNG, JPEG, GIF or WebP; scaled down to 192 pixels, never uploaded
Nothing you drop here leaves your browser. The picture is read and encrypted in this page only.
The sample picture is 9,216 blocks of 16 bytes (four pixels each) but only 498 different blocks, because large areas of it are a single color. ECB produced exactly 498 different ciphertext blocks, one for each, so the outline of the picture is plainly visible. CBC produced 9,216 different blocks, which look like noise. Nobody found the key and nobody broke the cipher, and the picture still leaked. The same failure hits any data with repeats: a database column, a table of records, a file header.
CBC: chaining the blocks
Cipher Block Chaining XORs each plaintext block with the previous ciphertext block before encrypting it, and the first block with a random starting value, the IV. Equal plaintext blocks no longer give equal ciphertext, because each ciphertext depends on everything before it.
- The IV must be unpredictable, not merely unique, or an attacker who can influence the plaintext can test guesses.
- It needs padding. The message has to be a whole number of blocks, so it's padded (PKCS#7 appends n bytes of value n). The decryptor checks the padding, and a decryptor that reveals whether the padding was valid can be turned into a decryption oracle. Serge Vaudenay described the attack in 2002, and the POODLE attack on SSL 3.0 in 2014 was a real-world version.
- It isn't authenticated. Flip a bit in ciphertext block Ci and plaintext block Pi+1 changes in exactly that bit, while Pi turns into garbage. An attacker who knows the plaintext can make targeted changes to one block, paying with one ruined block.
- Encryption is sequential, but decryption can run in parallel, because every C is already known.
CTR: a stream from a counter
Counter mode never puts the plaintext through the cipher at all. It encrypts a sequence of counter blocks (a nonce followed by 1, 2, 3, …) and XORs the result, the keystream, with the plaintext. That turns the block cipher into a stream cipher.
- No padding, any length, fully parallel, and you can jump to any block.
- A (key, nonce) pair must never repeat. Reuse it and the two ciphertexts XOR to the XOR of the plaintexts, the "two-time pad". The AES playground shows the second message falling out of that.
- Not authenticated, and malleable: flip a bit of the ciphertext and exactly that bit flips in the plaintext, with nothing else damaged. A "pay $100" can become "pay $900" without knowing the key (authenticated encryption).
OFB and CFB: the older stream modes
Output Feedback runs the cipher on its own output over and over to make the keystream, and XORs the stream with the plaintext. The keystream doesn't depend on the plaintext at all, so you can compute it in advance, but you can't parallelize it, and like CTR it isn't authenticated.
Cipher Feedback (CFB) feeds the ciphertext back instead, and it's the self-synchronizing cousin. Neither sees much use now, but OFB has a place in this site's history. Every message sealed here between 2016 and 2026 used AES-256 in OFB, and the browser's Web Crypto API has no OFB, so we open them by encrypting zero blocks in CBC mode, which produces exactly the OFB keystream (how we decrypt 2016 messages with a mode the browser does not have).
GCM: CTR with a seal
Galois/Counter Mode is CTR for confidentiality plus a polynomial hash, GHASH, over the ciphertext (and any extra data you want to bind to it), which yields a 128-bit authentication tag. On opening, the tag is checked first. A wrong key, a flipped bit or a truncated message is refused outright, which closes CTR's malleability problem. This is authenticated encryption, and it's what everything new should use. GCM keeps CTR's rules with a stricter edge: a (key, nonce) pair used twice breaks confidentiality and also leaks the authentication key. The full story is in AES-GCM, explained. NIST's rule for GCM with randomly chosen 96-bit IVs is to use no more than 232 messages under one key, because the chance that two random IVs collide grows with the square of the count. Below that the risk is negligible, and above it the key must be replaced. In the browser, CTR has a related knob: Web Crypto's AES-CTR takes a length that says how many bits at the end of the counter block count up, and the rest is the fixed nonce, so a counter that wraps around repeats the keystream.
The modes side by side
| Mode | Encrypt in parallel? | Decrypt in parallel? | Padding needed? | IV / nonce | Authenticated? | In Web Crypto? |
|---|---|---|---|---|---|---|
| ECB | Yes | Yes | Yes | None | No | No |
| CBC | No | Yes | Yes | Unpredictable IV | No | Yes |
| CFB | No | Yes | No | Unique IV | No | No |
| OFB | No | No | No | Unique IV | No | No |
| CTR | Yes | Yes | No | Unique nonce | No | Yes |
| GCM | Yes | Yes | No | Unique nonce | Yes (128-bit tag) | Yes |
Choosing a mode
For new work, use an authenticated mode: AES-GCM, or a different cipher with the same kind of guarantee, such as ChaCha20-Poly1305. If you have to use CBC or CTR, add a MAC over the ciphertext and verify it before decrypting anything (encrypt-then-MAC). Never use ECB for anything longer than one block. Disk encryption uses a further family, XTS, designed for data stored in place that can't grow a tag, and it's outside the scope of this page.
How cipher.ink uses this
Every message sealed today uses AES-256 in GCM mode, with a fresh random 12 bytes (96 bits) IV per message and per attachment, and a 128-bit tag. The messages sealed from 2016 to 2026 used OFB and are read through the CBC trick above, and that article states the format's weaknesses openly. The only unauthenticated format on this site is that legacy one, kept so old messages still open, and we use ECB nowhere.
On the timeline
- 2014 The POODLE attack exploits CBC padding in SSL 3.0; Google and Apple redesign phone encryption.