@reclaimprotocol/zk-symmetric-crypto
Version:
JS Wrappers for Various ZK Snark Circuits
141 lines (140 loc) • 6.83 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeGnarkOPRFOperator = makeGnarkOPRFOperator;
const js_base64_1 = require("js-base64");
const koffi = __importStar(require("koffi"));
const utils_1 = require("./utils");
const ALGS_MAP = {
'chacha20': { ext: 'chacha20_oprf', id: 3 },
'aes-128-ctr': { ext: 'aes128_oprf', id: 4 },
'aes-256-ctr': { ext: 'aes256_oprf', id: 5 },
};
function makeGnarkOPRFOperator({ fetcher, algorithm }) {
return {
async generateWitness(input) {
return (0, utils_1.serialiseGnarkWitness)(algorithm, input);
},
async groth16Prove(witness, logger) {
const lib = await initGnark(logger);
const { proof } = await (0, utils_1.executeGnarkFnAndGetJson)(lib.prove, witness);
return { proof: js_base64_1.Base64.toUint8Array(proof) };
},
async groth16Verify(publicSignals, proof, logger) {
const lib = await initGnark(logger);
const pubSignals = (0, utils_1.serialiseGnarkWitness)(algorithm, publicSignals);
const verifyParams = JSON.stringify({
cipher: `${algorithm}-toprf`,
proof: typeof proof === 'string'
? proof
: js_base64_1.Base64.fromUint8Array(proof),
publicSignals: js_base64_1.Base64.fromUint8Array(pubSignals),
});
return (0, utils_1.executeGnarkFn)(lib.verify, verifyParams) === 1;
},
async generateThresholdKeys(total, threshold, logger) {
const lib = await initGnark(logger);
const { generateThresholdKeys, vfree } = lib;
const params = { total: total, threshold: threshold };
const res = (0, utils_1.executeGnarkFn)(generateThresholdKeys, JSON.stringify(params));
const resJson = Buffer.from(koffi.decode(res.r0, 'unsigned char', res.r1)).toString();
vfree(res.r0); // Avoid memory leak!
const parsed = JSON.parse(resJson);
const shares = [];
for (let i = 0; i < parsed.shares.length; i++) {
const share = parsed.shares[i];
shares.push({
index: share.index,
publicKey: (0, js_base64_1.toUint8Array)(share.publicKey),
privateKey: (0, js_base64_1.toUint8Array)(share.privateKey),
});
}
return {
publicKey: (0, js_base64_1.toUint8Array)(parsed.publicKey),
privateKey: (0, js_base64_1.toUint8Array)(parsed.privateKey),
shares: shares,
};
},
async generateOPRFRequestData(data, domainSeparator, logger) {
const lib = await initGnark(logger);
const params = {
data: js_base64_1.Base64.fromUint8Array(data),
domainSeparator: domainSeparator,
};
const parsed = await (0, utils_1.executeGnarkFnAndGetJson)(lib.generateOPRFRequest, JSON.stringify(params));
return {
mask: (0, js_base64_1.toUint8Array)(parsed.mask),
maskedData: (0, js_base64_1.toUint8Array)(parsed.maskedData),
secretElements: [
(0, js_base64_1.toUint8Array)(parsed.secretElements[0]),
(0, js_base64_1.toUint8Array)(parsed.secretElements[1])
]
};
},
async finaliseOPRF(serverPublicKey, request, responses, logger) {
const lib = await initGnark(logger);
const params = {
serverPublicKey: (0, js_base64_1.fromUint8Array)(serverPublicKey),
request: {
mask: (0, js_base64_1.fromUint8Array)(request.mask),
maskedData: (0, js_base64_1.fromUint8Array)(request.maskedData),
secretElements: [
(0, js_base64_1.fromUint8Array)(request.secretElements[0]),
(0, js_base64_1.fromUint8Array)(request.secretElements[1])
]
},
responses: responses.map(({ publicKeyShare, evaluated, c, r }) => ({
publicKeyShare: (0, js_base64_1.fromUint8Array)(publicKeyShare),
evaluated: (0, js_base64_1.fromUint8Array)(evaluated),
c: (0, js_base64_1.fromUint8Array)(c),
r: (0, js_base64_1.fromUint8Array)(r),
}))
};
const parsed = await (0, utils_1.executeGnarkFnAndGetJson)(lib.toprfFinalize, JSON.stringify(params));
return (0, js_base64_1.toUint8Array)(parsed.output);
},
async evaluateOPRF(serverPrivate, maskedData, logger) {
const lib = await initGnark(logger);
const { oprfEvaluate, vfree } = lib;
const params = {
serverPrivate: (0, js_base64_1.fromUint8Array)(serverPrivate),
maskedData: (0, js_base64_1.fromUint8Array)(maskedData),
};
const res = (0, utils_1.executeGnarkFn)(oprfEvaluate, JSON.stringify(params));
const resJson = Buffer.from(koffi.decode(res.r0, 'unsigned char', res.r1)).toString();
vfree(res.r0); // Avoid memory leak!
const parsed = JSON.parse(resJson);
return {
evaluated: (0, js_base64_1.toUint8Array)(parsed.evaluated),
c: (0, js_base64_1.toUint8Array)(parsed.c),
r: (0, js_base64_1.toUint8Array)(parsed.r),
};
},
};
async function initGnark(logger) {
const { ext, id } = ALGS_MAP[algorithm];
return (0, utils_1.initGnarkAlgorithm)(id, ext, fetcher, logger);
}
}