gchq/CyberChef · error · OperationError
Invalid key length: ${key.length} bytes. XSalsa20 uses a ke
Error message
Invalid key length: ${key.length} bytes.
XSalsa20 uses a key of 16 or 32 bytes (128 or 256 bits). What it means
Thrown by XSalsa20.run when the converted key byte array is neither 16 nor 32 bytes long. XSalsa20 accepts only a 128-bit or 256-bit key; any other length is rejected before nonce handling and before hsalsa20/key-stream generation.
Source
Thrown at src/core/operations/XSalsa20.mjs:80
"value": ["Raw", "Hex"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const key = Utils.convertToByteArray(args[0].string, args[0].option),
nonceType = args[1].option,
rounds = parseInt(args[3], 10),
inputType = args[4],
outputType = args[5];
if (key.length !== 16 && key.length !== 32) {
throw new OperationError(`Invalid key length: ${key.length} bytes.
XSalsa20 uses a key of 16 or 32 bytes (128 or 256 bits).`);
}
let counter, nonce;
if (nonceType === "Integer") {
nonce = Utils.intToByteArray(parseInt(args[1].string, 10), 8, "little");
} else {
nonce = Utils.convertToByteArray(args[1].string, args[1].option);
if (!(nonce.length === 24)) {
throw new OperationError(`Invalid nonce length: ${nonce.length} bytes.
XSalsa20 uses a nonce of 24 bytes (192 bits).`);
}
}
counter = Utils.intToByteArray(args[2], 8, "little");
const xsalsaKey = hsalsa20(key, nonce.slice(0, 16), rounds);View on GitHub (pinned to 4290ea7539)
Solutions
- Confirm the key is exactly 16 or 32 bytes when decoded: count raw bytes, not characters.
- Verify the 'Key format' option (args[0].option) matches how the key is encoded — re-paste the key in the matching format.
- Generate a fresh 32-byte key (e.g. 64 hex chars) and select 'Hex', or 32 UTF8 chars and select 'UTF8'.
- If your key source is shorter, expand it via a KDF rather than zero-padding.
Example fix
// before: 24 hex chars = 12 bytes -> invalid
chef.bake(data, [{op:"XSalsa20", args:[{string:"a1b2...24hex",option:"Hex"}, ...]}]);
// after: 64 hex chars = 32 bytes -> valid
chef.bake(data, [{op:"XSalsa20", args:[{string:"<64 hex chars>",option:"Hex"}, ...]}]); Defensive patterns
Strategy: validation
Validate before calling
function xsalsa20KeyRecipe(keyStr, keyOption) {
const key = Utils.convertToByteArray(keyStr, keyOption);
if (key.length !== 16 && key.length !== 32) throw new Error(`XSalsa20 key must be 16 or 32 bytes, got ${key.length}`);
return [{string:keyStr, option:keyOption}];
} Type guard
const isXsalsa20KeyLen = (bytes) => bytes.length === 16 || bytes.length === 32;
Try / catch
try { chef.bake(data, recipe); } catch (e) { if (/Invalid key length/.test(e.message) && /XSalsa20/.test(e.message)) { /* fix key/option */ } else throw e; } Prevention
- Decode the key and assert byte length before building the recipe.
- Keep key format option in sync with the key encoding.
- Generate keys with a trusted RNG at 16/32 bytes.
When it happens
Trigger: args[0].string interpreted via args[0].option (Hex/UTF8/Base64/etc.) produces a byte array whose length is not 16 or 32. Example: a 24-character hex string is only 12 bytes; a 32-char UTF8 key is 32 bytes (valid) but a 16-char UTF8 key is 16 bytes (valid) — anything in between or outside fails.
Common situations: Mismatch between the declared key format and the actual data (Hex vs UTF8 selected wrongly); pasting a Base64 key while 'Hex' is selected; trimming/padding the key; using an AES-128 (16-byte) key with the intent of 256-bit.
Related errors
- Invalid nonce length: ${nonce.length} bytes. XSalsa20 uses
- Invalid key length: ${key.length} bytes XTEA requires a key
- Invalid key length: ${key.length} bytes XTEA requires a key
- Invalid key length: ${key.length} bytes. Ascon-AEAD128 requ
- Invalid key length: ${key.length} bytes. Ascon-AEAD128 requ
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/5475e82082903f88.
Report an issue: GitHub.