gchq/CyberChef · error · OperationError

IV must be 8 bytes (currently " + iv.length + " bytes)

Error message

IV must be 8 bytes (currently " + iv.length + " bytes)

What it means

RFC 3394 AES key wrap uses a fixed 8-byte IV (initial value / integrity check register), conventionally A6A6A6A6A6A6A6A6. AESKeyUnwrap requires args[1] to convert to exactly 8 bytes and throws otherwise. The IV length is independent of the KEK size.

Source

Thrown at src/core/operations/AESKeyUnwrap.mjs:71

        ];
    }

    /**
     * @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 < 24) {
            throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)");
        }

        const cipher = forge.cipher.createCipher("AES-ECB", kek);
        cipher.start();
        cipher.update(forge.util.createBuffer(""));
        cipher.finish();
        const paddingBlock = cipher.output.getBytes();

        const decipher = forge.cipher.createDecipher("AES-ECB", kek);

        let A = inputData.substring(0, 8);
        const R = [];
        for (let i = 8; i < inputData.length; i += 8) {
            R.push(inputData.substring(i, i + 8));

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Provide the standard 8-byte IV A6A6A6A6A6A6A6A6 with the IV format set to Hex (→ 8 bytes).
  2. If the wrap used a non-default IV, supply exactly that 8-byte value in the matching format.
  3. Double-check the IV format option matches the string you pasted.

Example fix

// before: IV "A6A6A6A6A6A6A6A6" format UTF8 → 16 bytes → throws
// after: set IV format to "Hex" → 8 bytes
Defensive patterns

Strategy: validation

Validate before calling

function validateWrapIv(ivBytes) {
  if (ivBytes.length !== 8) {
    throw new Error(`AES-KW IV must be 8 bytes, got ${ivBytes.length}`);
  }
}

Type guard

function isWrapIv(bytes) { return bytes instanceof Uint8Array && bytes.length === 8; }

Try / catch

try { aesKeyUnwrap(...); } catch (e) { if (/IV must be 8 bytes/.test(e.message)) {/* fix IV format */} else throw e; }

Prevention

When it happens

Trigger: The IV argument converts to a byte string whose length is not 8. E.g. entering the default A6A6A6A6A6A6A6A6 as hex while format is UTF8 (16 bytes), or supplying a 16-byte value by mistake.

Common situations: IV format option (Hex/UTF8) does not match the supplied string; user confused the 8-byte wrap IV with a 16-byte AES-CBC IV; left IV blank.

Related errors


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