keccak256-circom/test/keccak256.js
test/keccak256.jsRaw
1const chai = require("chai");
2const path = require("path");
3const crypto = require("crypto");
4const F1Field = require("ffjavascript").F1Field;
5const Scalar = require("ffjavascript").Scalar;
6exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
7const Fr = new F1Field(exports.p);
8
9const assert = chai.assert;
10
11const keccak256 = require("keccak256");
12
13const wasm_tester = require("circom_tester").wasm;
14const c_tester = require("circom_tester").c;
15
16// const printSignal = require("./helpers/printsignal");
17
18function bytesToU64(byteArray) {
19 // var value = 0;
20 var value = Fr.e(0);
21 for ( var i = byteArray.length - 1; i >= 0; i--) {
22 // value = (value * 256) + byteArray[i];
23 value = Fr.add(Fr.mul(Fr.e(value), Fr.e(256)), Fr.e(byteArray[i]));
24 }
25
26 return value;
27}
28function u64ToBytes(a) {
29 var b = Fr.e(a);
30
31 const buff = new Uint8Array(8);
32 Scalar.toRprLE(buff, 0, b, 8);
33 return buff;
34}
35function u64ToBits(a) {
36 const aBytes = u64ToBytes(a);
37 return bytesToBits(aBytes);
38}
39function bytesToBits(b) {
40 const bits = [];
41 for (let i = 0; i < b.length; i++) {
42 for (let j = 0; j < 8; j++) {
43 if ((Number(b[i])&(1<<j)) > 0) {
44 // bits.push(Fr.e(1));
45 bits.push(1);
46 } else {
47 // bits.push(Fr.e(0));
48 bits.push(0);
49 }
50 }
51 }
52 return bits
53}
54function u64ArrayToBits(u) {
55 let r = [];
56 for (let i = 0; i < u.length; i++) {
57 r = r.concat(u64ToBits(u[i]));
58 }
59 return r
60}
61function bitsToU64(b) {
62 if (b.length != 64) {
63 console.log("b.length = ", b.length, " max=64");
64 return;
65 }
66 const by = bitsToBytes(b)
67 return bytesToU64(by)
68}
69function bitsToBytes(a) {
70 const b = [];
71
72 for (let i=0; i<a.length; i++) {
73 const p = Math.floor(i/8);
74 if (b[p]==undefined) {
75 b[p] = 0;
76 }
77 if (a[i]==1) {
78 b[p] |= 1<<(i%8);
79 }
80 }
81 return b;
82}
83
84function bitsToU64Array(b) {
85 const r = [];
86 for (let i = 0; i < b.length/64; i++) {
87 r.push(bitsToU64(b.slice(i*64, i*64+64)));
88 }
89 return r
90}
91
92function strsToBigInts(a) {
93 let b = [];
94 for (let i=0; i<a.length; i++) {
95 b[i] = Fr.e(a[i]);
96 }
97 return b;
98}
99function intsToBigInts(a) {
100 let b = [];
101 for (let i=0; i<a.length; i++) {
102 b[i] = Fr.e(a[i]);
103 }
104 return b;
105}
106function bigIntsToInts(a) {
107 let b = [];
108 for (let i=0; i<a.length; i++) {
109 b[i] = Number(a[i]);
110 }
111 return b;
112}
113
114describe("Utils test", function () {
115 this.timeout(100000);
116
117 it ("utils", async () => {
118 let a = 3;
119 let aBits = u64ToBits(a);
120 let a2 = bitsToU64(aBits);
121 assert.equal(a2, a);
122 a = 12345;
123 aBits = u64ToBits(a);
124 a2 = bitsToU64(aBits);
125 assert.equal(a2, a);
126
127 a = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
128 aBits = u64ArrayToBits(a);
129 a2 = bitsToU64Array(aBits);
130 assert.deepEqual(a2, a);
131 });
132});
133
134
135describe("Theta test", function () {
136 this.timeout(100000);
137
138 it ("Theta (testvector generated from go)", async () => {
139 const cir = await wasm_tester(path.join(__dirname, "circuits", "theta_test.circom"));
140
141 const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
142 const expectedOut = intsToBigInts([26,9,13,29,47,31,14,8,22,34,16,3,3,19,37,21,24,30,12,56,14,29,25,9,51]);
143 const stateIn = u64ArrayToBits(input);
144 const expectedOutBits = u64ArrayToBits(expectedOut);
145
146 const witness = await cir.calculateWitness({ "in": stateIn }, true);
147
148 const stateOut = witness.slice(1, 1+(25*64));
149 const stateOutU64 = bitsToU64Array(stateOut);
150 // console.log(stateOutU64, expectedOut);
151 assert.deepEqual(stateOutU64, expectedOut);
152 });
153 it ("Theta (same test as previous, but using c_tester to ensure that circom_tester with c works as expected)", async () => {
154 const cir = await c_tester(path.join(__dirname, "circuits", "theta_test.circom"));
155
156 const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
157 const expectedOut = intsToBigInts([26,9,13,29,47,31,14,8,22,34,16,3,3,19,37,21,24,30,12,56,14,29,25,9,51]);
158 const stateIn = u64ArrayToBits(input);
159 const expectedOutBits = u64ArrayToBits(expectedOut);
160
161 const witness = await cir.calculateWitness({ "in": stateIn }, true);
162
163 const stateOut = witness.slice(1, 1+(25*64));
164 const stateOutU64 = bitsToU64Array(stateOut);
165 // console.log(stateOutU64, expectedOut);
166 assert.deepEqual(stateOutU64, expectedOut);
167 });
168
169 it ("Theta (testvector generated from go)", async () => {
170 const cir = await wasm_tester(path.join(__dirname, "circuits", "theta_test.circom"));
171 // const cir = await c_tester(path.join(__dirname, "circuits", "theta_test.circom"));
172
173 const input = strsToBigInts(["26388279066651", "246290629787648", "26388279902208",
174 "25165850", "246290605457408", "7784628352", "844424965783552",
175 "2305843009213694083", "844432714760192", "2305843009249345539",
176 "637534226", "14848", "641204224", "14354", "3670528", "6308236288",
177 "2130304761856", "648518346341354496", "6309216256", "648520476645130240",
178 "4611706359392501763", "792677514882318336", "20340965113972",
179 "4611732197915754499", "792633534417207412"]);
180 const expectedOut = strsToBigInts(["3749081831850030700", "1297317621190464868",
181 "10017560217643747862", "7854780639862409219", "13836147678645575967",
182 "3749090635727681271", "1297915755455157604", "12323429615135705749",
183 "7855062122598582297", "16141814766035214620", "3749090628446369381",
184 "1297071330560683876", "10017586606556924438", "7854780639837253643",
185 "13835971756788491039", "3749090634251287159", "1297070162329376100",
186 "9369068259580659222", "7854780645071013913", "14484490034407743775",
187 "8360757404916954740", "1801500877105239396", "10017570663003408994",
188 "3243123208712177690", "14628605291203076459"]);
189
190 const stateIn = u64ArrayToBits(input);
191 const expectedOutBits = u64ArrayToBits(expectedOut);
192
193 const witness = await cir.calculateWitness({ "in": stateIn }, true);
194
195 const stateOut = witness.slice(1, 1+(25*64));
196 const stateOutU64 = bitsToU64Array(stateOut);
197 assert.deepEqual(stateOutU64, expectedOut);
198 });
199
200
201});
202
203describe("RhoPi test", function () {
204 this.timeout(100000);
205
206 it ("RhoPi (testvector generated from go)", async () => {
207 const cir = await wasm_tester(path.join(__dirname, "circuits", "rhopi_test.circom"));
208
209 const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
210 const expectedOut = strsToBigInts(["0", "105553116266496", "105553116266496", "37748736", "393216",
211 "805306368", "9437184", "80", "562949953421312", "13835058055282163714",
212 "2", "448", "436207616", "4864", "5242880", "536870912", "343597383680",
213 "11264", "557056", "1657324662872342528", "9223372036854775808",
214 "288230376151711744", "7696581394432", "32985348833280", "84"]);
215 const stateIn = u64ArrayToBits(input);
216 const expectedOutBits = u64ArrayToBits(expectedOut);
217
218 const witness = await cir.calculateWitness({ "in": stateIn }, true);
219
220 const stateOut = witness.slice(1, 1+(25*64));
221 const stateOutU64 = bitsToU64Array(stateOut);
222 // console.log(stateOutU64, expectedOut);
223 assert.deepEqual(stateOutU64, expectedOut);
224 });
225});
226
227describe("Chi test", function () {
228 this.timeout(100000);
229
230 it ("Chi (testvector generated from go)", async () => {
231 const cir = await wasm_tester(path.join(__dirname, "circuits", "chi_test.circom"));
232
233 const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
234 const expectedOut = intsToBigInts([2, 0, 6, 3, 5, 4, 14, 6, 12, 11, 14, 10, 14, 13, 15,
235 14, 18, 16, 30, 3, 22, 20, 30, 19, 25]);
236 const stateIn = u64ArrayToBits(input);
237 const expectedOutBits = u64ArrayToBits(expectedOut);
238
239 const witness = await cir.calculateWitness({ "in": stateIn }, true);
240
241 const stateOut = witness.slice(1, 1+(25*64));
242 const stateOutU64 = bitsToU64Array(stateOut);
243 // console.log(stateOutU64, expectedOut);
244 assert.deepEqual(stateOutU64, expectedOut);
245 });
246});
247
248describe("Iota test", function () {
249 this.timeout(100000);
250
251 it ("Iota 3 (testvector generated from go)", async () => {
252 const cir = await wasm_tester(path.join(__dirname, "circuits", "iota3_test.circom"));
253
254 const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
255 const expectedOut = strsToBigInts(["9223372039002292224",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
256 const stateIn = u64ArrayToBits(input);
257 const expectedOutBits = u64ArrayToBits(expectedOut);
258
259 const witness = await cir.calculateWitness({ "in": stateIn }, true);
260
261 const stateOut = witness.slice(1, 1+(25*64));
262 const stateOutU64 = bitsToU64Array(stateOut);
263 // console.log(stateOutU64, expectedOut);
264 assert.deepEqual(stateOutU64, expectedOut);
265 });
266 it ("Iota 10 (testvector generated from go)", async () => {
267 const cir = await wasm_tester(path.join(__dirname, "circuits", "iota10_test.circom"));
268
269 const input = strsToBigInts(["9223372039002292224",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
270 const expectedOut = strsToBigInts(["9223372036854775817",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]);
271 const stateIn = u64ArrayToBits(input);
272 const expectedOutBits = u64ArrayToBits(expectedOut);
273
274 const witness = await cir.calculateWitness({ "in": stateIn }, true);
275
276 const stateOut = witness.slice(1, 1+(25*64));
277 const stateOutU64 = bitsToU64Array(stateOut);
278 // console.log(stateOutU64, expectedOut);
279 assert.deepEqual(stateOutU64, expectedOut);
280 });
281});
282
283describe("Keccak-Pad test", function () {
284 this.timeout(100000);
285
286 it ("Pad (testvector generated from go)", async () => {
287 const cir = await wasm_tester(path.join(__dirname, "circuits", "pad_test.circom"));
288
289 const input = [0,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];
290 const expectedOut = [0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128];
291
292 const stateIn = bytesToBits(input);
293
294 const witness = await cir.calculateWitness({ "in": stateIn }, true);
295
296 const stateOut = witness.slice(1, 1+(136*8));
297 const stateOutBytes = bitsToBytes(stateOut);
298 // console.log(stateOutBytes, expectedOut);
299 assert.deepEqual(stateOutBytes, expectedOut);
300 });
301});
302
303describe("keccakf test", function () {
304 this.timeout(100000);
305
306 // apt install nlohmann-json3-dev
307 // apt install nasm
308
309 it ("keccakfRound (testvector generated from go)", async () => {
310 // const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
311 const cir = await c_tester(path.join(__dirname, "circuits", "keccakfRound0_test.circom"));
312 await cir.loadConstraints();
313 // console.log("n_constraints", cir.constraints.length);
314
315 const input = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24];
316 const expectedOut = strsToBigInts(["26388279066651", "246290629787648", "26388279902208", "25165850", "246290605457408", "7784628352", "844424965783552", "2305843009213694083", "844432714760192", "2305843009249345539", "637534226", "14848", "641204224", "14354", "3670528", "6308236288", "2130304761856", "648518346341354496", "6309216256", "648520476645130240", "4611706359392501763", "792677514882318336", "20340965113972", "4611732197915754499", "792633534417207412"]);
317
318 const stateIn = u64ArrayToBits(input);
319 const expectedOutBits = u64ArrayToBits(expectedOut);
320
321 const witness = await cir.calculateWitness({ "in": stateIn }, true);
322
323 const stateOut = witness.slice(1, 1+(25*64));
324 const stateOutU64 = bitsToU64Array(stateOut);
325 // console.log(stateOutU64, expectedOut);
326 assert.deepEqual(stateOutU64, expectedOut);
327 });
328
329 it ("keccakfRound 20 (testvector generated from go)", async () => {
330 // const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
331 const cir = await c_tester(path.join(__dirname, "circuits", "keccakfRound20_test.circom"));
332 await cir.loadConstraints();
333 // console.log("n_constraints", cir.constraints.length);
334
335 const input = strsToBigInts(["26388279066651", "246290629787648", "26388279902208", "25165850", "246290605457408", "7784628352", "844424965783552", "2305843009213694083", "844432714760192", "2305843009249345539", "637534226", "14848", "641204224", "14354", "3670528", "6308236288", "2130304761856", "648518346341354496", "6309216256", "648520476645130240", "4611706359392501763", "792677514882318336", "20340965113972", "4611732197915754499", "792633534417207412"]);
336 const expectedOut = strsToBigInts(["17728382861289829725", "13654073086381141005", "9912591532945168756", "2030068283137172501", "5084683018496047808", "151244976540463006", "11718217461613725815", "11636071286320763433", "15039144509240642782", "11629028282864249197", "2594633730779457624", "14005558505838459171", "4612881094252610438", "2828009553220809993", "4838578484623267135", "1006588603063111352", "11109191860075454495", "1187545859779038208", "14661669042642437042", "5345317080454741069", "8196674451365552863", "635818354583088260", "13515759754032305626", "1708499319988748543", "7509292798507899312"]);
337
338 const stateIn = u64ArrayToBits(input);
339 const expectedOutBits = u64ArrayToBits(expectedOut);
340
341 const witness = await cir.calculateWitness({ "in": stateIn }, true);
342
343 const stateOut = witness.slice(1, 1+(25*64));
344 const stateOutU64 = bitsToU64Array(stateOut);
345 // console.log(stateOutU64, expectedOut);
346 assert.deepEqual(stateOutU64, expectedOut);
347 });
348});