UNPKG

@dedis/kyber

Version:

A typescript implementation of Kyber interfaces

123 lines (122 loc) 3.96 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const blake2xs_1 = require("@stablelib/blake2xs"); const bn_js_1 = __importDefault(require("bn.js")); const point_1 = require("../../pairing/point"); const scalar_1 = __importDefault(require("../../pairing/scalar")); const BLS = __importStar(require("../bls")); const COEF_SIZE = 128 / 8; /** * Generate the list of coefficients for the list of public keys * * @param pubkeys The list of public keys * @return The list of coefficients as BigNumber */ function hashPointToR(pubkeys) { const peers = pubkeys.map((p) => p.marshalBinary()); const xof = new blake2xs_1.BLAKE2Xs(); peers.forEach((p) => xof.update(p)); const out = Buffer.allocUnsafe(COEF_SIZE * peers.length); xof.stream(out); const coefs = []; for (let i = 0; i < peers.length; i++) { coefs[i] = new bn_js_1.default(out.slice(i * COEF_SIZE, (i + 1) * COEF_SIZE), "le"); } return coefs; } exports.hashPointToR = hashPointToR; /** * Aggregate the list of points according to the mask participation. * The length of the mask and the list of points must match. Intermediate * non-participating points can be null. * * @param mask The mask with the participation * @param points The list of points to aggregate */ function aggregatePoints(mask, points) { if (mask.getCountTotal() !== points.length) { throw new Error("Length of mask and points does not match"); } const coefs = hashPointToR(mask.publics); let agg = null; for (let i = 0; i < coefs.length; i++) { if (mask.isIndexEnabled(i)) { const c = new scalar_1.default(coefs[i]); const p = points[i].clone(); p.mul(c, p); // R is in the range [1; 2^128] inclusive thus (c + 1) * p p.add(p, points[i]); if (agg == null) { agg = p; } else { agg.add(agg, p); } } } return agg; } /** * Aggregate the public keys of the mask * * @param mask The mask with the participation and the list of points * @return The new point representing the aggregation */ function aggregatePublicKeys(mask) { return aggregatePoints(mask, mask.publics); } exports.aggregatePublicKeys = aggregatePublicKeys; /** * Aggregate a list of signatures according to the given mask * * @param mask The mask with the participation * @param sigs The signatures as bytes * @return The new point representing the aggregation */ function aggregateSignatures(mask, sigs) { const points = sigs.map((s) => { if (!s) { return null; } const p = new point_1.BN256G1Point(); p.unmarshalBinary(s); return p; }); return aggregatePoints(mask, points); } exports.aggregateSignatures = aggregateSignatures; /** * Sign the message using the given secret * * @param msg The Message to sign * @param secret The secret key * @return The BDN signature */ function sign(msg, secret) { return BLS.sign(msg, secret); } exports.sign = sign; /** * Verify the given signature against the message using the mask * to aggregate the public keys * * @param msg The message * @param mask The mask with the public keys * @param sig The signature as bytes * @return true if the signature matches, false otherwise */ function verify(msg, mask, sig) { const pub = aggregatePublicKeys(mask); return BLS.verify(msg, pub, sig); } exports.verify = verify;