Block cipher modes of operation are how you actually use a symmetric encryption algorithm, like AES, to protect data longer than a single block.
Let’s see what that looks like with GCM, the modern gold standard, encrypting a short message with AES-256.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import os
# Generate a random 256-bit key
key = os.urandom(32)
# Generate a random 96-bit IV (Initialization Vector) for GCM
iv = os.urandom(12)
# The data to encrypt (must be a multiple of the block size, 16 bytes for AES)
# We'll pad it to 16 bytes
data = b"This is a secret message."
padder = padding.PKCS7(algorithms.AES.block_size).padder()
padded_data = padder.update(data) + padder.finalize()
# Create a cipher object for AES-256 in GCM mode
cipher = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend())
encryptor = cipher.encryptor()
# Encrypt the data
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
# GCM also produces an authentication tag
tag = encryptor.tag
print(f"Key (hex): {key.hex()}")
print(f"IV (hex): {iv.hex()}")
print(f"Original Data: {data}")
print(f"Padded Data: {padded_data}")
print(f"Ciphertext (hex): {ciphertext.hex()}")
print(f"Authentication Tag (hex): {tag.hex()}")
# Now, let's decrypt
decryptor = cipher.decryptor()
# You MUST provide the tag for GCM decryption
decryptor.authenticate_additional_data(b"") # No AAD in this example
decryptor.update(ciphertext, tag)
decrypted_padded_data = decryptor.finalize()
# Unpad the data
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
decrypted_data = unpadder.update(decrypted_padded_data) + unpadder.finalize()
print(f"Decrypted Data: {decrypted_data}")
The core problem these modes solve is that a block cipher, by itself, can only encrypt fixed-size blocks of data (16 bytes for AES). To encrypt longer messages, you need a strategy to break the data into blocks and process them. More importantly, simply encrypting each block independently (like in ECB mode) is insecure because identical plaintext blocks will produce identical ciphertext blocks, revealing patterns. Modes of operation introduce mechanisms to ensure that even identical plaintext blocks result in different ciphertext blocks, and often provide authentication to detect tampering.
The fundamental components you control are the key, which must be kept secret and is used for both encryption and decryption, and the Initialization Vector (IV), which is not secret and should be unique for each encryption with the same key. The IV is crucial for ensuring that different encryptions of the same plaintext produce different ciphertexts. For modes like GCM, you might also have Authenticated Data (AAD), which is data that is authenticated but not encrypted, useful for headers or metadata.
ECB (Electronic Codebook) is the simplest mode. Each block of plaintext is encrypted independently using the same key. It’s like looking up each plaintext block in a codebook to find its corresponding ciphertext block.
- Problem: Identical plaintext blocks result in identical ciphertext blocks. This is a massive security vulnerability, as it leaks information about the plaintext. Think of an image encrypted with ECB – you’d still see the outlines of the original image.
- When to use: Almost never. Only for extremely short, random data where patterns are impossible, or for very specific, limited use cases where the lack of diffusion is acceptable and understood.
CBC (Cipher Block Chaining) improves on ECB by XORing the previous ciphertext block with the current plaintext block before encrypting it. This chaining effect means that each ciphertext block depends on all preceding plaintext blocks.
- How it works:
- For the first block, the plaintext is XORed with an IV.
- For subsequent blocks, the previous ciphertext block is XORed with the current plaintext block.
- Security: Much better than ECB because identical plaintext blocks will produce different ciphertexts if they are in different positions within the message (due to the chaining). However, CBC is susceptible to padding oracle attacks if padding is not handled carefully, and it does not provide integrity or authenticity on its own.
- Example Config:
modes.CBC(iv)whereivis a random byte string of the same length as the cipher’s block size (16 bytes for AES).
GCM (Galois/Counter Mode) is an Authenticated Encryption with Associated Data (AEAD) mode. This means it provides both confidentiality (encryption) and integrity/authenticity (protection against tampering) in a single pass. It’s widely adopted due to its efficiency and security.
- How it works: It combines a counter mode (CTR) for encryption with a Galois field multiplication-based MAC (Message Authentication Code) for authentication. The counter mode ensures that each block is encrypted using a unique keystream, derived from the key and IV. The authentication is built on top of this.
- Key Features:
- Confidentiality: Achieved via CTR mode.
- Integrity & Authenticity: Achieved via a universal hash function (GHASH) over the ciphertext and optional AAD.
- Efficiency: Can be parallelized and is often hardware-accelerated.
- Example Config:
modes.GCM(iv, tag_length=16)whereivis typically 12 bytes (96 bits), andtag_lengthis usually 16 bytes.
The one thing most people miss about GCM is that the authentication tag is not just a checksum; it’s a cryptographic proof of integrity and authenticity generated using a polynomial evaluation over a finite field. When you decrypt, the system recomputes this tag based on the ciphertext, the IV, and any AAD, and compares it to the tag provided during encryption. If they don’t match exactly, decryption fails, and you know the data has been tampered with or is not from the expected source. This prevents bit-flipping attacks and other manipulation attempts that unauthenticated modes are vulnerable to.
The next concept you’ll run into is how to properly manage keys and IVs in a real-world application, and the implications of IV reuse.