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.

168 lines
3.5 KiB

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