UNPKG

mima-kit

Version:

mima-kit is a cryptographic suite implemented in TypeScript. The goal is to provide an easy-to-use cryptographic library. mima-kit 是一个使用 TypeScript 实现的密码学套件。目标是提供一个简单易用的密码学库。

192 lines (191 loc) 5.37 kB
import { KitError, mod, modInverse, modPow, modPrimeSquareRoot } from './utils'; // * Galois Field /** * 素域 * * Prime Field * * @param {bigint} p - 素数 / prime number */ export function GF(p) { const _mod = (a) => mod(a, p); // 乘法逆元 const inv = (a) => modInverse(a, p); // 指数运算 const pow = (a, b) => modPow(a, b, p); // 模素平方根 const root = (a) => modPrimeSquareRoot(a, p); // 素域加法 const add = (...args) => args.reduce((acc, cur) => _mod(acc + cur)); // 素域减法 const sub = (a, ...args) => { const b = args.map((v) => _mod(p - v)); return add(a, ...b); }; // 素域乘法 const mul = (...args) => args.reduce((acc, cur) => _mod(acc * cur)); // 素域除法 const div = (a, b) => mul(a, inv(b)); // 素域平方 const squ = (a) => _mod(a * a); // 辅助:是否在域内 const include = (a) => a >= 0n && a < p; return { add, sub, mul, div, mod: _mod, inv, pow, squ, root, include, }; } /** * 二元扩域 * * Binary Field * * @param {number} m - 次数 / degree * @param {bigint} IP - 不可约多项式 / irreducible polynomial */ export function GF2(m, IP) { /** m - 1 */ const m_1 = Number(m - 1n); /** 2^m */ const m_h = 1n << m; /** 2^n - 1 */ const mask = m_h - 1n; // 要求 IP 最高项为 x^m if ((IP & m_h) === 0n) throw new KitError('Irreducible polynomial must have degree m (set bit at x^m)'); // 多项式加法与减法: a + b mod 2 = a ^ b const add = (...args) => args.reduce((acc, cur) => acc ^ cur) & mask; const sub = add; // 约化: 按 IP 做多项式模约化 function reduce(poly) { let result = poly; const irreducible_degree = Number(m); // 计算多项式的最高位 let poly_degree = result.toString(2).length - 1; // 当多项式度数 >= m 时进行约简 while (poly_degree >= irreducible_degree) { const shift = poly_degree - irreducible_degree; // 将不可约多项式左移 shift 位后异或到结果中 result ^= IP << BigInt(shift); // 更新多项式度数(优化:直接跳过连续的0) poly_degree = result.toString(2).length - 1; } return result; } // 乘法 const _mul = (a, b) => { if (a === 0n || b === 0n) return 0n; let result = 0n; let a_val = a & mask; let b_val = b & mask; const ipMask = IP & mask; // 使用更高效的位运算优化 while (b_val) { // 使用位运算优化:检查最低位 result ^= b_val & 1n ? a_val : 0n; b_val >>= 1n; // 优化进位处理 if (a_val & (1n << (m - 1n))) { a_val = (a_val << 1n) & mask; a_val ^= ipMask; } else { a_val = (a_val << 1n) & mask; } } return result; }; const mul = (...args) => args.reduce((acc, cur) => _mul(acc, cur)); // 专用平方 const squ = (a) => { if (a === 0n) return 0n; if (a === 1n) return 1n; let r = 0n; for (let x = a & mask, i = 0n; x > 0n; x >>= 1n, i++) { if (x & 1n) r |= 1n << (2n * i); } return reduce(r); }; // Itoh–Tsujii 逆元: a^(2^m-2) = ∏_{i=1}^{m-1} a^{2^i} const inv = (a) => { a &= mask; if (a === 0n) throw new KitError('Division by zero'); let acc = 1n; let t = a; for (let i = 1; i <= m_1; i++) { // t = a^{2^i} t = _mul(t, t); acc = _mul(acc, t); } // acc = a^{2^m-2} return acc & mask; }; // 除法 const div = (a, b) => { a &= mask; b &= mask; if (b === 0n) throw new KitError('Division by zero'); return mul(a, inv(b)); }; // 幂运算: 针对 2 的幂优化,否则通用平方-乘 const pow = (a, b) => { if (b === 0n) return 1n; if (a === 0n) return 0n; if (b < 0n) return inv(pow(a, -b)); // 如果 b 是 2 的幂,只需重复平方 if ((b & (b - 1n)) === 0n) { let r = a & mask; let e = b; while (e > 1n) { r = mul(r, r); e >>= 1n; } return r; } // 通用:平方-乘 let result = 1n; let base = a & mask; let exp = b; while (exp > 0n) { if (exp & 1n) result = _mul(result, base); base = _mul(base, base); exp >>= 1n; } return result & mask; }; // 平方根:重复平方 m-1 次 (a -> a^{2^(m-1)}) const root = (a) => pow(a, 1n << BigInt(m_1)); // 辅助:是否在域内 const include = (a) => a >= 0n && a <= mask; const mod = (a) => reduce(a & (mask | m_h)); return { add, sub, mul, div, mod, inv, pow, squ, root, include, }; }