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.

153 lines
3.3 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 Keccakf() {
  110. signal input in[25*64];
  111. signal output out[25*64];
  112. var i;
  113. var j;
  114. // 24 rounds
  115. component round[24];
  116. signal midRound[24*25*64];
  117. for (i=0; i<24; i++) {
  118. round[i] = KeccakfRound(i);
  119. if (i==0) {
  120. for (j=0; j<25*64; j++) {
  121. midRound[j] <== in[j];
  122. }
  123. }
  124. for (j=0; j<25*64; j++) {
  125. round[i].in[j] <== midRound[i*25*64+j];
  126. }
  127. if (i<23) {
  128. for (j=0; j<25*64; j++) {
  129. midRound[(i+1)*25*64+j] <== round[i].out[j];
  130. }
  131. }
  132. }
  133. for (i=0; i<25*64; i++) {
  134. out[i] <== round[23].out[i];
  135. }
  136. }