Cipher Block Chaining (CBC) is a block cipher mode of operation used with symmetric encryption algorithms like Advanced Encryption Standard (AES). It enhances data confidentiality by introducing dependency between plaintext blocks and their preceding ciphertext blocks. It also makes ciphertext less predictable even if plaintext contains repetitive patterns.

How CBC Mode Works in AES

CBC mode processes fixed-size blocks (typically 128 bits in AES) and requires an Initialization Vector (IV) for the first block. Each plaintext block is XORed with the previous ciphertext block before encryption.

Encryption Process

Each block of plaintext is processed sequentially, where the encryption of a block depends on the encryption result of the previous block.

Variables:

  • P[i]: i-th plaintext block
  • C[i]: i-th ciphertext block
  • IV: Initialization Vector (128-bit)
  • E_K: AES encryption function with key K
code
C[0] = E_K(P[0] ??? IV)
code
C[1] = E_K(P[1] ??? C[0])
code
C[2] = E_K(P[2] ??? C[1])

Each output block depends on the current plaintext block and the ciphertext block that precedes it.

Decryption Process

Decryption reverses the encryption process by first decrypting each ciphertext block and then XORing it with the previous ciphertext block.

Variables:

  • D_K: AES decryption function with key K
  • IV: Initialization Vector
code
P[0] = D_K(C[0]) ??? IV
code
P[1] = D_K(C[1]) ??? C[0]
code
P[2] = D_K(C[2]) ??? C[1]

Role of the Initialization Vector (IV)

The IV ensures that encrypting the same plaintext with the same key results in different ciphertext. Without a random IV, CBC becomes deterministic and exposes plaintext patterns.

IV Requirements:

  • Must be unpredictable and unique for each encryption session.
  • Must be exactly one block in length (e.g., 16 bytes for AES-128).
  • Can be transmitted in plaintext but must not be reused with the same key.

Example (Using Python)

code
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad

key = get_random_bytes(16)
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CBC, iv)


plaintext = b"Sensitive Data Block"
code
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))


# Decrypt
decipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(decipher.decrypt(ciphertext), AES.block_size)


assert decrypted == plaintext

Explanation:

  • pad/unpad: Ensures that the plaintext length aligns with AES block boundaries.
  • IV must be preserved or sent with the ciphertext so the recipient can correctly decrypt the message.
  • If the IV is lost or reused, decryption will fail or introduce security vulnerabilities.

CBC in Media Encryption (e.g., HLS)

In video streaming (like HLS), AES-CBC is commonly used to encrypt .ts video segments. The EXT-X-KEY tag defines the encryption method and IV used per segment.

code
#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/key.key",IV=0x1a2b3c4d5e6f77889900aabbccddeeff

Using the same IV for different segments, especially with the same key, is a security flaw that can expose segment patterns.