-
Notifications
You must be signed in to change notification settings - Fork 0
/
mimcsponge.js
104 lines (90 loc) · 2.62 KB
/
mimcsponge.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { Scalar, getCurveFromName } from "ffjavascript";
import { ethers } from "ethers";
const SEED = "mimcsponge";
const NROUNDS = 220;
export default async function buildMimcSponge() {
const bn128 = await getCurveFromName("bn128", true);
return new MimcSponge(bn128.Fr);
}
class MimcSponge {
constructor (F) {
this.F = F;
this.cts = this.getConstants(SEED, NROUNDS);
}
getIV (seed) {
const F = this.F;
if (typeof seed === "undefined") seed = SEED;
const c = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(seed+"_iv"));
const cn = Scalar.e(c);
const iv = cn.mod(F.p);
return iv;
};
getConstants (seed, nRounds) {
const F = this.F;
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDS;
const cts = new Array(nRounds);
let c = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(SEED));;
for (let i=1; i<nRounds; i++) {
c = ethers.utils.keccak256(c);
cts[i] = F.e(c);
}
cts[0] = F.e(0);
cts[cts.length - 1] = F.e(0);
return cts;
};
hash(_xL_in, _xR_in, _k) {
const F = this.F;
let xL = F.e(_xL_in);
let xR = F.e(_xR_in);
const k = F.e(_k);
for (let i=0; i<NROUNDS; i++) {
const c = this.cts[i];
const t = (i==0) ? F.add(xL, k) : F.add(F.add(xL, k), c);
const t2 = F.square(t);
const t4 = F.square(t2);
const t5 = F.mul(t4, t);
const xR_tmp = F.e(xR);
if (i < (NROUNDS - 1)) {
xR = xL;
xL = F.add(xR_tmp, t5);
} else {
xR = F.add(xR_tmp, t5);
}
}
return {
xL: xL,
xR: xR
};
}
multiHash(arr, key, numOutputs) {
const F = this.F;
if (typeof(numOutputs) === "undefined") {
numOutputs = 1;
}
if (typeof(key) === "undefined") {
key = F.zero;
}
let R = F.zero;
let C = F.zero;
for (let i=0; i<arr.length; i++) {
R = F.add(R, F.e(arr[i]));
const S = this.hash(R, C, key);
R = S.xL;
C = S.xR;
}
let outputs = [R];
for (let i=1; i < numOutputs; i++) {
const S = this.hash(R, C, key);
R = S.xL;
C = S.xR;
outputs.push(R);
}
if (numOutputs == 1) {
return outputs[0];
} else {
return outputs;
}
}
result =
}