gchq/CyberChef · error · OperationError
input must be 8n (n>=2) bytes (currently " + inputData.lengt
Error message
input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)
What it means
RFC 3394 requires the key material being wrapped to be at least 2 blocks (n≥2), i.e. a multiple of 8 bytes and ≥ 16 bytes. AESKeyWrap throws this when inputData.length % 8 !== 0 or inputData.length < 16. (Compare with unwrap, which needs ≥ 24 because the wrapped form adds one IV block.)
Source
Thrown at src/core/operations/AESKeyWrap.mjs:75
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const kek = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteString(args[1].string, args[1].option),
inputType = args[2],
outputType = args[3];
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
}
if (iv.length !== 8) {
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
}
const inputData = Utils.convertToByteString(input, inputType);
if (inputData.length % 8 !== 0 || inputData.length < 16) {
throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)");
}
const cipher = forge.cipher.createCipher("AES-ECB", kek);
let A = iv;
const R = [];
for (let i = 0; i < inputData.length; i += 8) {
R.push(inputData.substring(i, i + 8));
}
let cntLower = 1, cntUpper = 0;
for (let j = 0; j < 6; j++) {
for (let i = 0; i < R.length; i++) {
cipher.start();
cipher.update(forge.util.createBuffer(A + R[i]));
cipher.finish();
const B = cipher.output.getBytes();
const msbBuffer = Utils.strToArrayBuffer(B.substring(0, 8));
const msbView = new DataView(msbBuffer);View on GitHub (pinned to 4290ea7539)
Solutions
- Confirm the input is the raw key material (e.g. a 16/24/32-byte AES key) you intend to protect.
- Verify the input format option and that decoding yields a multiple of 8 bytes ≥ 16.
- If you genuinely have an 8-byte key, note RFC 3394 disallows it — use a different wrapping scheme or pad per your protocol.
Example fix
// before: wrap an 8-byte DES key → throws (n must be ≥2) // after: wrap a 16/24/32-byte AES key instead
Defensive patterns
Strategy: validation
Validate before calling
function validateKeyMaterial(bytes) {
if (bytes.length % 8 !== 0 || bytes.length < 16) {
throw new Error(`Key material must be 8n (n>=2) bytes, got ${bytes.length}`);
}
} Type guard
function isWrappableKey(bytes) { return bytes.length >= 16 && bytes.length % 8 === 0; } Try / catch
try { aesKeyWrap(...); } catch (e) { if (/input must be 8n/.test(e.message)) {/* supply ≥16-byte key material */} else throw e; } Prevention
- Wrap key material of at least 2 blocks (≥16 bytes).
- Verify format option yields a multiple of 8 bytes ≥ 16.
- RFC 3394 disallows a single 8-byte block — use another scheme for DES-size keys.
When it happens
Trigger: The key-data input is not a multiple of 8 bytes, or is shorter than 16 bytes. For example, trying to wrap a single 8-byte block, or feeding an odd-length hex string that decodes to a non-multiple-of-8 byte count.
Common situations: Attempting to wrap a DES-size (8-byte) key (too small); format-option mismatch producing wrong byte count; truncated key material; user fed already-wrapped data by mistake.
Related errors
- input must be 8n (n>=3) bytes (currently " + inputData.lengt
- KEK must be either 16, 24, or 32 bytes (currently " + kek.le
- IV must be 8 bytes (currently " + iv.length + " bytes)
- KEK must be either 16, 24, or 32 bytes (currently " + kek.le
- IV must be 8 bytes (currently " + iv.length + " bytes)
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/dba9a9f185fcf561.
Report an issue: GitHub.