· ·

CISSP – Block Cipher’s Modes of Operation, Explained without the Math

Somewhere in the CISSP Symmetrical Cryptography domain there’s some pages and information about something called “modes of operations” and moves on quite quickly. I know the CISSP is very surface level knowledge with the different topics but I found this to be very interesting and I wanted to dig deeper – especially because some practice questions are asking for specific knowledge of these different modes.

I stared at ECB, CBC, CTR and GCM for a solid while thinking they were just alphabet soup before it clicked that they’re actually answering one very practical question: encryption algorithms only know how to scramble a fixed-size chunk of data, so what do you do when your data is bigger than the chunk?

/what’s a block cipher?

A block cipher is an encryption algorithm that only works on fixed-size pieces of data at a time, called blocks. AES, the one you’ll bump into everywhere, works on 128bit blocks. Feed it a 128bit block of plaintext and key, and it spits out a 128bit block ciphertext. Feed it exact same plaintext and key again, and – this is important – you get the exact same cipertext back. It’s what’s called deterministic (will always produce the exact same output, with no room for randomness, chance, or variation), by design.

That determinism is fine, exactly what we want and need, if you only ever have exactly one block to encrypt. But real data – a file, a message, a database column – is basically never exactly 128bit long. So you need a strategy for chaining a bunch of block encryptions together to cover different length or amount of data. That strategy is what a “mode of operation” actually is.

/ecb – the one you should never use

Electronic Codebook is the simplest possible mode: chop your data into blocks, encrypt each block independently with the same key, done. No memory of what came before, no interaction between blocks at all.
-> Block 1 gets encrypted on its own.
-> Block 2 gets encrypted on its own.
-> Block 3, same deal, completely independent of blocks 1 and 2.

The problem falls straight out of that determinism I mentioned before: identical plaintext blocks produce identical ciphertext blocks, every single time. If two 128bit chunks in your file happen to be the same – which happens constantly in structured data, images etc. – the encrypted output will show two identical blocks too. You haven’t hidden the pattern, you’ve just relabeled it with different symbols.

This is famously demonstrated with the “ECB Penguin” – take a bitmap image of the Linux penguin, encrypt blocks of it with ECB mode, and the outline of the penguine is still completely visible in the encrypted version, just recolored into ciphertext blocks. This example here shows Tux (mascot / penguin of linux) encrypted with ECB:

Source: https://github.com/pakesson/diy-ecb-penguin

/cbc – chaining blocks together

Cipher Block Chaining fixes the pattern-leaking problem with one clever trick: before encrypting a block, XOR it with the ciphertext of the previous block first.
-> Block 1 gets XORed with a random starting value (Initialization Vector (IV)), then encrypted.
-> Block 2 gets XORed with the ciphertext of Block 1, then encrypted.
-> Block 3 gets XORed with the ciphertext of Block 2, then encrypted.
-> and so on down the chain, all the way to the last block.

Now, even if two plaintext blocks are identical, they get chained onto different previous ciphertext, so their output ciphertext ends up different too. The penguin disappears completely.

But CBC has a catch: because each block depends on the one before it, encryption has to happen chronologically, one block after another – you can’t encrypt block 47 without first encrypting block 46. Decryption can actually happen parallel, since you already have all the ciphertext blocks available to XOR against. And that IV has to be unpredictable and never reused with the same key, or you weaken the whole scheme.

/cfb and ofc – cbc’s lesser-known siblings

Two modes that don’t come up as often but round out the “chaining” family: Cipher Feedback (CFB) and Output Feedback (OFB). Both turn a block cipher into something that behaves like a stream cipher, similar to what CTR does (covered next), but by feeding either the previous ciphertext (CFB) or the previous keystream ouput (OFB) back into the next encryption step, rather than chaining the plaintext itself like CBC does. They’re not wrong if it pops up on a question, they’re just mostly historical at this point – CTR and GCM do the same job better, with cleaner parallelism and feter footguns.

/ctr – turning a block cipher into a stream

Counter mode takes a completely different approach from all the chaining modes above: instead of encrypting your actual data directly, it encrypts a counter value (starting nonce, then nonce+1, then nonce+2, and so on), and XORs the result of that with your plaintext.
-> Encrypt(counter=0) XOR plaintext block 1 = ciphertext block 1
-> Encrypt(counter=1) XOR plaintext block 2 = ciphertext block 2
-> Encrypt(counter=2) XOR plaintext block 3 = ciphertext block 3

It’s a slightly different mental model than CBC: the block cipher isn’t touching the data at all here. It’s generating a pseudorandom-looking stream of bytes (the “keystream”) from the counter, and all your actual plaintext ever does is get XORed against that stream. Encrypt(counter) never depends on your data, so it can be pre-computed, cached, or run in parallel across as many cores as you have lying around.

/gcm – encryption plus a tamper receipt

Here’s the thing, none of the modes above actually solve authenticity. ECB, CBC, CFB, OFB and CTR are all only trying to keep your data secret – none of them tell you if the ciphertext was tampered with in transit. You could decrypt something, and it would look fine, while actually being subtly altered – a changed bank account number, a changed permission flag – with absolutely no built-in way to detect it.

Galoise/Counter Mode (GCM) is CTR mode’s suped-up cousin. It does the counter-based encryption exactly like CTR and bolts on an authentication tag calculated alongside it, using technique called Galoise field multiplication. When you decrypt, you also verify that tag against the ciphertext you received. If even a single bit of ciphertext was altered, verification fails outright and you know immediately, instead of silently trusting corrupted or attacker-modified data.

This combo – confidentiality + integrity + authenticity in one single pass – is called Authenticated Encryption. GCM is the mode doing the heavy lifting behind TLS 1.3, most VPN traffic and modern disk and database encryption today.

/summary

Short acronyms to wrap this up and make it memorable for me:

ECB -> Exposes pattern (penguin problem), nothing hidden between identical blocks

CBC -> Chains each block to the one before it, breaking the pattern

CTR -> Counts up a counter and XORs it in, no chaining, fully parallel

GCM -> guards the data with an authentication tag on top – the mode that actually wins and is the modern default

Onto the next domain. Keep you posted – bye bye, Casi.