circomlib/src/mimcsponge.js
src/mimcsponge.jsRaw
1const bigInt = require("big-integer");
2const Web3Utils = require("web3-utils");
3const ZqField = require("ffjavascript").ZqField;
4const F = new ZqField(bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
5
6const SEED = "mimcsponge";
7const NROUNDS = 220;
8
9exports.getIV = (seed) => {
10 if (typeof seed === "undefined") seed = SEED;
11 const c = Web3Utils.keccak256(seed+"_iv");
12 const cn = bigInt(Web3Utils.toBN(c).toString());
13 const iv = cn.mod(F.p);
14 return iv;
15};
16
17exports.getConstants = (seed, nRounds) => {
18 if (typeof seed === "undefined") seed = SEED;
19 if (typeof nRounds === "undefined") nRounds = NROUNDS;
20 const cts = new Array(nRounds);
21 let c = Web3Utils.keccak256(SEED);
22 for (let i=1; i<nRounds; i++) {
23 c = Web3Utils.keccak256(c);
24
25 const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.p.toString()));
26 const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
27 cts[i] = bigInt(Web3Utils.toBN(c2).toString());
28 }
29 cts[0] = bigInt(0);
30 cts[cts.length - 1] = bigInt(0);
31 return cts;
32};
33
34const cts = exports.getConstants(SEED, NROUNDS);
35
36exports.hash = (_xL_in, _xR_in, _k) =>{
37 let xL = bigInt(_xL_in);
38 let xR = bigInt(_xR_in);
39 const k = bigInt(_k);
40 for (let i=0; i<NROUNDS; i++) {
41 const c = cts[i];
42 const t = (i==0) ? F.add(xL, k) : F.add(F.add(xL, k), c);
43 const xR_tmp = bigInt(xR);
44 if (i < (NROUNDS - 1)) {
45 xR = xL;
46 xL = F.add(xR_tmp, F.pow(t, 5));
47 } else {
48 xR = F.add(xR_tmp, F.pow(t, 5));
49 }
50 }
51 return {
52 xL: F.normalize(xL),
53 xR: F.normalize(xR),
54 };
55};
56
57exports.multiHash = (arr, key, numOutputs) => {
58 if (typeof(numOutputs) === "undefined") {
59 numOutputs = 1;
60 }
61 if (typeof(key) === "undefined") {
62 key = F.zero;
63 }
64
65 let R = F.zero;
66 let C = F.zero;
67
68 for (let i=0; i<arr.length; i++) {
69 R = F.add(R, bigInt(arr[i]));
70 const S = exports.hash(R, C, key);
71 R = S.xL;
72 C = S.xR;
73 }
74 let outputs = [R];
75 for (let i=1; i < numOutputs; i++) {
76 const S = exports.hash(R, C, key);
77 R = S.xL;
78 C = S.xR;
79 outputs.push(R);
80 }
81 if (numOutputs == 1) {
82 return F.normalize(outputs[0]);
83 } else {
84 return outputs.map(x => F.normalize(x));
85 }
86};