UNPKG

circomlibjs-hinkal-fork

Version:

Javascript library to work with circomlib

108 lines (94 loc) 3.15 kB
import { Scalar, utils } from "ffjavascript"; import buildBabyJub from "./babyjub.js"; import { buildPoseidon } from "./poseidon_wasm.js"; import createBlakeHash from "blake-hash"; export default async function buildEddsa() { const babyJub = await buildBabyJub("bn128"); const poseidon = await buildPoseidon(); return new Eddsa(babyJub, poseidon); } class Eddsa { constructor(babyJub, poseidon) { this.babyJub = babyJub; this.poseidon = poseidon; this.F = babyJub.F; } pruneBuffer(buff) { buff[0] = buff[0] & 0xf8; buff[31] = buff[31] & 0x7f; buff[31] = buff[31] | 0x40; return buff; } prv2pub(prv) { const sBuff = this.pruneBuffer( createBlakeHash("blake512").update(prv).digest().slice(0, 32), ); let s = utils.leBuff2int(sBuff); const A = this.babyJub.mulPointEscalar( this.babyJub.Base8, Scalar.shr(s, 3), ); return A; } signPoseidon(prv, msg) { const F = this.babyJub.F; const sBuff = this.pruneBuffer( createBlakeHash("blake512").update(Buffer.from(prv)).digest(), ); const s = Scalar.fromRprLE(sBuff, 0, 32); const A = this.babyJub.mulPointEscalar( this.babyJub.Base8, Scalar.shr(s, 3), ); const composeBuff = new Uint8Array(32 + msg.length); composeBuff.set(sBuff.slice(32), 0); F.toRprLE(composeBuff, 32, msg); const rBuff = createBlakeHash("blake512") .update(Buffer.from(composeBuff)) .digest(); let r = Scalar.mod(Scalar.fromRprLE(rBuff, 0, 64), this.babyJub.subOrder); const R8 = this.babyJub.mulPointEscalar(this.babyJub.Base8, r); const hm = this.poseidon([R8[0], R8[1], A[0], A[1], msg]); const hms = Scalar.e(this.babyJub.F.toObject(hm)); const S = Scalar.mod( Scalar.add(r, Scalar.mul(hms, s)), this.babyJub.subOrder, ); return { R8: R8, S: S, }; } verifyPoseidon(msg, sig, A) { // Check parameters if (typeof sig != "object") return false; if (!Array.isArray(sig.R8)) return false; if (sig.R8.length != 2) return false; if (!this.babyJub.inCurve(sig.R8)) return false; if (!Array.isArray(A)) return false; if (A.length != 2) return false; if (!this.babyJub.inCurve(A)) return false; if (sig.S >= this.babyJub.subOrder) return false; const hm = this.poseidon([sig.R8[0], sig.R8[1], A[0], A[1], msg]); const hms = Scalar.e(this.babyJub.F.toObject(hm)); const Pleft = this.babyJub.mulPointEscalar(this.babyJub.Base8, sig.S); let Pright = this.babyJub.mulPointEscalar(A, Scalar.mul(hms, 8)); Pright = this.babyJub.addPoint(sig.R8, Pright); if (!this.babyJub.F.eq(Pleft[0], Pright[0])) return false; if (!this.babyJub.F.eq(Pleft[1], Pright[1])) return false; return true; } packSignature(sig) { const buff = new Uint8Array(64); const R8p = this.babyJub.packPoint(sig.R8); buff.set(R8p, 0); const Sp = Scalar.toRprLE(buff, 32, sig.S, 32); return buff; } unpackSignature(sigBuff) { return { R8: this.babyJub.unpackPoint(sigBuff.slice(0, 32)), S: Scalar.fromRprLE(sigBuff, 32, 32), }; } }