gchq/CyberChef · error · OperationError

Invalid BIT padding.

Error message

Invalid BIT padding.

What it means

removePadding BIT (ISO 7816-4) branch walks backwards from the end expecting zero bytes followed by a single 0x80 terminator. If a non-zero, non-0x80 byte is encountered first, the padding is not a valid BIT sequence and decryption is rejected. Symptom of a wrong key or corrupted tail.

Source

Thrown at src/core/lib/Present.mjs:309

            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 PRESENT cipher with specified block mode
 *
 * @param {number[]} message - Plaintext as byte array
 * @param {number[]} key - Key (10 bytes for 80-bit or 16 bytes for 128-bit)
 * @param {number[]} iv - IV (8 bytes, not used for ECB)
 * @param {string} mode - Block cipher mode ("ECB" or "CBC")
 * @param {string} padding - Padding type ("NO", "PKCS5", "ZERO", "RANDOM", "BIT")

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Verify the key matches the encrypting side exactly.
  2. Confirm BIT padding was used to encrypt; if not, pass the matching padding type.
  3. Decrypt with padding='NO' and inspect the tail bytes for a 0x80 marker.
  4. Check the IV and ciphertext integrity in CBC mode.

Example fix

// before
const pt = decryptPRESENT(ct, key, iv, 'CBC', 'BIT'); // tail has stray byte -> error

// after
const raw = decryptPRESENT(ct, key, iv, 'CBC', 'NO');
console.log(raw.slice(-8)); // look for 0x80 terminator
// if no 0x80 present, try the actual scheme:
const pt = decryptPRESENT(ct, key, iv, 'CBC', 'PKCS5');
Defensive patterns

Strategy: try-catch

Validate before calling

function hasValidBITPadding(bytes) {
  for (let i = bytes.length - 1; i >= 0; i--) {
    if (bytes[i] === 0x80) return true;
    if (bytes[i] !== 0) return false;
  }
  return false;
}

const raw = decryptPRESENT(ct, key, iv, mode, 'NO');
if (!hasValidBITPadding(raw)) throw new Error('Wrong key or non-BIT-padded source');

Try / catch

try {
  return decryptPRESENT(ct, key, iv, mode, 'BIT');
} catch (e) {
  if (!/BIT padding/.test(e.message)) throw e;
  const raw = decryptPRESENT(ct, key, iv, mode, 'NO');
  throw new Error('No valid BIT padding found; key is probably wrong or scheme is not BIT');
}

Prevention

When it happens

Trigger: Calling decryptPRESENT(..., 'BIT') where the decrypted tail contains arbitrary non-zero bytes before any 0x80 marker. Typical with wrong key/IV, or when the data was not BIT-padded.

Common situations: Wrong key producing random plaintext; BIT padding not actually used on the encrypt side (e.g. PKCS5 was); corrupted final ciphertext block; mismatched IV in CBC mode.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/a2c50b0ec0bf4323. Report an issue: GitHub.