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;