{"record":{"id":"c42e7a65ee41df0f","repo":"gchq/CyberChef","slug":"wrong-key-size","errorCode":null,"errorMessage":"Wrong key size","messagePattern":"Wrong key size","errorType":"validation","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/LS47.mjs","lineNumber":99,"sourceCode":"export function deriveKey(password) {\n    let i = 0;\n    let k = letters;\n    for (const c of password) {\n        const [row, col] = findIx(c);\n        k = rotateDown(rotateRight(k, i, col), i, row);\n        i = (i + 1) % 7;\n    }\n    return k;\n}\n\n/**\n * Checks the key is a valid key.\n *\n * @param {string} key\n */\nfunction checkKey(key) {\n    if (key.length !== letters.length)\n        throw new OperationError(\"Wrong key size\");\n    const counts = new Array();\n    for (let i = 0; i < letters.length; i++)\n        counts[letters.charAt(i)] = 0;\n    for (const elem of letters) {\n        if (letters.indexOf(elem) === -1)\n            throw new OperationError(\"Letter \" + elem + \" not in LS47\");\n        counts[elem]++;\n        if (counts[elem] > 1)\n            throw new OperationError(\"Letter duplicated in the key\");\n    }\n}\n\n/**\n * Finds the position of a letter in they key.\n *\n * @param {letter} key\n * @param {string} letter\n * @returns {object}","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/LS47.mjs#L81-L117","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst ct = LS47.encrypt(myPassword, plaintext); // raw password -> Wrong key size\n\n// after\nLS47.initTiles();\nconst key = LS47.deriveKey(myPassword);    // 49-char permutation\nconst ct = LS47.encrypt(key, plaintext);","handlingStrategy":"validation","validationCode":"import { initTiles, deriveKey } from './LS47.mjs';\n\nfunction validLS47Key(key) {\n  const ALPHABET = \"_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()\";\n  return typeof key === 'string' &&\n         key.length === 49 &&\n         new Set(key).size === 49 &&\n         [...key].every(c => ALPHABET.includes(c));\n}\n\n// use before encrypt/decrypt/encryptPad/decryptPad\ninitTiles();\nconst key = validLS47Key(myKey) ? myKey : deriveKey(passphrase);","typeGuard":"function isLS47Key(x): x is string {\n  if (typeof x !== 'string' || x.length !== 49) return false;\n  const ALPHABET = \"_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()\";\n  return new Set(x).size === 49 && [...x].every(c => ALPHABET.includes(c));\n}","tryCatchPattern":"try {\n  const ct = LS47.encrypt(key, plaintext);\n} catch (e) {\n  if (e instanceof OperationError && /Wrong key size/.test(e.message)) {\n    throw new Error('LS47 key must be a 49-character permutation; use deriveKey().');\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["cryptography","ls47","validation","user-input"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}