gchq/CyberChef · error · OperationError

No padding requested but input is not a ${blockSize}-byte mu

Error message

No padding requested but input is not a ${blockSize}-byte multiple.

What it means

Thrown by applyPadding() in Twofish.mjs when padding is "NO" but the message length is not a multiple of the 16-byte Twofish block size. ECB and CBC modes require block-aligned input; selecting "NO" padding is a promise that the caller has already aligned the data, and the function refuses to silently misalign it.

Source

Thrown at src/core/lib/Twofish.mjs:353

 * @param {number} blockSize - Block size in bytes
 * @returns {number[]} - Padded message
 */
function applyPadding(message, padding, blockSize) {
    const remainder = message.length % blockSize;
    let nPadding = remainder === 0 ? 0 : blockSize - remainder;

    // For PKCS5, always add at least one byte (full block if already aligned)
    if (padding === "PKCS5" && remainder === 0) {
        nPadding = blockSize;
    }

    if (nPadding === 0) return [...message];

    const paddedMessage = [...message];

    switch (padding) {
        case "NO":
            throw new OperationError(`No padding requested but input is not a ${blockSize}-byte multiple.`);

        case "PKCS5":
            for (let i = 0; i < nPadding; i++) {
                paddedMessage.push(nPadding);
            }
            break;

        case "ZERO":
            for (let i = 0; i < nPadding; i++) {
                paddedMessage.push(0);
            }
            break;

        case "RANDOM":
            for (let i = 0; i < nPadding; i++) {
                paddedMessage.push(Math.floor(Math.random() * 256));
            }
            break;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Use "PKCS5" padding (the default) for variable-length messages so the library can align them for you.
  2. If you must use "NO", pre-pad or pre-truncate the message so message.length % 16 === 0 before calling encryptTwofish.
  3. Switch to a stream mode (CFB/OFB/CTR) which does not require block alignment and ignores the padding argument.

Example fix

// before
encryptTwofish(msg, key, iv, "ECB", "NO"); // msg is 20 bytes
// after
encryptTwofish(msg, key, iv, "ECB", "PKCS5");
Defensive patterns

Strategy: validation

Validate before calling

const BLOCK = 16; // Twofish
if ((mode === "ECB" || mode === "CBC") && padding === "NO" && msg.length % BLOCK !== 0) {
    throw new Error(
        `Message is ${msg.length} bytes; 'NO' padding requires a multiple of ${BLOCK}. ` +
        `Use 'PKCS5' or pre-align the data.`
    );
}
encryptTwofish(msg, key, iv, mode, padding);

Type guard

function canUseNoPadding(msg, mode, blockSize = 16) {
    return mode !== "ECB" && mode !== "CBC" || msg.length % blockSize === 0;
}

Try / catch

try {
    ct = encryptTwofish(msg, key, iv, mode, padding);
} catch (e) {
    if (e instanceof OperationError && /No padding requested/.test(e.message)) {
        // auto-upgrade to PKCS5 or pre-pad the message
        ct = encryptTwofish(msg, key, iv, mode, "PKCS5");
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling encryptTwofish() with mode "ECB" or "CBC" and padding "NO" on a message whose length % 16 !== 0. Hit when a caller wants to avoid padding overhead but supplies plaintext that does not fit whole blocks, or when "NO" was selected by mistake instead of "PKCS5".

Common situations: Interoperating with a system that uses no padding but expects block-aligned input; defaulting to "NO" in a UI without ensuring alignment; encrypting variable-length fields with ECB.

Related errors


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