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