functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
54 lines (53 loc) • 1.72 kB
JavaScript
import { listToVec, msb, uint, vec, vec8, length } from "../../types/bit_vec/module.f.js";
import { hmac } from "../hmac/module.f.js";
import { curve } from "../secp/module.f.js";
const concat = listToVec(msb);
const v00 = vec8(0x00n);
const v01 = vec8(0x01n);
/**
* The size of the result equals the size of the hash.
*
* @param sha2 SHA2 hash function
* @returns A function that accepts a private key, a message hash and returns `k`.
*/
const createK = (sha2) => {
const h = hmac(sha2);
let vs = vec(sha2.hashLength);
let k0 = vs(0x00n);
let v0 = vs(0x01n);
return (privateKey) => (messageHash) => {
const pm = concat([privateKey, messageHash]);
let k = k0;
let v = v0;
k = h(k)(concat([v, v00, pm]));
v = h(k)(v);
k = h(k)(concat([v, v01, pm]));
v = h(k)(v);
return uint(h(k)(v));
};
};
export const newPrivateKey = (i) => (random) => {
const { nf } = curve(i);
if (length(nf.max) < length(random)) {
throw "need more random bits";
}
return uint(random) % nf.p;
};
export const sign = (sha2) => (curveInit) => (privateKey) => (messageHash) => {
const { mul, pf } = curve(curveInit);
// const curveVec = vec(length(pf.max))
//`k` is a unique for each `z` and secret.
const k = createK(sha2)(privateKey)(messageHash) % pf.p;
// `R = G * k`.
const rp = mul(curveInit.g)(k);
// `r = R.x`
const r = rp === null ? 0n : rp[0];
// `s = ((z + r * d) / k)`.
const d = uint(privateKey);
const z = uint(messageHash);
const rd = pf.mul(r)(d);
const zrd = pf.add(z)(rd);
const kn1 = pf.reciprocal(k);
const s = pf.mul(zrd)(kn1);
return [r, s];
};