gchq/CyberChef · error · OperationError
Wrong key size
Error message
Wrong key size
What it means
LS47 is a 7x7 tile-based substitution cipher using a fixed 49-character alphabet (letters = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()"). The key must be a permutation of exactly those 49 characters. checkKey() rejects any key whose length differs from letters.length (49). This guard runs at the start of encrypt/decrypt/encryptPad/decryptPad before any cryptographic work.
Source
Thrown at src/core/lib/LS47.mjs:99
export function deriveKey(password) {
let i = 0;
let k = letters;
for (const c of password) {
const [row, col] = findIx(c);
k = rotateDown(rotateRight(k, i, col), i, row);
i = (i + 1) % 7;
}
return k;
}
/**
* Checks the key is a valid key.
*
* @param {string} key
*/
function checkKey(key) {
if (key.length !== letters.length)
throw new OperationError("Wrong key size");
const counts = new Array();
for (let i = 0; i < letters.length; i++)
counts[letters.charAt(i)] = 0;
for (const elem of letters) {
if (letters.indexOf(elem) === -1)
throw new OperationError("Letter " + elem + " not in LS47");
counts[elem]++;
if (counts[elem] > 1)
throw new OperationError("Letter duplicated in the key");
}
}
/**
* Finds the position of a letter in they key.
*
* @param {letter} key
* @param {string} letter
* @returns {object}View on GitHub (pinned to 4290ea7539)
Solutions
- Generate the key with deriveKey(password) (exported from LS47.mjs) which always returns a valid 49-char permutation.
- Verify key.length === 49 before calling encrypt/decrypt and surface a clearer error to the end user.
- Strip whitespace/newlines from the key (key.replace(/\s/g, '')) before passing it in.
- If you have a hand-built key, confirm it contains exactly one of each of the 49 alphabet characters.
Example fix
// before const ct = LS47.encrypt(myPassword, plaintext); // raw password -> Wrong key size // after LS47.initTiles(); const key = LS47.deriveKey(myPassword); // 49-char permutation const ct = LS47.encrypt(key, plaintext);
Defensive patterns
Strategy: validation
Validate before calling
import { initTiles, deriveKey } from './LS47.mjs';
function validLS47Key(key) {
const ALPHABET = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()";
return typeof key === 'string' &&
key.length === 49 &&
new Set(key).size === 49 &&
[...key].every(c => ALPHABET.includes(c));
}
// use before encrypt/decrypt/encryptPad/decryptPad
initTiles();
const key = validLS47Key(myKey) ? myKey : deriveKey(passphrase); Type guard
function isLS47Key(x): x is string {
if (typeof x !== 'string' || x.length !== 49) return false;
const ALPHABET = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()";
return new Set(x).size === 49 && [...x].every(c => ALPHABET.includes(c));
} Try / catch
try {
const ct = LS47.encrypt(key, plaintext);
} catch (e) {
if (e instanceof OperationError && /Wrong key size/.test(e.message)) {
throw new Error('LS47 key must be a 49-character permutation; use deriveKey().');
}
throw e;
} Prevention
- Always derive the key with deriveKey(password) - never pass a raw password to encrypt/decrypt.
- Store keys verbatim; do not re-encode (hex/base64) without re-validating length.
- Strip whitespace/newlines from keys before use.
- Add a unit test asserting key.length === 49 and Set size 49 for any key you persist.
When it happens
Trigger: Calling encrypt(key, plaintext), decrypt(key, ciphertext), encryptPad(...), or decryptPad(...) with a key string whose .length !== 49. Common offenders: passing a raw password instead of a derived key, passing a hex/base64 key, or a manually typed key missing a character.
Common situations: User passes a human-typed passphrase straight to encrypt() rather than deriveKey(); key copied with a trailing newline or whitespace inflating length; key truncated by a paste operation; using an LS47+ key (longer alphabet) against the plain LS47 routine.
Related errors
- Letter ${letter} is not in the key
- Letter ${elem} not in LS47
- Letter duplicated in the key
- Letter ${letter} is not included in LS47
- Byte length must be a positive integer
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/c42e7a65ee41df0f.
Report an issue: GitHub.