/** * @author p-leriche [philip.leriche@cantab.net] * @copyright Crown Copyright 2025 * @license Apache-2.0 */ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import { parseBigInt, egcd } from "../lib/BigIntUtils.mjs"; /* ---------- operation class ---------- */ /** * Modular Inverse operation */ class ModularInverse extends Operation { /** * ModularInverse constructor */ constructor() { super(); this.name = "Modular Inverse"; this.module = "Crypto"; this.description = "Computes the modular multiplicative inverse of a modulo m.

" + "Finds x such that a*x = 1 (mod m).

" + "Input handling: If either a or m is left blank, " + "its value is taken from the Input field."; this.infoURL = "https://wikipedia.org/wiki/Modular_multiplicative_inverse"; this.inputType = "string"; this.outputType = "string"; this.args = [ { name: "Value (a)", type: "string", value: "" }, { name: "Modulus (m)", type: "string", value: "" } ]; } /** * @param {string} input * @param {Object[]} args * @returns {string} */ run(input, args) { const [aStr, mStr] = args; // Trim everything so "" and " " count as empty const aParam = aStr?.trim(); const mParam = mStr?.trim(); const inputVal = input?.trim(); let a, m; if (aParam && mParam) { // Case 1: value and modulus both given as parameters a = aParam; m = mParam; } else if (!aParam && mParam) { // Case 2: value missing - take from input a = inputVal; m = mParam; if (!a) throw new OperationError("Value (a) must be defined"); } else if (aParam && !mParam) { // Case 3: modulus missing - take from input a = aParam; m = inputVal; if (!m) throw new OperationError("Modulus (m) must be defined"); } else if (!aParam && !mParam) { // Case 4: value and modulus both missing throw new OperationError("Value (a) and Modulus (m) must be defined"); } const aBI = parseBigInt(a, "Value (a)"); const mBI = parseBigInt(m, "Modulus (m)"); if (mBI <= 0n) { throw new OperationError("Modulus must be greater than zero"); } const aNorm = ((aBI % mBI) + mBI) % mBI; const [g, x] = egcd(aNorm, mBI); if (g !== 1n && g !== -1n) { throw new OperationError("Inverse does not exist because gcd(a, m) ≠ 1"); } let inv = x; if (g === -1n) inv = -inv; inv = ((inv % mBI) + mBI) % mBI; return inv.toString(); } } export default ModularInverse;