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
JavaScript
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 };
})();