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
JavaScript
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 {};
}