All files / src DHKE.ts

100% Statements 35/35
100% Branches 1/1
100% Functions 6/6
100% Lines 32/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71  4x 4x   4x 4x 4x       31x 64x 64x 64x 64x 64x   33x     31x   4x 108x           27x 27x 27x 27x 26x   27x 27x 27x               22x 22x                 11x 21x 21x 21x 21x           21x       4x  
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
import { secp256k1 } from '@noble/curves/secp256k1';
import { encodeUint8toBase64 } from './base64.js';
import { MintKeys, Proof, SerializedBlindedSignature } from './model/types/index.js';
import { bytesToNumber } from './utils.js';
import { sha256 } from '@noble/hashes/sha256';
import { bytesToHex } from '@noble/curves/abstract/utils';
 
function hashToCurve(secret: Uint8Array): ProjPointType<bigint> {
	let point: ProjPointType<bigint> | undefined;
	while (!point) {
		const hash = sha256(secret);
		const hashHex = bytesToHex(hash);
		const pointX = '02' + hashHex;
		try {
			point = pointFromHex(pointX);
		} catch (error) {
			secret = sha256(secret);
		}
	}
	return point;
}
export function pointFromHex(hex: string) {
	return secp256k1.ProjectivePoint.fromHex(hex);
}
/* export function h2cToPoint(h2c: H2CPoint<bigint>): ProjPointType<bigint> {
	return secp256k1.ProjectivePoint.fromAffine(h2c.toAffine());
} */
function blindMessage(secret: Uint8Array, r?: bigint): { B_: ProjPointType<bigint>; r: bigint } {
	const secretMessageBase64 = encodeUint8toBase64(secret);
	const secretMessage = new TextEncoder().encode(secretMessageBase64);
	const Y = hashToCurve(secretMessage);
	if (!r) {
		r = bytesToNumber(secp256k1.utils.randomPrivateKey());
	}
	const rG = secp256k1.ProjectivePoint.BASE.multiply(r);
	const B_ = Y.add(rG);
	return { B_, r };
}
 
function unblindSignature(
	C_: ProjPointType<bigint>,
	r: bigint,
	A: ProjPointType<bigint>
): ProjPointType<bigint> {
	const C = C_.subtract(A.multiply(r));
	return C;
}
 
function constructProofs(
	promises: Array<SerializedBlindedSignature>,
	rs: Array<bigint>,
	secrets: Array<Uint8Array>,
	keys: MintKeys
): Array<Proof> {
	return promises.map((p: SerializedBlindedSignature, i: number) => {
		const C_ = pointFromHex(p.C_);
		const A = pointFromHex(keys[p.amount]);
		const C = unblindSignature(C_, rs[i], A);
		const proof = {
			id: p.id,
			amount: p.amount,
			secret: encodeUint8toBase64(secrets[i]),
			C: C.toHex(true)
		};
		return proof;
	});
}
 
export { hashToCurve, blindMessage, unblindSignature, constructProofs };