Skip to content
Lesson 11 of 12

Step 1 of 5 · Reading · ~2 min

PKCS#7 Padding & Padding Oracle Attacks

Modes of Operation

PKCS#7 Padding & Padding Oracle Attacks

ECB and CBC require the plaintext to be a multiple of the AES block size (16 bytes). PKCS#7 padding (RFC 5652, originally PKCS #5) handles arbitrary-length input.

The padding rule

Append n bytes, each with value n, where n = block_size - (len(data) mod block_size). Crucially: if the data is already a multiple of the block, append a full block of 0x10 bytes — never zero. Without that rule the unpadder cannot tell "no padding" from "16 bytes of zero".

4869 (2 bytes)               -> 4869 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e
00112233...eeff (16 bytes)   -> 0011...eeff 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
empty                        -> 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10

The padding oracle attack

If your decryption code reveals (even implicitly via error timing) whether the padding was valid, an attacker can decrypt arbitrary ciphertext byte-by-byte. The attack:

  1. Target the last byte of block C_i. Set C'_{i-1} to a random block, leaving C_i alone.
  2. Submit C'_{i-1} || C_i to the oracle. CBC decryption produces P' = dec(C_i) XOR C'_{i-1}.
  3. Tweak the last byte of C'_{i-1} from 0x00 to 0xff until the oracle reports VALID. The attacker now knows P'[15] = 0x01 (since CBC unpadder requires a valid 1-byte pad).
  4. Therefore dec(C_i)[15] = C'_{i-1}[15] XOR 0x01. Combined with the real C_{i-1}[15] you recover P_i[15].
  5. Repeat for byte 14 (target value 0x02 with byte 15 set to make P'[15] = 0x02), etc.

About 128 oracle calls per byte = ~2048 per block. Real-world examples: Vaudenay (2002), POODLE (2014), Lucky Thirteen (2013).

The fix: AEAD

The right answer is authenticated encryption. AES-GCM, ChaCha20-Poly1305, and AES-OCB compute a MAC over the ciphertext. The decrypter MUST verify the MAC before even attempting to unpad. No tag, no oracle.

If you're stuck with CBC, wrap it in HMAC: tag = HMAC-SHA256(K_mac, IV || ciphertext). Verify the tag first, in constant time, then decrypt and unpad.

Up nextAES-GCM Authenticated EncryptionModes of Operation

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…