{"record":{"id":"8bb28b98c4272177","repo":"gchq/CyberChef","slug":"the-value-of-a-must-be-coprime-to-26","errorCode":null,"errorMessage":"The value of `a` must be coprime to 26.","messagePattern":"The value of `a` must be coprime to 26\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Ciphers.mjs","lineNumber":36,"sourceCode":" * Affine Cipher Encode operation.\n *\n * @author Matt C [matt@artemisbot.uk]\n * @param {string} input\n * @param {Object[]} args\n * @returns {string}\n */\nexport function affineEncode(input, args) {\n    const alphabet = \"abcdefghijklmnopqrstuvwxyz\",\n        a = args[0],\n        b = args[1];\n    let output = \"\";\n\n    if (!/^\\+?(0|[1-9]\\d*)$/.test(a) || !/^\\+?(0|[1-9]\\d*)$/.test(b)) {\n        throw new OperationError(\"The values of a and b can only be integers.\");\n    }\n\n    if (Utils.gcd(a, 26) !== 1) {\n        throw new OperationError(\"The value of `a` must be coprime to 26.\");\n    }\n\n    for (let i = 0; i < input.length; i++) {\n        if (alphabet.indexOf(input[i]) >= 0) {\n            // Uses the affine function ax+b % m = y (where m is length of the alphabet)\n            output += alphabet[((a * alphabet.indexOf(input[i])) + b) % 26];\n        } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {\n            // Same as above, accounting for uppercase\n            output += alphabet[((a * alphabet.indexOf(input[i].toLowerCase())) + b) % 26].toUpperCase();\n        } else {\n            // Non-alphabetic characters\n            output += input[i];\n        }\n    }\n    return output;\n}\n\n/**","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Ciphers.mjs#L18-L54","documentation":"Thrown by affineEncode when the multiplier `a` is not coprime to 26 (the alphabet length). The affine cipher maps each letter x to (a*x + b) mod 26, and this map is only a bijection (hence invertible for decoding) when a and 26 share no common factor. Coprime-to-26 values of a are exactly {1,3,5,7,9,11,15,17,19,21,23,25}; every even number and every multiple of 13 fails.","triggerScenarios":"affineEncode(input, [a, b]) is called with a being even (e.g. 2, 4, 26) or a multiple of 13 (13, 39). The check Utils.gcd(a, 26) !== 1 fires before any character is processed, so even valid-looking text throws on the first call.","commonSituations":"Developer copies an example key pair where a=2 or a=10; auto-generating random affine keys without filtering for coprimality; treating a as any integer rather than a unit mod 26; passing a=0 (also rejected because gcd(0,26)=26).","solutions":["Choose a from the set coprime to 26: 1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25.","When generating keys randomly, loop until Utils.gcd(candidate, 26) === 1.","Verify the key pair before invoking affineEncode (see validationCode)."],"exampleFix":"// before\naffineEncode(text, [2, 3]); // gcd(2,26)=2 -> throws\n\n// after\naffineEncode(text, [5, 8]); // gcd(5,26)=1 -> ok","handlingStrategy":"validation","validationCode":"import Utils from \".../Utils.mjs\";\nfunction isValidAffineA(a) {\n  return Number.isInteger(a) && Utils.gcd(a, 26) === 1;\n}\n// call site:\nif (!isValidAffineA(a)) {\n  throw new Error(`a=${a} is not coprime to 26; use one of 1,3,5,7,9,11,15,17,19,21,23,25`);\n}\naffineEncode(input, [a, b]);","typeGuard":"function isCoprimeTo26(a) {\n  return Number.isInteger(a) && a > 0 && Utils.gcd(a, 26) === 1;\n}","tryCatchPattern":null,"preventionTips":["Maintain a constant COPRIME_A = [1,3,5,7,9,11,15,17,19,21,23,25] and select from it.","When generating random keys, retry until gcd(a,26)===1 rather than accepting the first draw.","Never use even values or multiples of 13 for a."],"tags":["cryptography","affine-cipher","input-validation","math"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}