@cloudflare/zkp-ecdsa
Version:
zkp-ecdsa: A Typescript Implementation of ZKAttest
204 lines • 8.13 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Group, hashPoints } from '../curves/group.js';
import { MultiMult, Relation } from '../curves/multimult.js';
import { expMod, invMod, posMod, rnd } from '../bignum/big.js';
import { jsonArrayMember, jsonMember, jsonObject, toJson } from 'typedjson';
import { cmpArray } from '../util.js';
import { interpolate } from './interpolate.js';
let GKProof = class GKProof {
constructor(cl, ca, cb, cd, f, za, zb, zd) {
this.cl = cl;
this.ca = ca;
this.cb = cb;
this.cd = cd;
this.f = f;
this.za = za;
this.zb = zb;
this.zd = zd;
}
eq(o) {
return (cmpArray(this.cl, o.cl) &&
cmpArray(this.ca, o.ca) &&
cmpArray(this.cb, o.cb) &&
cmpArray(this.cd, o.cd) &&
cmpArray(this.f, o.f) &&
cmpArray(this.za, o.za) &&
cmpArray(this.zb, o.zb) &&
this.zd.eq(o.zd));
}
};
__decorate([
jsonArrayMember(Group.Point, { isRequired: true }),
__metadata("design:type", Array)
], GKProof.prototype, "cl", void 0);
__decorate([
jsonArrayMember(Group.Point, { isRequired: true }),
__metadata("design:type", Array)
], GKProof.prototype, "ca", void 0);
__decorate([
jsonArrayMember(Group.Point, { isRequired: true }),
__metadata("design:type", Array)
], GKProof.prototype, "cb", void 0);
__decorate([
jsonArrayMember(Group.Point, { isRequired: true }),
__metadata("design:type", Array)
], GKProof.prototype, "cd", void 0);
__decorate([
jsonArrayMember(Group.Scalar, { isRequired: true }),
__metadata("design:type", Array)
], GKProof.prototype, "f", void 0);
__decorate([
jsonArrayMember(Group.Scalar, { isRequired: true }),
__metadata("design:type", Array)
], GKProof.prototype, "za", void 0);
__decorate([
jsonArrayMember(Group.Scalar, { isRequired: true }),
__metadata("design:type", Array)
], GKProof.prototype, "zb", void 0);
__decorate([
jsonMember({ constructor: Group.Scalar, isRequired: true }),
__metadata("design:type", Group.Scalar)
], GKProof.prototype, "zd", void 0);
GKProof = __decorate([
jsonObject,
toJson,
__metadata("design:paramtypes", [Array, Array, Array, Array, Array, Array, Array, Group.Scalar])
], GKProof);
export { GKProof };
function pad(vals, c) {
const ret = [];
for (let i = 0; i < vals.length; i++) {
ret[i] = c.newScalar(vals[i]);
}
const padLen = 2 ** Math.ceil(Math.log2(vals.length));
for (let i = vals.length; i < padLen; i++) {
ret.push(ret[0]);
}
return ret;
}
function commit(params, val, blinder) {
const posVal = posMod(val, params.c.order), posBlinder = posMod(blinder, params.c.order);
return params.g.dblmul(params.c.newScalar(posVal), params.h, params.c.newScalar(posBlinder));
}
export async function proveMembership(params, com, index, initialValues) {
const values = pad(initialValues, params.c), c = params.c, el = BigInt(index), n = Math.ceil(Math.log2(values.length)), eli = [];
let l_tmp = el;
for (let i = 0; i < n; i++) {
eli[i] = l_tmp % BigInt(2);
l_tmp /= BigInt(2);
}
const ri = [], ai = [], si = [], ti = [], rho = [];
for (let i = 0; i < n; i++) {
ri[i] = rnd(c.order);
ai[i] = rnd(c.order);
si[i] = rnd(c.order);
ti[i] = rnd(c.order);
rho[i] = rnd(c.order);
}
const cl = [], ca = [], cb = [], cd = [];
for (let i = 0; i < n; i++) {
cl[i] = commit(params, eli[i], ri[i]);
ca[i] = commit(params, ai[i], si[i]);
cb[i] = commit(params, eli[i] * ai[i], ti[i]);
}
const omegas = [];
for (let i = 0; i < n; i++) {
omegas[i] = BigInt(i);
}
const dv = [];
for (const w of omegas) {
const f0j = [], f1j = [], ratio = [];
for (let j = 0; j < n; j++) {
f0j[j] = posMod((BigInt(1) - eli[j]) * w - ai[j], c.order);
f1j[j] = posMod(eli[j] * w + ai[j], c.order);
ratio[j] = posMod(f1j[j] * invMod(f0j[j], c.order), c.order);
}
let prod = BigInt(1);
for (let i = 0; i < f0j.length; i++) {
prod *= f0j[i];
prod = posMod(prod, c.order);
}
const p = [];
p[0] = prod;
for (let i = 0; i < n; i++) {
const oldlen = p.length;
for (let j = 0; j < oldlen; j++) {
p[oldlen + j] = posMod(ratio[i] * p[j], c.order);
}
}
let dval = BigInt(0);
for (let i = 0; i < values.length; i++) {
dval += (values[index].k - values[i].k) * p[i];
dval = posMod(dval, c.order);
}
dv.push(dval);
}
const di = interpolate(omegas, dv, c.order);
for (let i = 0; i < n; i++) {
cd[i] = commit(params, di[i], rho[i]);
}
const commitments = cl.concat(ca).concat(cb).concat(cd), x = await hashPoints('SHA-256', commitments), f = [], za = [], zb = [];
let zd = (com.r.k * expMod(x, BigInt(n), c.order)) % c.order;
for (let i = 0; i < n; i++) {
f[i] = c.newScalar(posMod(eli[i] * x + ai[i], c.order));
za[i] = c.newScalar(posMod(ri[i] * x + si[i], c.order));
zb[i] = c.newScalar(posMod(ri[i] * (x - f[i].k) + ti[i], c.order));
}
for (let i = 0; i < n; i++) {
zd = posMod(zd - rho[i] * expMod(x, BigInt(i), c.order), c.order);
}
return new GKProof(cl, ca, cb, cd, f, za, zb, c.newScalar(zd));
}
export async function verifyMembership(params, com, initVec, proof) {
const c = params.c, multi = new MultiMult(c), vec = pad(initVec, c), n = Math.ceil(Math.log2(vec.length));
if (n != proof.cl.length ||
n != proof.ca.length ||
n != proof.cb.length ||
n != proof.cd.length ||
n != proof.f.length ||
n != proof.za.length ||
n != proof.zb.length) {
return false;
}
const f = proof.f, x = await hashPoints('SHA-256', proof.cl.concat(proof.ca).concat(proof.cb).concat(proof.cd));
multi.addKnown(params.g);
multi.addKnown(params.h);
for (let i = 0; i < n; i++) {
const rel0 = new Relation(c);
rel0.insertM([proof.cl[i], proof.ca[i], params.g, params.h], [c.newScalar(x), c.newScalar(BigInt(1)), proof.f[i].neg(), proof.za[i].neg()]);
rel0.drain(multi);
const rel1 = new Relation(c);
rel1.insertM([proof.cl[i], proof.cb[i], params.h], [c.newScalar(posMod(x - f[i].k, c.order)), c.newScalar(BigInt(1)), proof.zb[i].neg()]);
rel1.drain(multi);
}
let total = BigInt(0);
for (let i = 0; i < vec.length; i++) {
let pix = BigInt(1);
for (let j = 0; j < n; j++) {
if (i & (1 << j)) {
pix = posMod(pix * f[j].k, c.order);
}
else {
pix = posMod(pix * (x - f[j].k), c.order);
}
}
total = posMod(total + vec[i].k * pix, c.order);
}
const relFinal = new Relation(c);
for (let i = 0; i < n; i++) {
relFinal.insert(proof.cd[i], c.newScalar(posMod(-expMod(x, BigInt(i), c.order), c.order)));
}
relFinal.insert(com, c.newScalar(expMod(x, BigInt(n), c.order)));
relFinal.insertM([params.g, params.h], [c.newScalar(posMod(-total, c.order)), proof.zd.neg()]);
relFinal.drain(multi);
return multi.evaluate().isIdentity();
}
//# sourceMappingURL=gk.js.map