Modes of Operation

Suppose you encrypt a hospital's patient database with AES. You do this one 16-byte block at a time, using the same key for every block. An attacker who cannot break AES itself can still notice something important. Two patients with identical diagnosis codes produce identical ciphertext blocks. That single observation is visible without ever recovering the key. It can leak diagnoses, salaries, or repeated passwords across an entire encrypted dataset. This is not a flaw in AES; it is a flaw in how AES was used. A block cipher only promises to scramble one fixed-size block unpredictably. It says nothing about what happens when you need to encrypt a message longer than that one block. This is almost always the case. A mode of operation is the missing piece. It is an algorithm that takes a block cipher (like AES) and a key. It turns them into a scheme for encrypting messages of arbitrary length. Modes matter enormously in practice because virtually no real message is exactly 16 bytes. TLS records, disk sectors, database rows, and video streams are all much longer. The mode determines whether the resulting scheme leaks patterns, tolerates parallel hardware, survives bit-flipping attacks, or requires padding at all. Choosing the wrong mode has caused real breaches. Examples include ECB-encrypted images that visibly reveal their content, and CBC implementations broken by padding-oracle attacks. This article builds the concept from the ground up. It uses the Block Ciphers and the PRP Abstraction you already know. It assumes familiarity with The Advanced Encryption Standard (AES) as the concrete block cipher. We treat three canonical modes — ECB, CBC, and CTR. We explain exactly how each is computed, and why ECB is dangerous. We show why CBC and CTR achieve a strong security notion called semantic security under chosen-plaintext attack. We also cover what each mode costs in practice (parallelism, error propagation, padding, IV/nonce management). By the end you will be able to trace ECB, CBC, and CTR encryption and decryption by hand. You will explain precisely why deterministic block-by-block encryption leaks equality patterns. You will articulate the tradeoffs that lead real protocols (TLS, disk encryption, IPsec) to prefer CTR-like constructions. You will also see why none of these modes alone protect integrity. This sets up the need for Message Authentication Codes.

Key takeaways
  • A mode of operation extends a block cipher (fixed-size PRP) to encrypt messages of arbitrary length.
  • ECB encrypts each block independently and identically — identical plaintext blocks always produce identical ciphertext blocks, leaking patterns.
  • CBC chains blocks via XOR with the previous ciphertext block (or a random IV for the first), making it non-deterministic and pattern-hiding.
  • CTR mode turns a block cipher into a stream cipher by encrypting a counter and XORing with plaintext; it is parallelizable and needs no padding.
  • CBC and CTR are semantically secure under chosen-plaintext attack (CPA) when the IV/nonce is chosen correctly; ECB is never CPA-secure for multi-block messages.
  • None of these modes provide authenticity — an attacker can still tamper with ciphertext undetected, motivating Message Authentication Codes.
The core insight

A mode of operation is what makes a block cipher's encryption randomized across blocks, and randomness (not the cipher's strength) is what hides patterns in long messages.

The idea

A block cipher, modeled as a pseudorandom permutation (PRP), is a keyed function Ek:{0,1}n→{0,1}nE_k : \{0,1\}^n \to \{0,1\}^n that looks like a random permutation to anyone without the key. Crucially, a PRP is deterministic: encrypting the same nn-bit block under the same key always gives the same output. This determinism is fine — even necessary — for a single block, but it becomes a liability the moment we must encrypt a message mm longer than nn bits. We split mm into blocks m1,m2,…,mℓm_1, m_2, \dots, m_\ell and need a rule for turning them into ciphertext blocks c1,…,cℓc_1, \dots, c_\ell (plus possibly some extra public value). That rule is the mode of operation. The security goal for encryption is semantic security under a chosen-plaintext attack (CPA-security): an adversary who can request encryptions of plaintexts of their choosing should not be able to distinguish the encryption of m0m_0 from the encryption of m1m_1 for any two equal-length messages they pick, better than random guessing. A mode that encrypts each block deterministically and independently cannot be CPA-secure for multi-block messages, because the adversary can simply submit two messages that differ only in whether a block repeats, and check for repeated ciphertext blocks. This is exactly the flaw in ECB (Electronic Codebook) mode. CBC (Cipher Block Chaining) and CTR (Counter) mode repair this by injecting randomness or state — an initialization vector (IV) or nonce — so that encrypting the same plaintext twice yields different ciphertext, provided the IV/nonce is fresh.

