You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
3.8 KiB

  1. pragma circom 2.0.0;
  2. include "./utils.circom";
  3. include "./permutations.circom";
  4. template Pad(nBits) {
  5. signal input in[nBits];
  6. var blockSize=136*8;
  7. signal output out[blockSize];
  8. signal out2[blockSize];
  9. var i;
  10. for (i=0; i<nBits; i++) {
  11. out2[i] <== in[i];
  12. }
  13. var domain = 0x01;
  14. for (i=0; i<8; i++) {
  15. out2[nBits+i] <== (domain >> i) & 1;
  16. }
  17. for (i=nBits+8; i<blockSize; i++) {
  18. out2[i] <== 0;
  19. }
  20. component aux = OrArray(8);
  21. for (i=0; i<8; i++) {
  22. aux.a[i] <== out2[blockSize-8+i];
  23. aux.b[i] <== (0x80 >> i) & 1;
  24. }
  25. for (i=0; i<8; i++) {
  26. out[blockSize-8+i] <== aux.out[i];
  27. }
  28. for (i=0; i<blockSize-8; i++) {
  29. out[i]<==out2[i];
  30. }
  31. }
  32. template KeccakfRound(r) {
  33. signal input in[25*64];
  34. signal output out[25*64];
  35. var i;
  36. component theta = Theta();
  37. component rhopi = RhoPi();
  38. component chi = Chi();
  39. component iota = Iota(r);
  40. for (i=0; i<25*64; i++) {
  41. theta.in[i] <== in[i];
  42. }
  43. for (i=0; i<25*64; i++) {
  44. rhopi.in[i] <== theta.out[i];
  45. }
  46. for (i=0; i<25*64; i++) {
  47. chi.in[i] <== rhopi.out[i];
  48. }
  49. for (i=0; i<25*64; i++) {
  50. iota.in[i] <== chi.out[i];
  51. }
  52. for (i=0; i<25*64; i++) {
  53. out[i] <== iota.out[i];
  54. }
  55. }
  56. template Absorb() {
  57. var blockSizeBytes=136;
  58. signal input s[25*64];
  59. signal input block[blockSizeBytes*8];
  60. signal output out[25*64];
  61. var i;
  62. var j;
  63. component aux[blockSizeBytes/8];
  64. component newS = Keccakf();
  65. for (i=0; i<blockSizeBytes/8; i++) {
  66. aux[i] = XorArray(64);
  67. for (j=0; j<64; j++) {
  68. aux[i].a[j] <== s[i*64+j];
  69. aux[i].b[j] <== block[i*64+j];
  70. }
  71. for (j=0; j<64; j++) {
  72. newS.in[i*64+j] <== aux[i].out[j];
  73. }
  74. }
  75. // fill the missing s that was not covered by the loop over
  76. // blockSizeBytes/8
  77. for (i=(blockSizeBytes/8)*64; i<25*64; i++) {
  78. newS.in[i] <== s[i];
  79. }
  80. for (i=0; i<25*64; i++) {
  81. out[i] <== newS.out[i];
  82. }
  83. }
  84. template Final(nBits) {
  85. signal input in[nBits];
  86. signal output out[25*64];
  87. var blockSize=136*8;
  88. var i;
  89. // pad
  90. component pad = Pad(nBits);
  91. for (i=0; i<nBits; i++) {
  92. pad.in[i] <== in[i];
  93. }
  94. // absorb
  95. component abs = Absorb();
  96. for (i=0; i<blockSize; i++) {
  97. abs.block[i] <== pad.out[i];
  98. }
  99. for (i=0; i<25*64; i++) {
  100. abs.s[i] <== 0;
  101. }
  102. for (i=0; i<25*64; i++) {
  103. out[i] <== abs.out[i];
  104. }
  105. }
  106. template Squeeze(nBits) {
  107. signal input s[25*64];
  108. signal output out[nBits];
  109. var i;
  110. var j;
  111. for (i=0; i<25; i++) {
  112. for (j=0; j<64; j++) {
  113. if (i*64+j<nBits) {
  114. out[i*64+j] <== s[i*64+j];
  115. }
  116. }
  117. }
  118. }
  119. template Keccakf() {
  120. signal input in[25*64];
  121. signal output out[25*64];
  122. var i;
  123. var j;
  124. // 24 rounds
  125. component round[24];
  126. signal midRound[24*25*64];
  127. for (i=0; i<24; i++) {
  128. round[i] = KeccakfRound(i);
  129. if (i==0) {
  130. for (j=0; j<25*64; j++) {
  131. midRound[j] <== in[j];
  132. }
  133. }
  134. for (j=0; j<25*64; j++) {
  135. round[i].in[j] <== midRound[i*25*64+j];
  136. }
  137. if (i<23) {
  138. for (j=0; j<25*64; j++) {
  139. midRound[(i+1)*25*64+j] <== round[i].out[j];
  140. }
  141. }
  142. }
  143. for (i=0; i<25*64; i++) {
  144. out[i] <== round[23].out[i];
  145. }
  146. }
  147. template Keccak(nBits) {
  148. signal input in[nBits];
  149. signal output out[nBits];
  150. var i;
  151. component f = Final(nBits);
  152. for (i=0; i<nBits; i++) {
  153. f.in[i] <== in[i];
  154. }
  155. component squeeze = Squeeze(nBits);
  156. for (i=0; i<25*64; i++) {
  157. squeeze.s[i] <== f.out[i];
  158. }
  159. for (i=0; i<nBits; i++) {
  160. out[i] <== squeeze.out[i];
  161. }
  162. }