From 9e078dc2996f93c6f864a89f5a6b1a193e6e4b19 Mon Sep 17 00:00:00 2001 From: Kobi Gurkan Date: Sat, 22 Jun 2019 17:35:37 +0300 Subject: [PATCH] fix: makes mimcsponge usable --- circuits/eddsamimcsponge.circom | 123 ++++++++++++++++++++++++++++++++ index.js | 1 + src/eddsa.js | 44 ++++++++++++ src/mimcsponge.js | 4 ++ 4 files changed, 172 insertions(+) create mode 100644 circuits/eddsamimcsponge.circom diff --git a/circuits/eddsamimcsponge.circom b/circuits/eddsamimcsponge.circom new file mode 100644 index 0000000..419fb91 --- /dev/null +++ b/circuits/eddsamimcsponge.circom @@ -0,0 +1,123 @@ +/* + Copyright 2018 0KIMS association. + + This file is part of circom (Zero Knowledge Circuit Compiler). + + circom is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + circom is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with circom. If not, see . +*/ + +include "compconstant.circom"; +include "pointbits.circom"; +include "mimcsponge.circom"; +include "bitify.circom"; +include "escalarmulany.circom"; +include "escalarmulfix.circom"; + +template EdDSAMiMCSpongeVerifier() { + signal input enabled; + signal input Ax; + signal input Ay; + + signal input S; + signal input R8x; + signal input R8y; + + signal input M; + + var i; + +// Ensure S compConstant.in[i]; + } + compConstant.in[253] <== 0; + compConstant.out === 0; + +// Calculate the h = H(R,A, msg) + + component hash = MiMCSponge(5, 220, 1); + hash.ins[0] <== R8x; + hash.ins[1] <== R8y; + hash.ins[2] <== Ax; + hash.ins[3] <== Ay; + hash.ins[4] <== M; + hash.k <== 0; + + component h2bits = Num2Bits_strict(); + h2bits.in <== hash.outs[0]; + +// Calculate second part of the right side: right2 = h*8*A + + // Multiply by 8 by adding it 3 times. This also ensure that the result is in + // the subgroup. + component dbl1 = BabyDbl(); + dbl1.x <== Ax; + dbl1.y <== Ay; + component dbl2 = BabyDbl(); + dbl2.x <== dbl1.xout; + dbl2.y <== dbl1.yout; + component dbl3 = BabyDbl(); + dbl3.x <== dbl2.xout; + dbl3.y <== dbl2.yout; + + // We check that A is not zero. + component isZero = IsZero(); + isZero.in <== dbl3.x; + isZero.out === 0; + + component mulAny = EscalarMulAny(254); + for (i=0; i<254; i++) { + mulAny.e[i] <== h2bits.out[i]; + } + mulAny.p[0] <== dbl3.xout; + mulAny.p[1] <== dbl3.yout; + + +// Compute the right side: right = R8 + right2 + + component addRight = BabyAdd(); + addRight.x1 <== R8x; + addRight.y1 <== R8y; + addRight.x2 <== mulAny.out[0]; + addRight.y2 <== mulAny.out[1]; + +// Calculate left side of equation left = S*B8 + + var BASE8 = [ + 17777552123799933955779906779655732241715742912184938656739573121738514868268, + 2626589144620713026669568689430873010625803728049924121243784502389097019475 + ]; + component mulFix = EscalarMulFix(253, BASE8); + for (i=0; i<253; i++) { + mulFix.e[i] <== snum2bits.out[i]; + } + +// Do the comparation left == right if enabled; + + component eqCheckX = ForceEqualIfEnabled(); + eqCheckX.enabled <== enabled; + eqCheckX.in[0] <== mulFix.out[0]; + eqCheckX.in[1] <== addRight.xout; + + component eqCheckY = ForceEqualIfEnabled(); + eqCheckY.enabled <== enabled; + eqCheckY.in[0] <== mulFix.out[1]; + eqCheckY.in[1] <== addRight.yout; +} diff --git a/index.js b/index.js index de190c3..46b9807 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,5 @@ exports.smt = require("./src/smt"); exports.eddsa = require("./src/eddsa"); exports.mimc7 = require("./src/mimc7"); +exports.mimcsponge = require("./src/mimcsponge"); exports.babyJub = require("./src/babyjub"); diff --git a/src/eddsa.js b/src/eddsa.js index f3079f3..8ca6cb4 100644 --- a/src/eddsa.js +++ b/src/eddsa.js @@ -3,12 +3,15 @@ const bigInt = require("snarkjs").bigInt; const babyJub = require("./babyjub"); const pedersenHash = require("./pedersenHash").hash; const mimc7 = require("./mimc7"); +const mimcsponge = require("./mimcsponge"); exports.prv2pub= prv2pub; exports.sign = sign; exports.signMiMC = signMiMC; +exports.signMiMCSponge = signMiMCSponge; exports.verify = verify; exports.verifyMiMC = verifyMiMC; +exports.verifyMiMCSponge = verifyMiMCSponge; exports.packSignature = packSignature; exports.unpackSignature = unpackSignature; exports.pruneBuffer = pruneBuffer; @@ -69,6 +72,25 @@ function signMiMC(prv, msg) { }; } +function signMiMCSponge(prv, msg) { + const h1 = createBlakeHash("blake512").update(prv).digest(); + const sBuff = pruneBuffer(h1.slice(0,32)); + const s = bigInt.leBuff2int(sBuff); + const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3)); + + const msgBuff = bigInt.leInt2Buff(msg, 32); + const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest(); + let r = bigInt.leBuff2int(rBuff); + r = r.mod(babyJub.subOrder); + const R8 = babyJub.mulPointEscalar(babyJub.Base8, r); + const hm = mimcsponge.multiHash([R8[0], R8[1], A[0], A[1], msg]); + const S = r.add(hm.mul(s)).mod(babyJub.subOrder); + return { + R8: R8, + S: S + }; +} + function verify(msg, sig, A) { // Check parameters if (typeof sig != "object") return false; @@ -116,6 +138,28 @@ function verifyMiMC(msg, sig, A) { return true; } +function verifyMiMCSponge(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 (!babyJub.inCurve(sig.R8)) return false; + if (!Array.isArray(A)) return false; + if (A.length!= 2) return false; + if (!babyJub.inCurve(A)) return false; + if (sig.S>= babyJub.subOrder) return false; + + const hm = mimcsponge.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]); + + const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S); + let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8"))); + Pright = babyJub.addPoint(sig.R8, Pright); + + if (!Pleft[0].equals(Pright[0])) return false; + if (!Pleft[1].equals(Pright[1])) return false; + return true; +} + function packSignature(sig) { const R8p = babyJub.packPoint(sig.R8); const Sp = bigInt.leInt2Buff(sig.S, 32); diff --git a/src/mimcsponge.js b/src/mimcsponge.js index 651cb3c..bb37a9d 100644 --- a/src/mimcsponge.js +++ b/src/mimcsponge.js @@ -53,6 +53,10 @@ exports.multiHash = (arr, key, numOutputs) => { if (typeof(numOutputs) === "undefined") { numOutputs = 1; } + if (typeof(key) === "undefined") { + key = F.zero; + } + let R = F.zero; let C = F.zero;