Figure
Same plaintext blocks, three different fates: ECB repeats, CBC and CTR do not
Plaintext: m1 m2 m1 m3 (block m1 repeats) ECB c1 c2 c1 c3 ← c1 repeats: pattern visible CBC c1 c2 c3' c4 ← chaining hides repeat CTR c1 c2 c3' c4 ← counter differs per block, so no repeat Each block encrypted with distinct effective input (IV/counter mixed in) never repeats, even if plaintext does. ECB encrypts each block in isolation, so identical inputs always give identical outputs.

How it works

ECB — Electronic Codebook

ECB is the simplest and worst mode: split the message into blocks and encrypt each one independently with the same key. ``` ECB-Encrypt(key, m1, m2, ..., mL): for i in 1..L: ci <- E(key, mi) return c1, c2, ..., cL ECB-Decrypt(key, c1, c2, ..., cL): for i in 1..L: mi <- D(key, ci) return m1, m2, ..., mL ``` No IV, no state carried between blocks. This is precisely why it fails: E(k,⋅)E(k,\cdot) is a deterministic function, so mi=mj  ⟹  ci=cjm_i = m_j \implies c_i = c_j. Any structure in the plaintext — repeated blocks, repeated file headers, images with large uniform regions — survives into the ciphertext as repeated or patterned ciphertext blocks.

CBC — Cipher Block Chaining

