Understand AES best practices, block padding, and modes
Introduction
AES (Advanced Encryption Standard) is the most widely used symmetric encryption; HTTPS/TLS, Wi‑Fi (WPA2/3), full-disk encryption (BitLocker, FileVault), ZIP/7z archive encryption, and messaging apps (Signal, WhatsApp) all rely on it. Understanding how AES works helps explain how modern secure encryption is implemented.
Understanding encryption and AES
Why use AES
A “symmetric encryption algorithm” means the same key is used to transform plaintext into ciphertext and to reverse that operation. Considering practicality, AES is one of the symmetric encryption standards that best balances security, performance, and hardware support.
The recipe for perfect secrecy
The simplest classic example of perfect secrecy is the One-Time Pad (OTP). Any data in a computer can be seen as a series of 0s and 1s; by XORing the plaintext with a truly random key of the same length that is used only once, the ciphertext reveals no information about the plaintext even to an attacker with unlimited computing power.
Achieving perfect secrecy is very strict (OTP is nearly impractical). Claude Shannon’s concepts let us balance “theoretical security” and “practical feasibility”:
- Confusion: hide the relationship between the key and the ciphertext so attackers cannot derive the key
- Diffusion: ensure each bit of plaintext affects many bits of ciphertext to avoid preserving patterns
How AES works
AES is a block cipher that processes 128 bits of data at a time, with key sizes of 128 / 192 / 256 bits.
- Processes a fixed-size block each time (128 bits = 16 bytes)
- Uses the same Key for encryption and decryption
- Applies multiple rounds of transformations to make recovery difficult
AES treats 16 bytes of data as a 4x4 matrix:
[ a0 a4 a8 a12 ][ a1 a5 a9 a13 ][ a2 a6 a10 a14 ][ a3 a7 a11 a15 ]- SubBytes
- ShiftRows
- MixColumns
- AddRoundKey
AES modes of operation
AES itself only encrypts a single block, but real-world data is usually much larger, so modes of operation are used to handle many blocks:
ECB (Electronic Codebook)
Each block is encrypted independently; identical plaintext blocks produce identical ciphertext blocks. This is the biggest security flaw—encrypted images reveal the original outlines. Do not use in real development.
CBC (Cipher Block Chaining)
Each plaintext block is XORed with the previous ciphertext block before encryption. The first block uses a randomly generated IV (initialization vector). Same plaintext + different IV → completely different ciphertext. The downside is encryption must be done serially and cannot be parallelized. It was historically one of the most common symmetric modes.
CTR (Counter)
Turns a block cipher into a stream cipher: encrypt an incrementing counter (Nonce + counter) to generate a keystream that is XORed with the plaintext. Each block can be computed independently, supporting full parallelism, and no padding is required. Note: never reuse the same Nonce.
GCM (Galois/Counter Mode)
Adds GHASH authentication on top of CTR to produce an Auth Tag. Decryption verifies the Auth Tag to detect tampering. Provides both confidentiality and integrity; currently the recommended mode and widely used in HTTPS/TLS.
CFB / OFB
Both are variants that turn a block cipher into a stream cipher. CFB depends on the previous ciphertext block (similar to CBC), while OFB is independent of ciphertext and is more suitable for low-latency scenarios.
PKCS7 padding
Fill the missing bytes with the value equal to the number of missing bytes
Block ciphers operate on fixed block sizes. PKCS7 padding is a method to make plaintext length align with the block size. Supported block sizes: 1–255 bytes, most commonly used with AES (16-byte blocks).
Block size = 8 bytes, Plaintext = HELLO (5 bytes)Original: H E L L OMissing: 3 bytesPadded: H E L L O 03 03 03Another example, Plaintext = HELLO123 (exactly 8 bytes):Even if it exactly aligns, add a full block, otherwise decryption cannot determine the end:H E L L O 1 2 3 | 08 08 08 08 08 08 08 08Missing 1 byte → fill 01Missing 2 bytes → fill 02 02Missing 5 bytes → fill 05 05 05 05 05Missing 16 bytes→ fill 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10How to remove padding after decryption?
Read the value of the last byte → remove that many bytes
length := len(plaintext)unpadding := int(plaintext[length-1])plaintext = plaintext[:(length - unpadding)]Common vulnerability: Padding Oracle Attack
If a system returns different error messages on decryption failure, an attacker can exploit those differences to gradually recover the plaintext—this is the Padding Oracle Attack.
- Use AES-GCM (an AEAD mode that does not require padding)
- Do not leak whether padding was correct in error messages
Initialization Vector (IV)
IV / Nonce must be unique; some modes (like CBC) additionally require randomness
The initialization vector (IV) is a piece of random data introduced during encryption to ensure that the same plaintext produces different ciphertexts each time.
- Mode leakage: avoid letting attackers observe repeated ciphertext blocks and infer corresponding plaintext content (Fixed IV Penguin)
- Reuse: using the same IV with the same key causes a Many-Time Pad problem
IVs are typically prepended in plaintext to the encrypted data because the decryption side needs the same IV to recover the first block.
Conclusion
Correct algorithm + correct usage = real security
- Use proven practices (standard libraries, mature packages)
- IVs can be public but must be random (at least cryptographically secure pseudorandom)
- Provide keys via environment variables
- For new projects prefer AES-256-GCM; when compatibility is needed use AES-128-CBC + PKCS7; never use ECB.
Further reading
- Day 21. 加密演算法要注意的那些毛 (一) - 加密模式 - 看完眼眶濕濕的App開發者慘烈對抗險惡資安環境血與淚的控訴!
- AES: How to Design Secure Encryption - Spanning Tree
- Padding Oracle Attack - CTF Wiki
- (只用加法乘法)手撕美国AES高级加密标准过程 - 技术蛋老师
- AES: How to Design Secure Encryption - Spanning Tree