gchq/CyberChef · error · OperationError
Invalid BIT padding.
Error message
Invalid BIT padding.
What it means
Thrown by removePadding() in Twofish.mjs in the BIT (ISO/IEC 9797-1 padding method 1) branch when scanning backwards from the end of the message: a non-zero byte other than the 0x80 terminator is encountered before the terminator is found. BIT padding is 0x80 followed by zero bytes; finding any other non-zero value means the padding is malformed.
Source
Thrown at src/core/lib/Twofish.mjs:424
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.");
}
default:
throw new OperationError(`Unknown padding type: ${padding}`);
}
}
/**
* Encrypt using Twofish cipher with specified block mode
*
* @param {number[]} message - Plaintext as byte array
* @param {number[]} key - Key (16, 24, or 32 bytes)
* @param {number[]} iv - IV (16 bytes, not used for ECB)
* @param {string} mode - Block cipher mode ("ECB", "CBC", "CFB", "OFB", "CTR")
* @param {string} padding - Padding type ("NO", "PKCS5", "ZERO", "RANDOM", "BIT")View on GitHub (pinned to 4290ea7539)
Solutions
- Confirm the encrypt side used BIT padding and the same mode/key/IV.
- If the encrypt side used a different padding scheme, set the decrypt padding argument to match (PKCS5, ZERO, NO).
- If the plaintext genuinely ends in 0x80 followed by non-zero data, BIT padding is ambiguous for that data — choose PKCS5 instead.
Example fix
// before: data was PKCS5-padded, decrypt declares BIT decryptTwofish(ct, key, iv, "CBC", "BIT"); // throws on non-zero tail byte // after decryptTwofish(ct, key, iv, "CBC", "PKCS5");
Defensive patterns
Strategy: try-catch
Validate before calling
function isValidBitPadding(bytes) {
let i = bytes.length - 1;
while (i >= 0 && bytes[i] === 0) i--;
return i >= 0 && bytes[i] === 0x80;
}
const probe = decryptTwofish(ct, key, iv, mode, "NO");
if (!isValidBitPadding(probe)) {
throw new Error("Decrypted output has invalid BIT padding; verify key/IV/mode and that BIT padding was applied.");
} Type guard
function isValidBitPadding(bytes) {
let i = bytes.length - 1;
while (i >= 0 && bytes[i] === 0) i--;
return i >= 0 && bytes[i] === 0x80;
} Try / catch
try {
pt = decryptTwofish(ct, key, iv, "CBC", "BIT");
} catch (e) {
if (e instanceof OperationError && /Invalid BIT padding/.test(e.message)) {
return { error: "Wrong key/IV/mode, or data was not BIT-padded." };
}
throw e;
} Prevention
- Only use BIT padding when you can guarantee the plaintext never legitimately ends in 0x80 + zeros; prefer PKCS5 otherwise.
- Ensure encrypt and decrypt agree on the padding scheme.
- Treat BIT-padding failures as key/IV/mode suspects first.
When it happens
Trigger: Calling decryptTwofish() with padding "BIT" on ECB/CBC output where the decrypted tail contains a non-zero, non-0x80 byte before the expected terminator. Causes: wrong key/IV, mode mismatch, the data was not BIT-padded, or the terminator was itself corrupted.
Common situations: Decrypting data encrypted with a different padding (PKCS5/ZERO) but declaring "BIT"; bit errors in the final block; interop with a system that uses a different bit-padding convention.
Related errors
- Invalid PKCS#5 padding.
- No padding requested but input is not a ${blockSize}-byte mu
- Unknown padding type: ${padding}
- Invalid ciphertext length: ${originalLength} bytes. Must be
- Unable to decrypt input with these parameters.
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/5fe73fcb7eb18a65.
Report an issue: GitHub.