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

215 lines (214 loc) 6.59 kB
import { U8, mod, modInverse, modPow, modPrimeSquare } from './utils'; // * FpEC Components /** * 将椭圆曲线点转换为 U8 格式 * * Convert EC Point to U8 Format */ export function U8Point(point, byte) { if (!point) { return { isInfinity: true, x: new U8(), y: new U8() }; } const isInfinity = point.isInfinity; const x = typeof point.x === 'bigint' ? U8.fromBI(point.x, byte) : U8.from(point.x); const y = typeof point.y === 'bigint' ? U8.fromBI(point.y, byte) : U8.from(point.y); return { isInfinity, x, y }; } /** * 将椭圆曲线点转换为 bigint 格式 * * Convert EC Point to bigint Format */ export function BIPoint(point) { if (!point) { return { isInfinity: true, x: 0n, y: 0n }; } const isInfinity = point.isInfinity; const x = typeof point.x === 'bigint' ? point.x : U8.from(point.x).toBI(); const y = typeof point.y === 'bigint' ? point.y : U8.from(point.y).toBI(); return { isInfinity, x, y }; } /** * 蒙哥马利梯子点乘法 * * Montgomery Ladder Point Multiplication * * @param addPoint 素域椭圆曲线点加法函数 / Prime Field EC Point Addition Function * @param {FpECPoint} P 椭圆曲线点 / EC Point * @param {bigint | Uint8Array} k 标量 / Scalar */ function LadderMultiply(addPoint, P, k) { k = typeof k === 'bigint' ? k : U8.from(k).toBI(); let R0 = BIPoint(); let R1 = BIPoint(P); // MSb -> LSb const bit_array = k.toString(2).split(''); for (const bit of bit_array) { if (bit === '1') { R0 = addPoint(R0, R1); R1 = addPoint(R1, R1); } else { R1 = addPoint(R0, R1); R0 = addPoint(R0, R0); } } return R0; } /** 素域运算 / Prime Field Operations */ export function Fp(p) { const _mod = (a) => mod(a, p); const inverse = (a) => modInverse(a, p); const root = (a) => modPrimeSquare(a, p); const pow = (a, b) => modPow(a, b, p); const plus = (...args) => args.reduce((acc, cur) => _mod(acc + cur)); const multiply = (...args) => args.reduce((acc, cur) => _mod(acc * cur)); const subtract = (a, ...args) => { const b = args.map(v => _mod(p - v)); return plus(a, ...b); }; const divide = (a, b) => multiply(a, inverse(b)); return { plus, multiply, subtract, divide, mod: _mod, pow, inverse, root, }; } /** * 素域椭圆曲线运算 * * Prime Field Elliptic Curve Operations */ export function FpEC(curve) { switch (curve.type) { case 'Weierstrass': return FpWEC(curve); case 'Montgomery': return FpMEC(curve); case 'TwistedEdwards': return FpTEC(curve); } } /** * 素域 Weierstrass 椭圆曲线运算 * * Prime Field Weierstrass Elliptic Curve Operations */ export function FpWEC(curve) { const { p, a } = curve; const { plus, multiply, subtract, divide } = Fp(p); const addPoint = (A, B) => { // O + P = P if (A.isInfinity) { return BIPoint(B); } if (B.isInfinity) { return BIPoint(A); } let [x1, y1] = [A.x, A.y]; let [x2, y2] = [B.x, B.y]; x1 = typeof x1 === 'bigint' ? x1 : U8.from(x1).toBI(); y1 = typeof y1 === 'bigint' ? y1 : U8.from(y1).toBI(); x2 = typeof x2 === 'bigint' ? x2 : U8.from(x2).toBI(); y2 = typeof y2 === 'bigint' ? y2 : U8.from(y2).toBI(); // P + (-P) = O if (x1 === x2 && y1 !== y2) { return BIPoint(); } let λ = 0n; // P1 + P2 if (x1 !== x2) { // λ = (y2 - y1) / (x2 - x1) const numerator = subtract(y2, y1); const denominator = subtract(x2, x1); λ = divide(numerator, denominator); } // P1 + P1 else { // λ = (3 * x1 * x1 + a) / 2 * y1 const numerator = plus(multiply(3n, x1, x1), a); const denominator = multiply(2n, y1); λ = divide(numerator, denominator); } // x3 = λ * λ - x1 - x2 const x3 = subtract(multiply(λ, λ), x1, x2); // y3 = λ * (x1 - x3) - y1 const y3 = subtract(multiply(λ, subtract(x1, x3)), y1); return { isInfinity: false, x: x3, y: y3 }; }; const mulPoint = (P, k) => LadderMultiply(addPoint, P, k); return { addPoint, mulPoint }; } /** * 素域 Montgomery 椭圆曲线运算 * * Prime Field Montgomery Elliptic Curve Operations */ export function FpMEC(curve) { const { p, a, b } = curve; const { plus, multiply, subtract, divide } = Fp(p); const addPoint = (A, B) => { // O + P = P if (A.isInfinity) { return BIPoint(B); } if (B.isInfinity) { return BIPoint(A); } let [x1, y1] = [A.x, A.y]; let [x2, y2] = [B.x, B.y]; x1 = typeof x1 === 'bigint' ? x1 : U8.from(x1).toBI(); y1 = typeof y1 === 'bigint' ? y1 : U8.from(y1).toBI(); x2 = typeof x2 === 'bigint' ? x2 : U8.from(x2).toBI(); y2 = typeof y2 === 'bigint' ? y2 : U8.from(y2).toBI(); // P + (-P) = O if (x1 === x2 && y1 !== y2) { return BIPoint(); } let λ = 0n; // P1 + P2 if (x1 !== x2) { // λ = (y2 - y1) / (x2 - x1) const numerator = subtract(y2, y1); const denominator = subtract(x2, x1); λ = divide(numerator, denominator); } // P1 + P1 else { // λ = (3 * x1 * x1 + 2 * a * x1 + 1) / 2 * b * y1 const numerator = plus(multiply(3n, x1, x1), multiply(2n, a, x1), 1n); const denominator = multiply(2n, b, y1); λ = divide(numerator, denominator); } // x3 = b * λ * λ - a - x1 - x2 const x3 = subtract(multiply(λ, λ, b), a, x1, x2); // y3 = (2 x1 + x2 + a) * λ - b * λ * λ * λ - y1 const y3 = subtract(multiply(2n * x1 + x2 + a, λ), multiply(λ, λ, λ, b), y1); return { isInfinity: false, x: x3, y: y3 }; }; const mulPoint = (P, k) => LadderMultiply(addPoint, P, k); return { addPoint, mulPoint }; } /** * 素域 Twisted Edwards 椭圆曲线运算 * * Prime Field Twisted Edwards Elliptic Curve Operations */ // eslint-disable-next-line unused-imports/no-unused-vars export function FpTEC(curve) { // TODO return {}; }