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

134 lines (133 loc) 5.21 kB
import { Fp } from '../../core/ec'; import { curve25519, curve448 } from '../../core/ecParams'; import { KitError, U8, genRandomBI, getBIBits } from '../../core/utils'; // * X25519 & X448 Algorithms function cSwap(swap, x_2, x_3) { const mask = -swap; const dummy = mask & (x_2 ^ x_3); x_2 ^= dummy; x_3 ^= dummy; return [x_2, x_3]; } /** 蒙哥马利梯子算法 / Montgomery Ladder Algorithm */ function ladder(k, u, p, a24, bit) { const { plus, subtract, pow, multiply } = Fp(p); let x_2 = 1n; let z_2 = 0n; let x_3 = u; let z_3 = 1n; let swap = 0n; const bit_array = k.toString(2).padStart(bit, '0').split('').map(BigInt); for (const bit of bit_array) { swap ^= bit; [x_2, x_3] = cSwap(swap, x_2, x_3); [z_2, z_3] = cSwap(swap, z_2, z_3); swap = bit; const A = plus(x_2, z_2); const AA = pow(A, 2n); const B = subtract(x_2, z_2); const BB = pow(B, 2n); const E = subtract(AA, BB); const C = plus(x_3, z_3); const D = subtract(x_3, z_3); const DA = multiply(D, A); const CB = multiply(C, B); x_3 = pow(plus(DA, CB), 2n); z_3 = multiply(u, pow(subtract(DA, CB), 2n)); x_2 = multiply(AA, BB); z_2 = multiply(E, plus(AA, multiply(E, a24))); } [x_2, x_3] = cSwap(swap, x_2, x_3); [z_2, z_3] = cSwap(swap, z_2, z_3); return multiply(x_2, pow(z_2, p - 2n)); } /** x25519 椭圆曲线算法 / Elliptic Curve Algorithm */ export const x25519 = (() => { const { p, G, n } = curve25519; const p_bit = getBIBits(p); const p_byte = (p_bit + 7) >> 3; const a24 = 121665n; const Gx = typeof G.x === 'bigint' ? G.x : U8.from(G.x).toBI(); function clamp(d) { d = d & 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8n; d = d | 0x4000000000000000000000000000000000000000000000000000000000000000n; return d; } function gen(type = 'key_pair', s_key) { if (type === 'key_pair') { // private key const t = genRandomBI(n, p_byte); const d_buffer = t.buffer; const d = t.result; // public key const x = ladder(clamp(d), Gx, p, a24, 255); const Q = U8.fromBI(x, p_byte); return { Q, d: d_buffer }; } else if (type === 'private_key') { return { d: genRandomBI(n, p_byte).buffer }; } else if (type === 'public_key') { const d_buffer = typeof s_key.d === 'bigint' ? U8.fromBI(s_key.d) : U8.from(s_key.d); const d = typeof s_key.d === 'bigint' ? s_key.d : d_buffer.toBI(); if (d === 0n) { throw new KitError('Invalid private key'); } const x = ladder(clamp(d), Gx, p, a24, 255); const Q = U8.fromBI(x, p_byte); return { Q, d: d_buffer }; } } const ecdh = (s_key, p_key) => { const u = typeof p_key.Q === 'bigint' ? p_key.Q : U8.from(p_key.Q).toBI(); const k = typeof s_key.d === 'bigint' ? s_key.d : U8.from(s_key.d).toBI(); const x = ladder(clamp(k), u, p, a24, 255); return U8.fromBI(x, p_byte); }; return { gen, dh: ecdh }; })(); /** x448 椭圆曲线算法 / Elliptic Curve Algorithm */ export const x448 = (() => { const { p, G, n } = curve448; const p_bit = getBIBits(p); const p_byte = (p_bit + 7) >> 3; const a24 = 39081n; const Gx = typeof G.x === 'bigint' ? G.x : U8.from(G.x).toBI(); function clamp(d) { d = d & 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcn; d = d | 0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n; return d; } function gen(type = 'key_pair', s_key) { if (type === 'key_pair') { // private key const t = genRandomBI(n, p_byte); const d_buffer = t.buffer; const d = t.result; // public key const x = ladder(clamp(d), Gx, p, a24, 448); const Q = U8.fromBI(x, p_byte); return { Q, d: d_buffer }; } else if (type === 'private_key') { return { d: genRandomBI(n, p_byte).buffer }; } else if (type === 'public_key') { const d_buffer = typeof s_key.d === 'bigint' ? U8.fromBI(s_key.d) : U8.from(s_key.d); const d = typeof s_key.d === 'bigint' ? s_key.d : d_buffer.toBI(); if (d === 0n) { throw new KitError('Invalid private key'); } const x = ladder(clamp(d), Gx, p, a24, 448); const Q = U8.fromBI(x, p_byte); return { Q, d: d_buffer }; } } const ecdh = (s_key, p_key) => { const u = typeof p_key.Q === 'bigint' ? p_key.Q : U8.from(p_key.Q).toBI(); const k = typeof s_key.d === 'bigint' ? s_key.d : U8.from(s_key.d).toBI(); const x = ladder(clamp(k), u, p, a24, 448); return U8.fromBI(x, p_byte); }; return { gen, dh: ecdh }; })();