arnaucube
arnaucube/keccak256-circomPublic Self-hosted repository
keccak256-circom/circuits/permutations.circom
circuits/permutations.circomRaw
  1// Keccak256 hash function (ethereum version).
  2// For LICENSE check https://github.com/vocdoni/keccak256-circom/blob/master/LICENSE
  3
  4pragma circom 2.0.0;
  5
  6include "./utils.circom";
  7
  8
  9// Theta
 10
 11template D(n, shl, shr) {
 12    // d = b ^ (a<<shl | a>>shr)
 13    signal input a[n];
 14    signal input b[n];
 15    signal output out[n];
 16    var i;
 17
 18    component aux0 = ShR(64, shr);
 19    for (i=0; i<64; i++) {
 20        aux0.in[i] <== a[i];
 21    }
 22    component aux1 = ShL(64, shl);
 23    for (i=0; i<64; i++) {
 24        aux1.in[i] <== a[i];
 25    }
 26    component aux2 = OrArray(64);
 27    for (i=0; i<64; i++) {
 28        aux2.a[i] <== aux0.out[i];
 29        aux2.b[i] <== aux1.out[i];
 30    }
 31    component aux3 = XorArray(64);
 32    for (i=0; i<64; i++) {
 33        aux3.a[i] <== b[i];
 34        aux3.b[i] <== aux2.out[i];
 35    }
 36    for (i=0; i<64; i++) {
 37        out[i] <== aux3.out[i];
 38    }
 39}
 40
 41template Theta() {
 42    signal input in[25*64];
 43    signal output out[25*64];
 44
 45    var i;
 46
 47    component c0 = Xor5(64);
 48    for (i=0; i<64; i++) {
 49        c0.a[i] <== in[i];
 50        c0.b[i] <== in[5*64+i];
 51        c0.c[i] <== in[10*64+i];
 52        c0.d[i] <== in[15*64+i];
 53        c0.e[i] <== in[20*64+i];
 54    }
 55
 56    component c1 = Xor5(64);
 57    for (i=0; i<64; i++) {
 58        c1.a[i] <== in[1*64+i];
 59        c1.b[i] <== in[6*64+i];
 60        c1.c[i] <== in[11*64+i];
 61        c1.d[i] <== in[16*64+i];
 62        c1.e[i] <== in[21*64+i];
 63    }
 64
 65    component c2 = Xor5(64);
 66    for (i=0; i<64; i++) {
 67        c2.a[i] <== in[2*64+i];
 68        c2.b[i] <== in[7*64+i];
 69        c2.c[i] <== in[12*64+i];
 70        c2.d[i] <== in[17*64+i];
 71        c2.e[i] <== in[22*64+i];
 72    }
 73
 74    component c3 = Xor5(64);
 75    for (i=0; i<64; i++) {
 76        c3.a[i] <== in[3*64+i];
 77        c3.b[i] <== in[8*64+i];
 78        c3.c[i] <== in[13*64+i];
 79        c3.d[i] <== in[18*64+i];
 80        c3.e[i] <== in[23*64+i];
 81    }
 82
 83    component c4 = Xor5(64);
 84    for (i=0; i<64; i++) {
 85        c4.a[i] <== in[4*64+i];
 86        c4.b[i] <== in[9*64+i];
 87        c4.c[i] <== in[14*64+i];
 88        c4.d[i] <== in[19*64+i];
 89        c4.e[i] <== in[24*64+i];
 90    }
 91
 92    // d = c4 ^ (c1<<1 | c1>>(64-1))
 93    component d0 = D(64, 1, 64-1);
 94    for (i=0; i<64; i++) {
 95        d0.a[i] <== c1.out[i];
 96        d0.b[i] <== c4.out[i];
 97    }
 98    // r[0] = a[0] ^ d
 99    component r0 = XorArray(64);
100    for (i=0; i<64; i++) {
101        r0.a[i] <== in[i];
102        r0.b[i] <== d0.out[i];
103    }
104    for (i=0; i<64; i++) {
105        out[i] <== r0.out[i];
106    }
107    // r[5] = a[5] ^ d
108    component r5 = XorArray(64);
109    for (i=0; i<64; i++) {
110        r5.a[i] <== in[5*64+i];
111        r5.b[i] <== d0.out[i];
112    }
113    for (i=0; i<64; i++) {
114        out[5*64+i] <== r5.out[i];
115    }
116    // r[10] = a[10] ^ d
117    component r10 = XorArray(64);
118    for (i=0; i<64; i++) {
119        r10.a[i] <== in[10*64+i];
120        r10.b[i] <== d0.out[i];
121    }
122    for (i=0; i<64; i++) {
123        out[10*64+i] <== r10.out[i];
124    }
125    // r[15] = a[15] ^ d
126    component r15 = XorArray(64);
127    for (i=0; i<64; i++) {
128        r15.a[i] <== in[15*64+i];
129        r15.b[i] <== d0.out[i];
130    }
131    for (i=0; i<64; i++) {
132        out[15*64+i] <== r15.out[i];
133    }
134    // r[20] = a[20] ^ d
135    component r20 = XorArray(64);
136    for (i=0; i<64; i++) {
137        r20.a[i] <== in[20*64+i];
138        r20.b[i] <== d0.out[i];
139    }
140    for (i=0; i<64; i++) {
141        out[20*64+i] <== r20.out[i];
142    }
143
144    // d = c0 ^ (c2<<1 | c2>>(64-1))
145    component d1 = D(64, 1, 64-1);
146    for (i=0; i<64; i++) {
147        d1.a[i] <== c2.out[i];
148        d1.b[i] <== c0.out[i];
149    }
150    // r[1] = a[1] ^ d
151    component r1 = XorArray(64);
152    for (i=0; i<64; i++) {
153        r1.a[i] <== in[1*64+i];
154        r1.b[i] <== d1.out[i];
155    }
156    for (i=0; i<64; i++) {
157        out[1*64+i] <== r1.out[i];
158    }
159    // r[6] = a[6] ^ d
160    component r6 = XorArray(64);
161    for (i=0; i<64; i++) {
162        r6.a[i] <== in[6*64+i];
163        r6.b[i] <== d1.out[i];
164    }
165    for (i=0; i<64; i++) {
166        out[6*64+i] <== r6.out[i];
167    }
168    // r[11] = a[11] ^ d
169    component r11 = XorArray(64);
170    for (i=0; i<64; i++) {
171        r11.a[i] <== in[11*64+i];
172        r11.b[i] <== d1.out[i];
173    }
174    for (i=0; i<64; i++) {
175        out[11*64+i] <== r11.out[i];
176    }
177    // r[16] = a[16] ^ d
178    component r16 = XorArray(64);
179    for (i=0; i<64; i++) {
180        r16.a[i] <== in[16*64+i];
181        r16.b[i] <== d1.out[i];
182    }
183    for (i=0; i<64; i++) {
184        out[16*64+i] <== r16.out[i];
185    }
186    // r[21] = a[21] ^ d
187    component r21 = XorArray(64);
188    for (i=0; i<64; i++) {
189        r21.a[i] <== in[21*64+i];
190        r21.b[i] <== d1.out[i];
191    }
192    for (i=0; i<64; i++) {
193        out[21*64+i] <== r21.out[i];
194    }
195
196    // d = c1 ^ (c3<<1 | c3>>(64-1))
197    component d2 = D(64, 1, 64-1);
198    for (i=0; i<64; i++) {
199        d2.a[i] <== c3.out[i];
200        d2.b[i] <== c1.out[i];
201    }
202    // r[2] = a[2] ^ d
203    component r2 = XorArray(64);
204    for (i=0; i<64; i++) {
205        r2.a[i] <== in[2*64+i];
206        r2.b[i] <== d2.out[i];
207    }
208    for (i=0; i<64; i++) {
209        out[2*64+i] <== r2.out[i];
210    }
211    // r[7] = a[7] ^ d
212    component r7 = XorArray(64);
213    for (i=0; i<64; i++) {
214        r7.a[i] <== in[7*64+i];
215        r7.b[i] <== d2.out[i];
216    }
217    for (i=0; i<64; i++) {
218        out[7*64+i] <== r7.out[i];
219    }
220    // r[12] = a[12] ^ d
221    component r12 = XorArray(64);
222    for (i=0; i<64; i++) {
223        r12.a[i] <== in[12*64+i];
224        r12.b[i] <== d2.out[i];
225    }
226    for (i=0; i<64; i++) {
227        out[12*64+i] <== r12.out[i];
228    }
229    // r[17] = a[17] ^ d
230    component r17 = XorArray(64);
231    for (i=0; i<64; i++) {
232        r17.a[i] <== in[17*64+i];
233        r17.b[i] <== d2.out[i];
234    }
235    for (i=0; i<64; i++) {
236        out[17*64+i] <== r17.out[i];
237    }
238    // r[22] = a[22] ^ d
239    component r22 = XorArray(64);
240    for (i=0; i<64; i++) {
241        r22.a[i] <== in[22*64+i];
242        r22.b[i] <== d2.out[i];
243    }
244    for (i=0; i<64; i++) {
245        out[22*64+i] <== r22.out[i];
246    }
247
248    // d = c2 ^ (c4<<1 | c4>>(64-1))
249    component d3 = D(64, 1, 64-1);
250    for (i=0; i<64; i++) {
251        d3.a[i] <== c4.out[i];
252        d3.b[i] <== c2.out[i];
253    }
254    // r[3] = a[3] ^ d
255    component r3 = XorArray(64);
256    for (i=0; i<64; i++) {
257        r3.a[i] <== in[3*64+i];
258        r3.b[i] <== d3.out[i];
259    }
260    for (i=0; i<64; i++) {
261        out[3*64+i] <== r3.out[i];
262    }
263    // r[8] = a[8] ^ d
264    component r8 = XorArray(64);
265    for (i=0; i<64; i++) {
266        r8.a[i] <== in[8*64+i];
267        r8.b[i] <== d3.out[i];
268    }
269    for (i=0; i<64; i++) {
270        out[8*64+i] <== r8.out[i];
271    }
272    // r[13] = a[13] ^ d
273    component r13 = XorArray(64);
274    for (i=0; i<64; i++) {
275        r13.a[i] <== in[13*64+i];
276        r13.b[i] <== d3.out[i];
277    }
278    for (i=0; i<64; i++) {
279        out[13*64+i] <== r13.out[i];
280    }
281    // r[18] = a[18] ^ d
282    component r18 = XorArray(64);
283    for (i=0; i<64; i++) {
284        r18.a[i] <== in[18*64+i];
285        r18.b[i] <== d3.out[i];
286    }
287    for (i=0; i<64; i++) {
288        out[18*64+i] <== r18.out[i];
289    }
290    // r[23] = a[23] ^ d
291    component r23 = XorArray(64);
292    for (i=0; i<64; i++) {
293        r23.a[i] <== in[23*64+i];
294        r23.b[i] <== d3.out[i];
295    }
296    for (i=0; i<64; i++) {
297        out[23*64+i] <== r23.out[i];
298    }
299
300    // d = c3 ^ (c0<<1 | c0>>(64-1))
301    component d4 = D(64, 1, 64-1);
302    for (i=0; i<64; i++) {
303        d4.a[i] <== c0.out[i];
304        d4.b[i] <== c3.out[i];
305    }
306    // r[4] = a[4] ^ d
307    component r4 = XorArray(64);
308    for (i=0; i<64; i++) {
309        r4.a[i] <== in[4*64+i];
310        r4.b[i] <== d4.out[i];
311    }
312    for (i=0; i<64; i++) {
313        out[4*64+i] <== r4.out[i];
314    }
315    // r[9] = a[9] ^ d
316    component r9 = XorArray(64);
317    for (i=0; i<64; i++) {
318        r9.a[i] <== in[9*64+i];
319        r9.b[i] <== d4.out[i];
320    }
321    for (i=0; i<64; i++) {
322        out[9*64+i] <== r9.out[i];
323    }
324    // r[14] = a[14] ^ d
325    component r14 = XorArray(64);
326    for (i=0; i<64; i++) {
327        r14.a[i] <== in[14*64+i];
328        r14.b[i] <== d4.out[i];
329    }
330    for (i=0; i<64; i++) {
331        out[14*64+i] <== r14.out[i];
332    }
333    // r[19] = a[19] ^ d
334    component r19 = XorArray(64);
335    for (i=0; i<64; i++) {
336        r19.a[i] <== in[19*64+i];
337        r19.b[i] <== d4.out[i];
338    }
339    for (i=0; i<64; i++) {
340        out[19*64+i] <== r19.out[i];
341    }
342    // r[24] = a[24] ^ d
343    component r24 = XorArray(64);
344    for (i=0; i<64; i++) {
345        r24.a[i] <== in[24*64+i];
346        r24.b[i] <== d4.out[i];
347    }
348    for (i=0; i<64; i++) {
349        out[24*64+i] <== r24.out[i];
350    }
351}
352
353// RhoPi
354
355template stepRhoPi(shl, shr) {
356    // out = a<<shl|a>>shr
357    signal input a[64];
358    signal output out[64];
359    var i;
360
361    component aux0 = ShR(64, shr);
362    for (i=0; i<64; i++) {
363        aux0.in[i] <== a[i];
364    }
365    component aux1 = ShL(64, shl);
366    for (i=0; i<64; i++) {
367        aux1.in[i] <== a[i];
368    }
369    component aux2 = OrArray(64);
370    for (i=0; i<64; i++) {
371        aux2.a[i] <== aux0.out[i];
372        aux2.b[i] <== aux1.out[i];
373    }
374    for (i=0; i<64; i++) {
375        out[i] <== aux2.out[i];
376    }
377}
378template RhoPi() {
379    signal input in[25*64];
380    signal output out[25*64];
381
382    var i;
383
384    // r[10] = a[1]<<1|a[1]>>(64-1)
385    component s10 = stepRhoPi(1, 64-1);
386    for (i=0; i<64; i++) {
387        s10.a[i] <== in[1*64+i];
388    }
389    // r[7] = a[10]<<3|a[10]>>(64-3)
390    component s7 = stepRhoPi(3, 64-3);
391    for (i=0; i<64; i++) {
392        s7.a[i] <== in[10*64+i];
393    }
394    // r[11] = a[7]<<6|a[7]>>(64-6)
395    component s11 = stepRhoPi(6, 64-6);
396    for (i=0; i<64; i++) {
397        s11.a[i] <== in[7*64+i];
398    }
399    // r[17] = a[11]<<10|a[11]>>(64-10)
400    component s17 = stepRhoPi(10, 64-10);
401    for (i=0; i<64; i++) {
402        s17.a[i] <== in[11*64+i];
403    }
404    // r[18] = a[17]<<15|a[17]>>(64-15)
405    component s18 = stepRhoPi(15, 64-15);
406    for (i=0; i<64; i++) {
407        s18.a[i] <== in[17*64+i];
408    }
409    // r[3] = a[18]<<21|a[18]>>(64-21)
410    component s3 = stepRhoPi(21, 64-21);
411    for (i=0; i<64; i++) {
412        s3.a[i] <== in[18*64+i];
413    }
414    // r[5] = a[3]<<28|a[3]>>(64-28)
415    component s5 = stepRhoPi(28, 64-28);
416    for (i=0; i<64; i++) {
417        s5.a[i] <== in[3*64+i];
418    }
419    // r[16] = a[5]<<36|a[5]>>(64-36)
420    component s16 = stepRhoPi(36, 64-36);
421    for (i=0; i<64; i++) {
422        s16.a[i] <== in[5*64+i];
423    }
424    // r[8] = a[16]<<45|a[16]>>(64-45)
425    component s8 = stepRhoPi(45, 64-45);
426    for (i=0; i<64; i++) {
427        s8.a[i] <== in[16*64+i];
428    }
429    // r[21] = a[8]<<55|a[8]>>(64-55)
430    component s21 = stepRhoPi(55, 64-55);
431    for (i=0; i<64; i++) {
432        s21.a[i] <== in[8*64+i];
433    }
434    // r[24] = a[21]<<2|a[21]>>(64-2)
435    component s24 = stepRhoPi(2, 64-2);
436    for (i=0; i<64; i++) {
437        s24.a[i] <== in[21*64+i];
438    }
439    // r[4] = a[24]<<14|a[24]>>(64-14)
440    component s4 = stepRhoPi(14, 64-14);
441    for (i=0; i<64; i++) {
442        s4.a[i] <== in[24*64+i];
443    }
444    // r[15] = a[4]<<27|a[4]>>(64-27)
445    component s15 = stepRhoPi(27, 64-27);
446    for (i=0; i<64; i++) {
447        s15.a[i] <== in[4*64+i];
448    }
449    // r[23] = a[15]<<41|a[15]>>(64-41)
450    component s23 = stepRhoPi(41, 64-41);
451    for (i=0; i<64; i++) {
452        s23.a[i] <== in[15*64+i];
453    }
454    // r[19] = a[23]<<56|a[23]>>(64-56)
455    component s19 = stepRhoPi(56, 64-56);
456    for (i=0; i<64; i++) {
457        s19.a[i] <== in[23*64+i];
458    }
459    // r[13] = a[19]<<8|a[19]>>(64-8)
460    component s13 = stepRhoPi(8, 64-8);
461    for (i=0; i<64; i++) {
462        s13.a[i] <== in[19*64+i];
463    }
464    // r[12] = a[13]<<25|a[13]>>(64-25)
465    component s12 = stepRhoPi(25, 64-25);
466    for (i=0; i<64; i++) {
467        s12.a[i] <== in[13*64+i];
468    }
469    // r[2] = a[12]<<43|a[12]>>(64-43)
470    component s2 = stepRhoPi(43, 64-43);
471    for (i=0; i<64; i++) {
472        s2.a[i] <== in[12*64+i];
473    }
474    // r[20] = a[2]<<62|a[2]>>(64-62)
475    component s20 = stepRhoPi(62, 64-62);
476    for (i=0; i<64; i++) {
477        s20.a[i] <== in[2*64+i];
478    }
479    // r[14] = a[20]<<18|a[20]>>(64-18)
480    component s14 = stepRhoPi(18, 64-18);
481    for (i=0; i<64; i++) {
482        s14.a[i] <== in[20*64+i];
483    }
484    // r[22] = a[14]<<39|a[14]>>(64-39)
485    component s22 = stepRhoPi(39, 64-39);
486    for (i=0; i<64; i++) {
487        s22.a[i] <== in[14*64+i];
488    }
489    // r[9] = a[22]<<61|a[22]>>(64-61)
490    component s9 = stepRhoPi(61, 64-61);
491    for (i=0; i<64; i++) {
492        s9.a[i] <== in[22*64+i];
493    }
494    // r[6] = a[9]<<20|a[9]>>(64-20)
495    component s6 = stepRhoPi(20, 64-20);
496    for (i=0; i<64; i++) {
497        s6.a[i] <== in[9*64+i];
498    }
499    // r[1] = a[6]<<44|a[6]>>(64-44)
500    component s1 = stepRhoPi(44, 64-44);
501    for (i=0; i<64; i++) {
502        s1.a[i] <== in[6*64+i];
503    }
504
505    for (i=0; i<64; i++) {
506        out[i] <== in[i];
507        out[10*64+i] <== s10.out[i];
508        out[7*64+i] <== s7.out[i];
509        out[11*64+i] <== s11.out[i];
510        out[17*64+i] <== s17.out[i];
511        out[18*64+i] <== s18.out[i];
512        out[3*64+i] <== s3.out[i];
513        out[5*64+i] <== s5.out[i];
514        out[16*64+i] <== s16.out[i];
515        out[8*64+i] <== s8.out[i];
516        out[21*64+i] <== s21.out[i];
517        out[24*64+i] <== s24.out[i];
518        out[4*64+i] <== s4.out[i];
519        out[15*64+i] <== s15.out[i];
520        out[23*64+i] <== s23.out[i];
521        out[19*64+i] <== s19.out[i];
522        out[13*64+i] <== s13.out[i];
523        out[12*64+i] <== s12.out[i];
524        out[2*64+i] <== s2.out[i];
525        out[20*64+i] <== s20.out[i];
526        out[14*64+i] <== s14.out[i];
527        out[22*64+i] <== s22.out[i];
528        out[9*64+i] <== s9.out[i];
529        out[6*64+i] <== s6.out[i];
530        out[1*64+i] <== s1.out[i];
531    }
532}
533
534
535// Chi
536
537template stepChi() {
538    // out = a ^ (^b) & c
539    signal input a[64];
540    signal input b[64];
541    signal input c[64];
542    signal output out[64];
543    var i;
544
545    // ^b
546    component bXor = XorArraySingle(64);
547    for (i=0; i<64; i++) {
548        bXor.a[i] <== b[i];
549    }
550    // (^b)&c
551    component bc = AndArray(64);
552    for (i=0; i<64; i++) {
553        bc.a[i] <== bXor.out[i];
554        bc.b[i] <== c[i];
555    }
556    // a^(^b)&c
557    component abc = XorArray(64);
558    for (i=0; i<64; i++) {
559        abc.a[i] <== a[i];
560        abc.b[i] <== bc.out[i];
561    }
562    for (i=0; i<64; i++) {
563        out[i] <== abc.out[i];
564    }
565}
566
567template Chi() {
568    signal input in[25*64];
569    signal output out[25*64];
570
571    var i;
572
573    component r0 = stepChi();
574    for (i=0; i<64; i++) {
575        r0.a[i] <== in[i];
576        r0.b[i] <== in[1*64+i];
577        r0.c[i] <== in[2*64+i];
578    }
579    component r1 = stepChi();
580    for (i=0; i<64; i++) {
581        r1.a[i] <== in[1*64+i];
582        r1.b[i] <== in[2*64+i];
583        r1.c[i] <== in[3*64+i];
584    }
585    component r2 = stepChi();
586    for (i=0; i<64; i++) {
587        r2.a[i] <== in[2*64+i];
588        r2.b[i] <== in[3*64+i];
589        r2.c[i] <== in[4*64+i];
590    }
591    component r3 = stepChi();
592    for (i=0; i<64; i++) {
593        r3.a[i] <== in[3*64+i];
594        r3.b[i] <== in[4*64+i];
595        r3.c[i] <== in[0*64+i];
596    }
597    component r4 = stepChi();
598    for (i=0; i<64; i++) {
599        r4.a[i] <== in[4*64+i];
600        r4.b[i] <== in[i];
601        r4.c[i] <== in[1*64+i];
602    }
603
604    component r5 = stepChi();
605    for (i=0; i<64; i++) {
606        r5.a[i] <== in[5*64+i];
607        r5.b[i] <== in[6*64+i];
608        r5.c[i] <== in[7*64+i];
609    }
610    component r6 = stepChi();
611    for (i=0; i<64; i++) {
612        r6.a[i] <== in[6*64+i];
613        r6.b[i] <== in[7*64+i];
614        r6.c[i] <== in[8*64+i];
615    }
616    component r7 = stepChi();
617    for (i=0; i<64; i++) {
618        r7.a[i] <== in[7*64+i];
619        r7.b[i] <== in[8*64+i];
620        r7.c[i] <== in[9*64+i];
621    }
622    component r8 = stepChi();
623    for (i=0; i<64; i++) {
624        r8.a[i] <== in[8*64+i];
625        r8.b[i] <== in[9*64+i];
626        r8.c[i] <== in[5*64+i];
627    }
628    component r9 = stepChi();
629    for (i=0; i<64; i++) {
630        r9.a[i] <== in[9*64+i];
631        r9.b[i] <== in[5*64+i];
632        r9.c[i] <== in[6*64+i];
633    }
634
635    component r10 = stepChi();
636    for (i=0; i<64; i++) {
637        r10.a[i] <== in[10*64+i];
638        r10.b[i] <== in[11*64+i];
639        r10.c[i] <== in[12*64+i];
640    }
641    component r11 = stepChi();
642    for (i=0; i<64; i++) {
643        r11.a[i] <== in[11*64+i];
644        r11.b[i] <== in[12*64+i];
645        r11.c[i] <== in[13*64+i];
646    }
647    component r12 = stepChi();
648    for (i=0; i<64; i++) {
649        r12.a[i] <== in[12*64+i];
650        r12.b[i] <== in[13*64+i];
651        r12.c[i] <== in[14*64+i];
652    }
653    component r13 = stepChi();
654    for (i=0; i<64; i++) {
655        r13.a[i] <== in[13*64+i];
656        r13.b[i] <== in[14*64+i];
657        r13.c[i] <== in[10*64+i];
658    }
659    component r14 = stepChi();
660    for (i=0; i<64; i++) {
661        r14.a[i] <== in[14*64+i];
662        r14.b[i] <== in[10*64+i];
663        r14.c[i] <== in[11*64+i];
664    }
665
666    component r15 = stepChi();
667    for (i=0; i<64; i++) {
668        r15.a[i] <== in[15*64+i];
669        r15.b[i] <== in[16*64+i];
670        r15.c[i] <== in[17*64+i];
671    }
672    component r16 = stepChi();
673    for (i=0; i<64; i++) {
674        r16.a[i] <== in[16*64+i];
675        r16.b[i] <== in[17*64+i];
676        r16.c[i] <== in[18*64+i];
677    }
678    component r17 = stepChi();
679    for (i=0; i<64; i++) {
680        r17.a[i] <== in[17*64+i];
681        r17.b[i] <== in[18*64+i];
682        r17.c[i] <== in[19*64+i];
683    }
684    component r18 = stepChi();
685    for (i=0; i<64; i++) {
686        r18.a[i] <== in[18*64+i];
687        r18.b[i] <== in[19*64+i];
688        r18.c[i] <== in[15*64+i];
689    }
690    component r19 = stepChi();
691    for (i=0; i<64; i++) {
692        r19.a[i] <== in[19*64+i];
693        r19.b[i] <== in[15*64+i];
694        r19.c[i] <== in[16*64+i];
695    }
696
697    component r20 = stepChi();
698    for (i=0; i<64; i++) {
699        r20.a[i] <== in[20*64+i];
700        r20.b[i] <== in[21*64+i];
701        r20.c[i] <== in[22*64+i];
702    }
703    component r21 = stepChi();
704    for (i=0; i<64; i++) {
705        r21.a[i] <== in[21*64+i];
706        r21.b[i] <== in[22*64+i];
707        r21.c[i] <== in[23*64+i];
708    }
709    component r22 = stepChi();
710    for (i=0; i<64; i++) {
711        r22.a[i] <== in[22*64+i];
712        r22.b[i] <== in[23*64+i];
713        r22.c[i] <== in[24*64+i];
714    }
715    component r23 = stepChi();
716    for (i=0; i<64; i++) {
717        r23.a[i] <== in[23*64+i];
718        r23.b[i] <== in[24*64+i];
719        r23.c[i] <== in[20*64+i];
720    }
721    component r24 = stepChi();
722    for (i=0; i<64; i++) {
723        r24.a[i] <== in[24*64+i];
724        r24.b[i] <== in[20*64+i];
725        r24.c[i] <== in[21*64+i];
726    }
727
728    for (i=0; i<64; i++) {
729        out[i] <== r0.out[i];
730        out[1*64+i] <== r1.out[i];
731        out[2*64+i] <== r2.out[i];
732        out[3*64+i] <== r3.out[i];
733        out[4*64+i] <== r4.out[i];
734
735        out[5*64+i] <== r5.out[i];
736        out[6*64+i] <== r6.out[i];
737        out[7*64+i] <== r7.out[i];
738        out[8*64+i] <== r8.out[i];
739        out[9*64+i] <== r9.out[i];
740
741        out[10*64+i] <== r10.out[i];
742        out[11*64+i] <== r11.out[i];
743        out[12*64+i] <== r12.out[i];
744        out[13*64+i] <== r13.out[i];
745        out[14*64+i] <== r14.out[i];
746
747        out[15*64+i] <== r15.out[i];
748        out[16*64+i] <== r16.out[i];
749        out[17*64+i] <== r17.out[i];
750        out[18*64+i] <== r18.out[i];
751        out[19*64+i] <== r19.out[i];
752
753        out[20*64+i] <== r20.out[i];
754        out[21*64+i] <== r21.out[i];
755        out[22*64+i] <== r22.out[i];
756        out[23*64+i] <== r23.out[i];
757        out[24*64+i] <== r24.out[i];
758    }
759}
760
761// Iota
762
763template RC(r) {
764    signal output out[64];
765    var rc[24] = [
766        0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
767        0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
768        0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
769        0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
770        0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
771        0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
772        0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
773        0x8000000000008080, 0x0000000080000001, 0x8000000080008008
774    ];
775    for (var i=0; i<64; i++) {
776        out[i] <== (rc[r] >> i) & 1;
777    }
778}
779
780template Iota(r) {
781    signal input in[25*64];
782    signal output out[25*64];
783    var i;
784
785    component rc = RC(r);
786
787    component iota = XorArray(64);
788    for (var i=0; i<64; i++) {
789        iota.a[i] <== in[i];
790        iota.b[i] <== rc.out[i];
791    }
792    for (i=0; i<64; i++) {
793        out[i] <== iota.out[i];
794    }
795    for (i=64; i<25*64; i++) {
796        out[i] <== in[i];
797    }
798}
799