gchq/CyberChef · error · OperationError

Invalid BIT padding.

Error message

Invalid BIT padding.

What it means

Thrown by RC6.removePadding for BIT (ISO/IEC 9797-1 padding method 2) when, scanning backwards, the decoder encounters a non-zero byte that is not the 0x80 terminator before finding the terminator — meaning the padding pattern is malformed. Also thrown if the scan completes with no 0x80 byte at all.

Source

Thrown at src/core/lib/RC6.mjs:429

            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 RC6 cipher with specified block mode
 *
 * @param {number[]} message - Plaintext as byte array
 * @param {number[]} key - Key as byte array
 * @param {number[]} iv - IV (block size 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

  1. Verify key/IV and that the sender actually used BIT padding.
  2. Decrypt with 'NO' and inspect the tail to confirm a 0x80 terminator exists.
  3. Switch the padding argument to match the sender's scheme.

Example fix

// before: decrypt as BIT though data is PKCS5
const pt = decryptRC6(ct, key, iv, 'CBC', 'BIT');
// after
const pt = decryptRC6(ct, key, iv, 'CBC', 'PKCS5');
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try {
  return decryptRC6(ct, key, iv, mode, 'BIT', rounds, w);
} catch (e) {
  if (e instanceof OperationError && /Invalid BIT padding/.test(e.message)) {
    // confirm sender used BIT; otherwise decrypt with 'NO' to inspect tail
    return decryptRC6(ct, key, iv, mode, 'NO', rounds, w);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling decryptRC6(...) with padding 'BIT' on plaintext whose tail is not a valid bit-padding sequence (0x80 followed by zero or more 0x00 bytes).

Common situations: Wrong key/IV producing random tail bytes; data padded with a different scheme but decrypted as BIT; message that legitimately ends in non-zero bytes with no 0x80 terminator; ciphertext truncated so the 0x80 byte is lost.

Related errors


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