gchq/CyberChef · error · OperationError

Invalid IV length: ${iv.length} bytes XTEA uses an IV lengt

Error message

Invalid IV length: ${iv.length} bytes

XTEA uses an IV length of ${TEA_BLOCK_SIZE} bytes (${TEA_BLOCK_SIZE * 8} bits).
Make sure you have specified the type correctly (e.g. Hex vs UTF8).

What it means

Thrown by XTEADecrypt.run when the IV length is not the TEA block size, not zero, and the mode is not ECB. An empty IV is allowed (and later zero-padded), and ECB mode ignores the IV; every other mode requires an IV equal to the block size (8 bytes for TEA).

Source

Thrown at src/core/operations/XTEADecrypt.mjs:90

    /**
     * @param {string} input
     * @param {Object[]} args
     * @returns {string}
     */
    run(input, args) {
        const key = Utils.convertToByteArray(args[0].string, args[0].option),
            iv = Utils.convertToByteArray(args[1].string, args[1].option),
            [,, mode, inputType, outputType, padding, rounds] = args;

        if (key.length !== 16)
            throw new OperationError(`Invalid key length: ${key.length} bytes

XTEA requires a key length of 16 bytes (128 bits).
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);

        if (iv.length !== TEA_BLOCK_SIZE && iv.length !== 0 && mode !== "ECB")
            throw new OperationError(`Invalid IV length: ${iv.length} bytes

XTEA uses an IV length of ${TEA_BLOCK_SIZE} bytes (${TEA_BLOCK_SIZE * 8} bits).
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);

        if (!Number.isInteger(rounds) || rounds < 1 || rounds > 255)
            throw new OperationError(`Invalid number of rounds: ${rounds}

Rounds must be an integer between 1 and 255. Standard XTEA uses 32 rounds.`);

        // Default IV to null bytes if empty (like AES)
        const actualIv = iv.length === 0 ? new Array(TEA_BLOCK_SIZE).fill(0) : iv;

        input = Utils.convertToByteArray(input, inputType);
        const output = decryptXTEA(input, key, actualIv, mode, padding, rounds);
        return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
    }

}

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Use an 8-byte IV (16 hex chars) for non-ECB XTEA modes.
  2. Leave the IV empty if you want it auto-zero-padded.
  3. For ECB mode the IV is ignored, so set mode to 'ECB' if you have no IV.
  4. Align the IV format option with the actual IV encoding.

Example fix

// before: 32 hex chars -> 16-byte IV, CBC mode -> fails
args:[key,{string:"<32 hex>",option:"Hex"}, "CBC", ...]
// after: 16 hex chars -> 8-byte IV
args:[key,{string:"<16 hex>",option:"Hex"}, "CBC", ...]
Defensive patterns

Strategy: validation

Validate before calling

const TEA_BLOCK_SIZE = 8;
function xteaIvRecipe(ivStr, ivOption, mode) {
  if (mode === "ECB") return {string:ivStr, option:ivOption};
  const iv = Utils.convertToByteArray(ivStr, ivOption);
  if (iv.length !== 0 && iv.length !== TEA_BLOCK_SIZE) throw new Error(`IV must be ${TEA_BLOCK_SIZE} bytes or empty`);
  return {string:ivStr, option:ivOption};
}

Type guard

const isValidXteaIv = (bytes, mode) => mode === "ECB" || bytes.length === 0 || bytes.length === 8;

Try / catch

try { chef.bake(data, recipe); } catch (e) { if (/Invalid IV length/.test(e.message) && /XTEA/.test(e.message)) { /* fix iv or switch mode */ } else throw e; }

Prevention

When it happens

Trigger: args[1] (the IV) decoded is a non-zero length that is not TEA_BLOCK_SIZE (8 bytes) while mode is CBC/CFB/OFB/etc. Example: a 16-byte AES-style IV with XTEA in CBC mode fails.

Common situations: Reusing an IV from another cipher (AES = 16 bytes) with XTEA (8 bytes); selecting ECB-vs-CBC inconsistently between encrypt and decrypt; Hex/UTF8 format mismatch on the IV.

Related errors


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