CBC fixes this by XORing each plaintext block with the previous ciphertext block before encrypting, and starting the chain with a random IV. ``` CBC-Encrypt(key, IV, m1, m2, ..., mL): c0 <- IV // c0 is not transmitted as ciphertext, // but IV itself must be sent/stored for i in 1..L: ci <- E(key, mi XOR c(i-1)) return IV, c1, c2, ..., cL CBC-Decrypt(key, IV, c1, c2, ..., cL): c0 <- IV for i in 1..L: mi <- D(key, ci) XOR c(i-1) return m1, m2, ..., mL ``` The IV must be unpredictable (ideally uniformly random) and is sent alongside the ciphertext in the clear — it need not be secret, only unpredictable before encryption occurs. Padding is required if the last plaintext block is shorter than nn bits (commonly PKCS#7 padding); the padding length must be verified and stripped on decryption. Decryption in CBC can be fully parallelized (compute D(k,ci)D(k,c_i) for all ii independently, then XOR with ci−1c_{i-1}), but encryption is inherently sequential — you cannot compute cic_i before ci−1c_{i-1} exists.

CTR — Counter Mode

CTR mode does not encrypt the plaintext directly at all. Instead it uses the block cipher to generate a keystream by encrypting a counter, and XORs that keystream with the plaintext — turning a block cipher into a stream cipher. ``` CTR-Encrypt(key, nonce, m1, m2, ..., mL): for i in 1..L: ctr_i <- nonce || i // or nonce + i, per spec pad_i <- E(key, ctr_i) ci <- mi XOR pad_i return nonce, c1, c2, ..., cL CTR-Decrypt(key, nonce, c1, c2, ..., cL): for i in 1..L: ctr_i <- nonce || i pad_i <- E(key, ctr_i) mi <- ci XOR pad_i return m1, m2, ..., mL ``` Encryption and decryption use only the forward direction E(k,⋅)E(k,\cdot) — the block-cipher inverse DD is never needed, which simplifies hardware. Every block's counter value is distinct within a message (and must never repeat across messages under the same key), which plays the same role IV freshness plays in CBC. No padding is needed: the last block's keystream can simply be truncated to the plaintext's remaining length.

Figure
CBC vs CTR data flow per block
CBC (top) vs CTR (bottom) — encrypting block i CBC: c(i-1) ⊕ m_i = XOR out E(key, ·) c_i CTR: nonce ‖ i E(key, ·) keystream ⊕ m_i = c_i CBC: E is on the critical path, chained through ciphertext ⇒ sequential encryption. CTR: E only ever depends on (key, nonce, i) — computable for all i in parallel, before m arrives. CTR decryption = same keystream XOR ciphertext (E's inverse D is never used). CBC decryption is parallelizable (needs D), CBC encryption is not.

Complexity & correctness

Time. All three modes require exactly one block-cipher invocation per plaintext block: Θ(ℓ)\Theta(\ell) calls to EE (or DD) for a message of ℓ\ell blocks, each call costing whatever a single AES encryption costs (constant, independent of ℓ\ell). Total time is Θ(ℓ⋅n)\Theta(\ell \cdot n) where nn is the block size, i.e., linear in message length. There is no asymptotic difference between ECB, CBC, and CTR in raw operation count; the differences are in parallelism and latency structure:

  • ECB: every block independent — fully parallel encryption and decryption.
  • CBC: encryption strictly sequential (each cic_i needs ci−1c_{i-1}), decryption fully parallel.
  • CTR: both encryption and decryption fully parallel, and keystream blocks can even be precomputed before the plaintext is known.

Space. All modes are streamable, needing O(n)O(n) working memory beyond input/output buffers (one block's worth of state), independent of message length ℓ\ell.

Correctness (decryption inverts encryption). For ECB this is immediate since D(k,E(k,m))=mD(k, E(k,m)) = m by the PRP's invertibility. For CBC, unwind the recurrence: given ci=E(k,mi⊕ci−1)c_i = E(k, m_i \oplus c_{i-1}), apply D(k,⋅)D(k,\cdot) to both sides, using D(k,E(k,x))=xD(k,E(k,x)) = x:

D(k,ci)=mi⊕ci−1  ⟹  mi=D(k,ci)⊕ci−1.D(k, c_i) = m_i \oplus c_{i-1} \implies m_i = D(k, c_i) \oplus c_{i-1}.

Since ci−1c_{i-1} (or c0=IVc_0 = IV) is known at decryption time, this recovers mim_i exactly, block by block. For CTR, decryption recomputes the same keystream block padi=E(k,nonce∥i)\text{pad}_i = E(k, \text{nonce}\|i) used at encryption (same key, same counter value), and

ci⊕padi=(mi⊕padi)⊕padi=mic_i \oplus \text{pad}_i = (m_i \oplus \text{pad}_i) \oplus \text{pad}_i = m_i

by the self-inverse property of XOR. No use of DD is needed at all in CTR.

Why ECB is not CPA-secure. Formally, in the CPA game the adversary picks two equal-length messages m0,m1m^0, m^1, receives c=Enc(k,mb)c = \text{Enc}(k, m^b) for a hidden random bit bb, and must guess bb. Choose m0=(x,x)m^0 = (x, x) (two identical blocks) and m1=(x,y)m^1 = (x, y) with x≠yx \ne y. Under ECB, Enc(k,m0)\text{Enc}(k,m^0) always has c1=c2c_1 = c_2, while Enc(k,m1)\text{Enc}(k,m^1) has c1=c2c_1 = c_2 only with negligible probability (a random collision, probability ≈2−n\approx 2^{-n} for an nn-bit block). The adversary guesses b=0b=0 iff c1=c2c_1=c_2, winning with probability ≈1−2−n≫1/2\approx 1 - 2^{-n} \gg 1/2. This proves ECB fails CPA-security for any message with ≥2\ge 2 blocks, regardless of how strong the underlying PRP is — the flaw is structural, not cryptanalytic.

Why CBC and CTR are CPA-secure (proof sketch). The standard argument replaces the PRP E(k,⋅)E(k,\cdot) with a truly random function on nn-bit strings (this substitution changes the adversary's winning probability by only a negligible amount, by the PRP security definition itself). Then:

  • CBC: with a random IV, the first XOR-input m1⊕IVm_1 \oplus IV is uniformly random and independent of m1m_1 (since IVIV is independent and uniform), so E(k,m1⊕IV)E(k, m_1 \oplus IV) looks uniformly random and independent of m1m_1 to the adversary. Inductively, as long as no collision occurs among the chaining values {ci−1}\{c_{i-1}\} fed into EE (which happens with negligible probability for a random function on a large domain), each output block looks like an independent uniform random string, hiding all information about the plaintext.
  • CTR: the keystream blocks E(k,nonce∥1),E(k,nonce∥2),…E(k,\text{nonce}\|1), E(k,\text{nonce}\|2), \dots are outputs of a random function on distinct inputs (distinct counters), hence themselves an independent uniform random string as long as inputs never repeat. XORing plaintext with an independent uniform pad is a one-time-pad-style argument: the ciphertext reveals nothing about the plaintext beyond its length.

Both arguments hinge on a single requirement: the effective inputs fed to EE must never repeat across encryptions under the same key (a fresh random IV for CBC; a never-reused nonce/counter for CTR). This is the exact tradeoff surface: CBC needs randomness in the IV, CTR needs uniqueness (not necessarily randomness) in the nonce, and violating either collapses the security proof — and, in practice, leaks information exactly as ECB does.

Honest tradeoffs.

PropertyECBCBCCTR
CPA-secureNoYes (random IV)Yes (unique nonce)
Parallel encryptionYesNoYes
Parallel decryptionYesYesYes
Needs paddingYesYesNo
Needs cipher inverse DDYesYesNo
Random-access decryptionYesPartial (need ci−1c_{i-1})Yes
Error propagation1 block2 blocks (this + next)1 block only

None of the three provides integrity: an attacker who flips bits in CBC or CTR ciphertext produces predictable, controlled changes in the decrypted plaintext (a classic bit-flipping attack), and no mode alone detects tampering. This gap is closed by combining encryption with a MAC, or by using an authenticated mode (e.g., GCM) — the natural next topic once encryption-only modes are understood.

Worked example

Let block size be tiny for hand-tracing: n=4n = 4 bits, and model E(k,⋅)E(k,\cdot) abstractly as a fixed permutation table (as any PRP would behave for a fixed key). Take

E(k,⋅):0000→1011, 0001→0110, 0010→1110, 0011→0001, 0100→1001,E(k, \cdot): 0000{\to}1011,\ 0001{\to}0110,\ 0010{\to}1110,\ 0011{\to}0001,\ 0100{\to}1001,

and suppose plaintext blocks (4 bits each) are:

m1=0010,m2=0100,m3=0010(note: m1=m3).m_1 = 0010,\quad m_2 = 0100,\quad m_3 = 0010 \quad (\text{note: } m_1 = m_3).

ECB. Each block encrypted alone:

blockplaintextciphertext
10010E(k,0010)=1110E(k,0010) = 1110
20100E(k,0100)=1001E(k,0100) = 1001
30010E(k,0010)=1110E(k,0010) = 1110

Ciphertext blocks 1 and 3 are identical (1110=11101110 = 1110) — an eavesdropper immediately learns m1=m3m_1 = m_3 without any key knowledge, exactly the leak described above.

CBC. Take IV=c0=0101IV = c_0 = 0101.

c1=E(k,m1⊕c0)=E(k,0010⊕0101)=E(k,0111)c_1 = E(k, m_1 \oplus c_0) = E(k, 0010 \oplus 0101) = E(k, 0111)

(suppose the table also gives 0111→10100111 \to 1010, so c1=1010c_1 = 1010).

c2=E(k,m2⊕c1)=E(k,0100⊕1010)=E(k,1110)c_2 = E(k, m_2 \oplus c_1) = E(k, 0100 \oplus 1010) = E(k, 1110)

(suppose 1110→00111110 \to 0011, so c2=0011c_2 = 0011).

c3=E(k,m3⊕c2)=E(k,0010⊕0011)=E(k,0001)=0110.c_3 = E(k, m_3 \oplus c_2) = E(k, 0010 \oplus 0011) = E(k, 0001) = 0110.

Ciphertext: c1c2c3=1010, 0011, 0110c_1 c_2 c_3 = 1010,\ 0011,\ 0110 — all distinct, even though m1=m3m_1 = m_3, because each was XORed with a different chaining value before encryption. Decryption recovers, e.g., m3=D(k,c3)⊕c2=0001⊕0011=0010m_3 = D(k,c_3) \oplus c_2 = 0001 \oplus 0011 = 0010 ✓, matching the original.

CTR. Take nonce =00= 00, so counters are ctr1=0001,ctr2=0010,ctr3=0011\text{ctr}_1 = 0001, \text{ctr}_2 = 0010, \text{ctr}_3 = 0011 (2-bit nonce + 2-bit counter, toy sizing). Keystream:

pad1=E(k,0001)=0110,pad2=E(k,0010)=1110,pad3=E(k,0011)=0001.\text{pad}_1 = E(k, 0001) = 0110,\quad \text{pad}_2 = E(k, 0010) = 1110,\quad \text{pad}_3 = E(k, 0011) = 0001.

Ciphertext:

c1=m1⊕pad1=0010⊕0110=0100c_1 = m_1 \oplus \text{pad}_1 = 0010 \oplus 0110 = 0100
c2=m2⊕pad2=0100⊕1110=1010c_2 = m_2 \oplus \text{pad}_2 = 0100 \oplus 1110 = 1010
c3=m3⊕pad3=0010⊕0001=0011c_3 = m_3 \oplus \text{pad}_3 = 0010 \oplus 0001 = 0011

Again c1≠c3c_1 \ne c_3 despite m1=m3m_1 = m_3, because the counters differed even though the plaintext blocks matched. Decryption simply re-derives the same keystream and XORs it back off: m3=c3⊕pad3=0011⊕0001=0010m_3 = c_3 \oplus \text{pad}_3 = 0011 \oplus 0001 = 0010 ✓. This toy trace demonstrates concretely what the CPA-security argument promises in general: chaining (CBC) or counters (CTR) make the effective input to EE different every time, so equal plaintext blocks stop producing equal ciphertext blocks — the leak that dooms ECB disappears.

Common pitfalls & traps

PitfallWhy it happensConsequence
Using ECB "because it's simple"No IV/state to manageRepeated blocks leak structure (famous "ECB penguin" image leak)
Reusing an IV in CBCTreating IV as a fixed constantTwo ciphertexts with same first-block XOR-input reveal m1⊕m1′m_1 \oplus m_1'
Reusing a nonce/counter in CTRNonce management bugs, VM cloning, counter resetKeystream reused ⇒ XOR of two ciphertexts reveals XOR of plaintexts (catastrophic)
Predictable (not random) CBC IV, e.g. all-zero or sequentialConfusing "IV must be sent in clear" with "IV can be anything"Breaks the CPA proof; enabled real chosen-plaintext attacks (e.g., early SSL/TLS CBC issues)
Forgetting padding removal validation in CBCOff-by-one in stripping PKCS#7 paddingPadding-oracle attacks recover plaintext byte-by-byte
Assuming encryption alone gives integrityConfusing confidentiality and authenticityBit-flipping attacks silently corrupt/redirect decrypted plaintext
Treating CTR counter overflow casuallyMessage longer than counter spaceCounter wraps and repeats ⇒ same failure as nonce reuse

Pioneers & history

The concept of a "mode of operation" as a formal object, separate from the block cipher itself, crystallized alongside the standardization of DES in the 1970s, and was later rigorously analyzed through the lens of provable security (the CPA/CCA game framework) developed by cryptographic theorists working on exact definitions of secure encryption.

Origins · 1 minHorst Feistel and how this was discovered
HF
Horst Feistel
1915–1990 · Developed the Feistel network structure at IBM, underlying DES and shaping how block ciphers — and thus the need for modes of operation — were designed

Feistel's structural work on DES's predecessor "Lucifer" established the block-cipher paradigm that modes of operation were later built to extend safely to arbitrary message lengths.

History
1976
— NIST/NBS standardizes DES, and ECB/CBC are documented as its official modes of operation.
1980
— FIPS 81 formally specifies ECB, CBC, CFB, and OFB modes for DES.
1997
— NIST begins the process leading to AES, prompting new formal analysis of modes for the new cipher.
2001
— NIST SP 800-38A standardizes CTR mode alongside ECB, CBC, CFB, OFB for AES.
2007
— NIST SP 800-38D standardizes GCM, combining CTR-style encryption with built-in authentication.

Where this matters

TLS/SSL historically used CBC-mode AES for record encryption (vulnerable to padding-oracle attacks like Lucky Thirteen if implemented carelessly), and modern TLS 1.3 has moved to authenticated modes built on CTR-like constructions (AES-GCM, ChaCha20-Poly1305). Disk encryption (BitLocker, LUKS, dm-crypt) uses specialized modes (XTS, itself CTR-adjacent) tuned for random-access reads without padding overhead. VPNs and IPsec commonly use CTR or GCM for high-throughput, parallelizable encryption on multi-core hardware. Cloud storage encryption at rest typically favors CTR-based constructions because objects must support random-offset reads without decrypting an entire file, something CBC's sequential dependency complicates. Even outside cryptography proper, the ECB pitfall is a favorite teaching example — visibly encrypting a bitmap image in ECB mode reproduces recognizable outlines of the original image, a vivid, widely reproduced demonstration of why deterministic block-wise encryption fails.

Ask the tutor: How does GCM combine CTR-mode encryption with a MAC to get both confidentiality and integrity in one pass?

Why can't we just use ECB and rely on AES being unbreakable?

AES being unbreakable means no one can invert E(k,⋅)E(k,\cdot) or recover kk without unrealistic effort. But ECB's weakness has nothing to do with breaking AES — it's a structural fact that E(k,⋅)E(k,\cdot) is a deterministic function, so equal inputs always give equal outputs. An attacker exploiting this never attacks AES at all; they simply observe ciphertext block equality patterns, which map directly onto plaintext block equality patterns. This is why ECB fails the formal CPA-security definition even under the assumption that AES is a perfect PRP — the mode itself, not the cipher, is the vulnerability.

Does the IV in CBC need to be kept secret?

No. The IV is transmitted or stored alongside the ciphertext in the clear, and the security proof does not require it to be secret — only unpredictable at the time of encryption, ideally by being chosen uniformly at random for every message. The reason secrecy isn't needed is that the IV's only job is to randomize the first block's input to the cipher; once that randomization has happened, revealing the IV afterward doesn't help an attacker undo it. What breaks security is predictability before encryption, e.g. an attacker who can guess the next IV and craft a chosen plaintext exploiting that guess.

Why doesn't CTR mode need padding, but CBC does?

CBC encrypts the plaintext itself through the block cipher, and a block cipher only operates on full fixed-size blocks — if the last chunk of plaintext is shorter than a block, it must be padded up to a full block before encryption (commonly with PKCS#7 padding). CTR mode never runs the plaintext through the block cipher at all; it only encrypts counters to produce a keystream, which is then XORed with the plaintext. XOR can be applied to a partial block by simply truncating the keystream to match, so there is no need to pad the plaintext to a multiple of the block size.

Is CBC or CTR "more secure"?

Both achieve the same formal guarantee — semantic security under chosen-plaintext attack — when used correctly (random IV for CBC, unique nonce for CTR), so neither is "more secure" in that sense. They differ in engineering properties: CTR parallelizes fully and avoids padding, making it faster on modern multi-core and hardware-accelerated systems, while CBC's decryption parallelizes but encryption doesn't. In practice CTR (or CTR-derived authenticated modes like GCM) is favored in most modern high-throughput protocols, while CBC persists mainly in legacy systems and requires careful padding-oracle mitigations.

What happens if you flip a bit in CBC or CTR ciphertext — does decryption fail?

Decryption does not fail with an error; it silently produces corrupted (but structured) plaintext, which is the danger. In CBC, flipping a bit in ciphertext block cic_i scrambles the decrypted block mim_i completely (since it goes through DD), but flips the same bit position in mi+1m_{i+1} predictably, since cic_i also feeds into the XOR for mi+1m_{i+1}. In CTR, flipping a bit in cic_i flips exactly the corresponding bit in mim_i and nowhere else, since XOR is bitwise. Both allow an attacker to make targeted, predictable changes to plaintext without detection — this is why encryption modes need to be paired with a MAC for integrity.

Why is a counter in CTR mode allowed to be non-random, but an IV in CBC must be unpredictable?

CTR's security relies only on every keystream input (nonce‖counter) being distinct across the whole message and across all messages ever encrypted under that key — predictability is fine as long as uniqueness holds, since a random function's outputs on distinct inputs are independent regardless of how those inputs were chosen. CBC's security additionally relies on the first XOR input, m1⊕IVm_1 \oplus IV, being unpredictable to the adversary before they choose their challenge messages, because otherwise a CPA adversary can select plaintexts specifically to exploit a predicted IV. That distinction — uniqueness suffices for CTR, unpredictability is required for CBC's first block — is a direct consequence of how each mode's proof is structured.

How do these modes relate to what comes after — Message Authentication Codes?

ECB, CBC, and CTR all address only confidentiality: hiding the content of a message from eavesdroppers. None of them stop an active attacker from modifying ciphertext in ways that produce predictable or exploitable changes to the plaintext after decryption, because none of them include any mechanism to detect tampering. Message Authentication Codes solve the complementary problem of integrity and authenticity — proving a message came from someone who knows the key and was not altered in transit. Real systems combine an encryption mode with a MAC (or use an integrated authenticated mode like GCM) precisely because encryption alone, however strong the mode, is not enough.

Before this

Where this leads