gchq/CyberChef · error · OperationError

No padding requested but input is not a

Error message

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

What it means

applyPadding with padding='NO' requires the message length to already be a multiple of the cipher block size (8 bytes for PRESENT). When remainder != 0 the function refuses to invent padding and throws, telling the caller the input is misaligned. This protects against silently truncating or extending plaintext.

Solutions

  1. Switch padding to 'PKCS5' (default and most interoperable) or 'BIT' (ISO 7816-4).
  2. Pre-pad/align the message to a multiple of 8 bytes yourself before using 'NO'.
  3. Use 'ZERO' padding if the receiver can tolerate trailing zero bytes.
  4. Confirm PRESENT's 8-byte block size matches the peer implementation's expectation.

Example fix

// before
encryptPRESENT([1,2,3], key, iv, 'ECB', 'NO'); // 3 bytes -> error

// after
encryptPRESENT([1,2,3], key, iv, 'ECB', 'PKCS5'); // auto-padded to 8
// or align manually:
const padded = [...msg];
while (padded.length % 8) padded.push(0);
encryptPRESENT(padded, key, iv, 'ECB', 'NO');
Defensive patterns

Strategy: validation

Validate before calling

const BLOCKSIZE = 8;
function encryptPresentSafe(msg, key, iv, mode, padding) {
  if (padding === 'NO' && msg.length % BLOCKSIZE !== 0) {
    throw new Error('Input is not a multiple of 8 bytes; use PKCS5 or align manually.');
  }
  return encryptPRESENT(msg, key, iv, mode, padding);
}

Try / catch

try {
  return encryptPRESENT(msg, key, iv, mode, padding);
} catch (e) {
  if (/No padding requested/.test(e.message)) {
    // recover by switching to PKCS5
    return encryptPRESENT(msg, key, iv, mode, 'PKCS5');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling encryptPRESENT(message, key, iv, 'ECB'|'CBC', 'NO') where message.length % 8 !== 0. Typical with arbitrary-length text or partial buffers.

Common situations: User selects 'No padding' in a recipe but supplies non-block-aligned input; interop with another cipher implementation that expects zero-padding; forgetting that PRESENT block size is 8 bytes (not 16 like AES).

Related errors


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

Appendix: source

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

 * @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)