gchq/CyberChef · error · OperationError
Invalid PKCS#5 padding.
Error message
Invalid PKCS#5 padding.
What it means
During PRESENT decryption with PKCS5 padding, removePadding reads the last byte as padByte and verifies that the final padByte bytes all equal padByte (PKCS#5/PKCS#7 spec). If any of those bytes differs, the padding is invalid and decryption is rejected. This branch fires when padByte is itself in range but one of the preceding bytes disagrees - the classic symptom of a wrong key.
Source
Thrown at src/core/lib/Present.mjs:295
* @returns {number[]} - Unpadded message
*/
function removePadding(message, padding, blockSize) {
if (message.length === 0) return message;
switch (padding) {
case "NO":
case "ZERO":
case "RANDOM":
// These padding types cannot be reliably removed
return message;
case "PKCS5": {
const padByte = message[message.length - 1];
if (padByte > 0 && padByte <= blockSize) {
// Verify padding
for (let i = 0; i < padByte; i++) {
if (message[message.length - 1 - i] !== padByte) {
throw new OperationError("Invalid PKCS#5 padding.");
}
}
return message.slice(0, message.length - padByte);
}
throw new OperationError("Invalid PKCS#5 padding.");
}
case "BIT": {
// Find 0x80 byte working backwards, skipping zeros
for (let i = message.length - 1; i >= 0; i--) {
if (message[i] === 0x80) {
return message.slice(0, i);
} else if (message[i] !== 0) {
throw new OperationError("Invalid BIT padding.");
}
}
throw new OperationError("Invalid BIT padding.");
}View on GitHub (pinned to 4290ea7539)
Solutions
- Verify the key matches the one used for encryption (same length - 10 or 16 bytes - and same bytes).
- Confirm the IV is correct and in the right byte order for CBC mode.
- Check that the encrypting party actually used PKCS5 padding; if not, set the matching padding type on decrypt.
- Inspect the last block of decrypted bytes - if it looks random, the key is almost certainly wrong.
- If you cannot guarantee PKCS5, decrypt with padding='NO' and inspect the raw tail bytes.
Example fix
// before const pt = decryptPRESENT(ct, wrongKey, iv, 'CBC', 'PKCS5'); // -> Invalid PKCS#5 padding // after - debug by skipping padding validation const raw = decryptPRESENT(ct, wrongKey, iv, 'CBC', 'NO'); console.log(raw.slice(-8)); // inspect last block to confirm wrong-key hypothesis // then supply the correct key: const pt = decryptPRESENT(ct, correctKey, iv, 'CBC', 'PKCS5');
Defensive patterns
Strategy: try-catch
Validate before calling
function isValidPKCS5(bytes, blockSize = 8) {
const pad = bytes[bytes.length - 1];
if (!(pad > 0 && pad <= blockSize)) return false;
for (let i = 0; i < pad; i++) {
if (bytes[bytes.length - 1 - i] !== pad) return false;
}
return true;
}
const raw = decryptPRESENT(ct, key, iv, mode, 'NO');
if (!isValidPKCS5(raw)) throw new Error('Wrong key or non-PKCS5 source data'); Try / catch
try {
return decryptPRESENT(ct, key, iv, mode, 'PKCS5');
} catch (e) {
if (!/PKCS#5/.test(e.message)) throw e;
// likely wrong key - inspect raw then surface a clear error
const raw = decryptPRESENT(ct, key, iv, mode, 'NO');
throw new Error('Decryption produced invalid PKCS5 padding; key is probably wrong.');
} Prevention
- Verify the key matches the encryption key exactly (same bytes and length).
- Confirm the IV is correct for CBC mode.
- Ensure the encrypting party actually used PKCS5.
- Treat 'Invalid PKCS#5 padding' as a strong wrong-key signal.
When it happens
Trigger: Calling decryptPRESENT(cipherText, wrongKey, iv, mode, 'PKCS5') - the decrypted plaintext looks random and the tail bytes do not form valid PKCS5 padding. Also fires with the right key but corrupted ciphertext bytes near the end of the last block.
Common situations: Wrong key supplied (most common); wrong IV in CBC mode corrupting the first block but randomly fixing the last; ciphertext truncated or with a byte flipped; message was not PKCS5-padded on the encrypting side (used ZERO/RANDOM instead).
Related errors
- Invalid BIT padding.
- No padding requested but input is not a ${blockSize}-byte mu
- Unknown padding type: ${padding}
- Invalid block cipher mode: ${mode}
- Invalid ciphertext length: ${cipherText.length} bytes. Must
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/5bb3570649aa91a4.
Report an issue: GitHub.