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 实现的密码学套件。目标是提供一个简单易用的密码学库。
113 lines (112 loc) • 2.96 kB
JavaScript
import { genPrime } from '../../core/prime';
import { KitError, U8, gcd, lcm, mod, modInverse, modPow } from '../../core/utils';
// * RSA Algorithm
/**
* RSA 加密原语
*
* RSA encryption primitive
*/
function encryptionPrimitive(key, M) {
const { n, e } = key;
if (e === undefined || n === undefined) {
throw new KitError('Invalid public key');
}
M = typeof M === 'bigint' ? M : U8.from(M).toBI();
if (M >= n) {
throw new KitError('Message representative out of range');
}
return modPow(M, e, n);
}
/**
* RSA 解密原语
*
* RSA decryption primitive
*/
function decryptionPrimitive(key, C) {
const { n, d } = key;
if (d === undefined || n === undefined) {
throw new KitError('Invalid private key');
}
C = typeof C === 'bigint' ? C : U8.from(C).toBI();
if (C >= n) {
throw new KitError('Ciphertext representative out of range');
}
return modPow(C, d, n);
}
/**
* RSA 签名原语
*
* RSA signature primitive
*/
function signaturePrimitive(key, M) {
const { n, d } = key;
if (d === undefined || n === undefined) {
throw new KitError('Invalid private key');
}
M = typeof M === 'bigint' ? M : U8.from(M).toBI();
if (M >= n) {
throw new KitError('Message representative out of range');
}
return modPow(M, d, n);
}
/**
* RSA 验证原语
*
* RSA verification primitive
*/
function verificationPrimitive(key, S) {
const { n, e } = key;
if (e === undefined || n === undefined) {
throw new KitError('Invalid public key');
}
S = typeof S === 'bigint' ? S : U8.from(S).toBI();
if (S >= n) {
throw new KitError('Signature is too long');
}
return modPow(S, e, n);
}
/**
* RSA 密钥生成
*
* RSA key generation
*
* @param {number} b - RSA 私钥长度 / RSA private key length (bit)
* @param {RandomPrimeGenerator} rpg - 随机素数生成器 / Random prime generator
*/
function genKey(b, rpg = genPrime) {
const p = rpg(b >> 1);
const q = rpg(b >> 1);
const n = p * q;
const λ = lcm(p - 1n, q - 1n);
// public key
const e = 65537n;
if (gcd(e, λ) !== 1n) {
throw new KitError('Invalid public exponent');
}
// private key
const d = modInverse(e, λ);
const dP = mod(d, p - 1n);
const dQ = mod(d, q - 1n);
const qInv = modInverse(q, p);
const privateKey = { n, e, d, p, q, dP, dQ, qInv };
return privateKey;
}
function fromKey(key) {
const encrypt = (M) => encryptionPrimitive(key, M);
const decrypt = (C) => decryptionPrimitive(key, C);
const sign = (M) => signaturePrimitive(key, M);
const verify = (S) => verificationPrimitive(key, S);
return {
...key,
encrypt,
decrypt,
sign,
verify,
};
}
export function rsa(b, rpg = genPrime) {
if (typeof b === 'number') {
return fromKey(genKey(b, rpg));
}
return fromKey(b);
}