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