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 实现的密码学套件。目标是提供一个简单易用的密码学库。

122 lines (121 loc) 4.3 kB
import { U8, modPow } from './utils'; // * Constants /** deterministic >= 1 - 0.5^t */ const T = 40; const LOW_PRIMES = [2n, 3n, 5n, 7n, 11n, 13n, 17n, 19n, 23n, 29n, 31n, 37n, 41n, 43n, 47n, 53n, 59n, 61n, 67n, 71n, 73n, 79n, 83n, 89n, 97n, 101n, 103n, 107n, 109n, 113n, 127n, 131n, 137n, 139n, 149n, 151n, 157n, 163n, 167n, 173n, 179n, 181n, 191n, 193n, 197n, 199n, 211n, 223n, 227n, 229n, 233n, 239n, 241n, 251n, 257n, 263n, 269n, 271n, 277n, 281n, 283n, 293n, 307n, 311n, 313n, 317n, 331n, 337n, 347n, 349n, 353n, 359n, 367n, 373n, 379n, 383n, 389n, 397n, 401n, 409n, 419n, 421n, 431n, 433n, 439n, 443n, 449n, 457n, 461n, 463n, 467n, 479n, 487n, 491n, 499n, 503n, 509n, 521n, 523n, 541n, 547n, 557n, 563n, 569n, 571n, 577n, 587n, 593n, 599n, 601n, 607n, 613n, 617n, 619n, 631n, 641n, 643n, 647n, 653n, 659n, 661n, 673n, 677n, 683n, 691n, 701n, 709n, 719n, 727n, 733n, 739n, 743n, 751n, 757n, 761n, 769n, 773n, 787n, 797n, 809n, 811n, 821n, 823n, 827n, 829n, 839n, 853n, 857n, 859n, 863n, 877n, 881n, 883n, 887n, 907n, 911n, 919n, 929n, 937n, 941n, 947n, 953n, 967n, 971n, 977n, 983n, 991n, 997n]; const LOW_PRIMES_LIMIT = (1n << 26n) / LOW_PRIMES[LOW_PRIMES.length - 1]; // * Functions /** Miller-Rabin 素性测试 / Primality Test */ function MillerRabin(n, t) { const n_1 = n - 1n; let s = 0n; let d = n_1; while ((d & 1n) === 0n) { d >>= 1n; s++; } t = (t + 1) >> 1; if (t > LOW_PRIMES.length) t = LOW_PRIMES.length; const tested = [2n]; for (let i = 0; i < t; ++i) { // Pick bases at random let base; do { base = LOW_PRIMES[Math.floor(Math.random() * LOW_PRIMES.length)]; } while (tested.includes(base)); tested.push(base); if (StrongPseudoPrime(n, n_1, s, d, base) === false) { return false; } } return true; } /** * 根据费马小定理: `base^(n-1) ≡ 1 (mod n)` 时 `n` 可能是素数, * 通过将 `n-1` 分解为 `2^s * d` 优化计算 * * According to Fermat's Little Theorem: `base^(n-1) ≡ 1 (mod n)` when `n` may be a prime, * optimize the calculation by decomposing `n-1` into `2^s * d` * * @param {bigint} n - 待测试的数 * @param {bigint} n_1 - n - 1 * @param {bigint} s - n - 1 = 2^s * d * @param {bigint} d - n - 1 = 2^s * d * @param {bigint} base - 测试基数 */ function StrongPseudoPrime(n, n_1, s, d, base) { let x = modPow(base, d, n); if (x === 1n || x === n_1) return true; let y = 0n; for (let i = 1; i < s; i++) { y = modPow(x, 2n, n); if (y === 1n && x !== 1n && x !== n_1) return false; x = y; } return y === 1n; } /** * 高级素性测试: 确定性 >= 1-.5^t * * Advanced primality test: deterministic >= 1-.5^t */ function _isProbablePrime(n, t = T) { // 低素数倍数 for (let i = 1; i < LOW_PRIMES.length;) { let m = LOW_PRIMES[i]; let j = i + 1; while (j < LOW_PRIMES.length && m < LOW_PRIMES_LIMIT) { m *= LOW_PRIMES[j++]; } m = n % m; while (i < j) { if (m % LOW_PRIMES[i++] === 0n) return false; } } return MillerRabin(n, t); } function genPrimeCandidate(buffer) { crypto.getRandomValues(buffer); buffer[0] |= 0x80; let n = buffer.toBI() | 1n; const n_mod_6 = n % 6n; if (n_mod_6 !== 1n && n_mod_6 !== 5n) n += 4n; return n; } /** 随机素数生成器 / Random Prime Generator */ export const genPrime = (b) => { const buffer = new U8(b >> 3); let n; do { n = genPrimeCandidate(buffer); } while (!_isProbablePrime(n)); return n; }; /** * 素性测试: 确定性 >= 1-.5^t * * Primality test: deterministic >= 1-.5^t * * @param {bigint} n - 待测试的数 / Number to be tested * @param {number} t - 测试轮数 / Number of tests */ export function isProbablePrime(n, t = T) { if (t <= 0) return false; // 偶数 if ((n & 1n) === 0n) return false; // 六倍原理 const n_mod_6 = n % 6n; if (n_mod_6 !== 1n && n_mod_6 !== 5n) return false; // 小素数 if (n <= LOW_PRIMES[LOW_PRIMES.length - 1]) return LOW_PRIMES.includes(n); return _isProbablePrime(n, t); }