{"record":{"id":"5bb3570649aa91a4","repo":"gchq/CyberChef","slug":"invalid-pkcs-5-padding","errorCode":null,"errorMessage":"Invalid PKCS#5 padding.","messagePattern":"Invalid PKCS#5 padding\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Present.mjs","lineNumber":295,"sourceCode":" * @returns {number[]} - Unpadded message\n */\nfunction removePadding(message, padding, blockSize) {\n    if (message.length === 0) return message;\n\n    switch (padding) {\n        case \"NO\":\n        case \"ZERO\":\n        case \"RANDOM\":\n            // These padding types cannot be reliably removed\n            return message;\n\n        case \"PKCS5\": {\n            const padByte = message[message.length - 1];\n            if (padByte > 0 && padByte <= blockSize) {\n                // Verify padding\n                for (let i = 0; i < padByte; i++) {\n                    if (message[message.length - 1 - i] !== padByte) {\n                        throw new OperationError(\"Invalid PKCS#5 padding.\");\n                    }\n                }\n                return message.slice(0, message.length - padByte);\n            }\n            throw new OperationError(\"Invalid PKCS#5 padding.\");\n        }\n\n        case \"BIT\": {\n            // Find 0x80 byte working backwards, skipping zeros\n            for (let i = message.length - 1; i >= 0; i--) {\n                if (message[i] === 0x80) {\n                    return message.slice(0, i);\n                } else if (message[i] !== 0) {\n                    throw new OperationError(\"Invalid BIT padding.\");\n                }\n            }\n            throw new OperationError(\"Invalid BIT padding.\");\n        }","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Present.mjs#L277-L313","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before\nconst pt = decryptPRESENT(ct, wrongKey, iv, 'CBC', 'PKCS5'); // -> Invalid PKCS#5 padding\n\n// after - debug by skipping padding validation\nconst raw = decryptPRESENT(ct, wrongKey, iv, 'CBC', 'NO');\nconsole.log(raw.slice(-8)); // inspect last block to confirm wrong-key hypothesis\n// then supply the correct key:\nconst pt = decryptPRESENT(ct, correctKey, iv, 'CBC', 'PKCS5');","handlingStrategy":"try-catch","validationCode":"function isValidPKCS5(bytes, blockSize = 8) {\n  const pad = bytes[bytes.length - 1];\n  if (!(pad > 0 && pad <= blockSize)) return false;\n  for (let i = 0; i < pad; i++) {\n    if (bytes[bytes.length - 1 - i] !== pad) return false;\n  }\n  return true;\n}\n\nconst raw = decryptPRESENT(ct, key, iv, mode, 'NO');\nif (!isValidPKCS5(raw)) throw new Error('Wrong key or non-PKCS5 source data');","typeGuard":null,"tryCatchPattern":"try {\n  return decryptPRESENT(ct, key, iv, mode, 'PKCS5');\n} catch (e) {\n  if (!/PKCS#5/.test(e.message)) throw e;\n  // likely wrong key - inspect raw then surface a clear error\n  const raw = decryptPRESENT(ct, key, iv, mode, 'NO');\n  throw new Error('Decryption produced invalid PKCS5 padding; key is probably wrong.');\n}","preventionTips":["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."],"tags":["cryptography","present","padding","decryption","wrong-key"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}