Decrypt with user-specified alphabet; allow user to input inverse coefficients

This commit is contained in:
Barry Brown 2024-06-13 06:44:48 +00:00
parent 41585e0d3d
commit ede3dc7471

View file

@ -5,8 +5,7 @@
*/ */
import Operation from "../Operation.mjs"; import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs"; import { affineDecrypt, affineDecryptInverse, AFFINE_ALPHABETS } from "../lib/Ciphers.mjs";
import OperationError from "../errors/OperationError.mjs";
/** /**
* Affine Cipher Decode operation * Affine Cipher Decode operation
@ -36,6 +35,11 @@ class AffineCipherDecode extends Operation {
"type": "number", "type": "number",
"value": 0 "value": 0
}, },
{
"name": "Alphabet",
"type": "editableOption",
"value": AFFINE_ALPHABETS
},
{ {
"name": "Use modular inverse values", "name": "Use modular inverse values",
"type": "boolean", "type": "boolean",
@ -52,43 +56,9 @@ class AffineCipherDecode extends Operation {
* @throws {OperationError} if a or b values are invalid * @throws {OperationError} if a or b values are invalid
*/ */
run(input, args) { run(input, args) {
const alphabet = "abcdefghijklmnopqrstuvwxyz", const a = args[0], b = args[1], alphabet = args[2], useInverse = args[3];
[a, b, useInv] = args, if (useInverse) return affineDecryptInverse(input, a, b, alphabet);
aModInv = Utils.modInv(a, 26); // Calculates modular inverse of a else return affineDecrypt(input, a, b, alphabet);
let output = "";
if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
throw new OperationError("The values of a and b can only be integers.");
}
if (Utils.gcd(a, 26) !== 1) {
throw new OperationError("The value of `a` must be coprime to 26.");
}
for (let i = 0; i < input.length; i++) {
if (alphabet.indexOf(input[i]) >= 0) {
if (useInv) {
// Uses the affine decode function (y+b)*a % m, where m is the length
// of the alphabet and a,b are modular inverses of the original a,b
output += alphabet[Utils.mod((alphabet.indexOf(input[i]) + b) * a, 26)];
} else {
// Uses the affine decode function (y-b * A') % m = x (where m is length of the alphabet and A' is modular inverse)
output += alphabet[Utils.mod((alphabet.indexOf(input[i]) - b) * aModInv, 26)];
}
} else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
if (useInv) {
// Same as above, accounting for uppercase
output += alphabet[Utils.mod((alphabet.indexOf(input[i].toLowerCase()) + b) * a, 26)].toUpperCase();
} else {
// Same as above, accounting for uppercase
output += alphabet[Utils.mod((alphabet.indexOf(input[i].toLowerCase()) - b) * aModInv, 26)].toUpperCase();
}
} else {
// Non-alphabetic characters
output += input[i];
}
}
return output;
} }
/** /**