{"record":{"id":"0dfad9e7e5d17986","repo":"gchq/CyberChef","slug":"no-padding-requested-in-mode-mode-but-input-is","errorCode":null,"errorMessage":"No padding requested in ${mode} mode but input is not a 16-byte multiple.","messagePattern":"No padding requested in (.+?) mode but input is not a 16-byte multiple\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/SM4.mjs","lineNumber":174,"sourceCode":" * @param {byteArray} key - The cipher key, 16 bytes.\n * @param {byteArray} iv - The IV or nonce, 16 bytes (not used with ECB mode)\n * @param {string} mode - The block cipher mode \"CBC\", \"ECB\", \"CFB\", \"OFB\", \"CTR\".\n * @param {boolean} noPadding - Don't add PKCS#7 padding if set.\n * @returns {byteArray} - The cipher text.\n */\nexport function encryptSM4(message, key, iv, mode=\"ECB\", noPadding=false) {\n    const messageLength = message.length;\n    if (messageLength === 0)\n        return [];\n    const roundKey = initSM4RoundKey(bytesToInts(key, 0));\n\n    /* Pad with PKCS#7 if requested for ECB/CBC else add zeroes (which are sliced off at the end) */\n    let padByte = 0;\n    let nPadding = 16 - (message.length & 0xF);\n    if (mode === \"ECB\" || mode === \"CBC\") {\n        if (noPadding) {\n            if (nPadding !== 16)\n                throw new OperationError(`No padding requested in ${mode} mode but input is not a 16-byte multiple.`);\n            nPadding = 0;\n        } else\n            padByte = nPadding;\n    }\n    for (let i = 0; i < nPadding; i++)\n        message.push(padByte);\n\n    const cipherText = [];\n    switch (mode) {\n        case \"ECB\":\n            for (let i = 0; i < message.length; i += BLOCKSIZE)\n                Array.prototype.push.apply(cipherText, intsToBytes(encryptBlockSM4(bytesToInts(message, i), roundKey)));\n            break;\n        case \"CBC\":\n            iv = bytesToInts(iv, 0);\n            for (let i = 0; i < message.length; i += BLOCKSIZE) {\n                const block = bytesToInts(message, i);\n                block[0] ^= iv[0]; block[1] ^= iv[1];","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/SM4.mjs#L156-L192","documentation":"encryptSM4 at SM4.mjs:174 guards the noPadding path. In ECB/CBC the input must already be a whole number of 16-byte blocks because the cipher cannot stream or truncate; with noPadding=true and any remainder, encryption is refused rather than silently mis-padding.","triggerScenarios":"encryptSM4(message, key, iv, mode='ECB'|'CBC', noPadding=true) where message.length % 16 != 0. Typical cause: caller deliberately disabled PKCS#7 padding but supplied a message that is not block-aligned.","commonSituations":"Protocol that requires no padding on the wire but the framing layer did not pre-pad to 16 bytes; toggling noPadding to avoid PKCS#7 overhead without aligning the payload; batch processing of variable-length records fed straight into ECB.","solutions":["Pre-pad the message to a 16-byte multiple yourself (e.g. with explicit zero bytes) before calling encryptSM4 with noPadding=true.","Or set noPadding=false to let the library apply PKCS#7 automatically.","Validate message.length % 16 === 0 up front so the failure is reported at the trust boundary, not deep in the cipher."],"exampleFix":"// before\nconst ct = encryptSM4(msg, key, iv, \"CBC\", true); // msg is 17 bytes\n// after: align to block boundary explicitly\nconst aligned = msg.concat(new Array((16 - msg.length % 16) % 16).fill(0));\nconst ct = encryptSM4(aligned, key, iv, \"CBC\", true);","handlingStrategy":"validation","validationCode":"function assertSm4NoPaddingAligned(message, noPadding, mode) {\n  if (noPadding && (mode === \"ECB\" || mode === \"CBC\")) {\n    if (message.length & 0xF)\n      throw new TypeError(\n        `noPadding requires a 16-byte multiple; got ${message.length} bytes`);\n  }\n}","typeGuard":"function isSm4BlockAligned(bytes) {\n  return Number.isInteger(bytes.length) && (bytes.length & 0xF) === 0;\n}","tryCatchPattern":"import OperationError from \"../errors/OperationError.mjs\";\ntry {\n  assertSm4NoPaddingAligned(msg, noPadding, mode);\n  const ct = encryptSM4(msg, key, iv, mode, noPadding);\n} catch (e) {\n  if (e instanceof OperationError && /No padding requested/.test(e.message)) {\n    // either pre-pad the message or enable PKCS#7\n  } else throw e;\n}","preventionTips":["If you need noPadding in ECB/CBC, pre-align the message to a 16-byte multiple.","Otherwise leave noPadding=false to use PKCS#7 automatically.","Centralise the alignment rule so encrypt and decrypt cannot disagree."],"tags":["sm4","cipher","padding","block-mode","validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}