|
|
pragma circom 2.0.0;
include "./utils.circom"; include "./permutations.circom";
template Pad(nBits) { signal input in[nBits];
var blockSize=136*8; signal output out[blockSize]; signal out2[blockSize];
var i;
for (i=0; i<nBits; i++) { out2[i] <== in[i]; } var domain = 0x01; for (i=0; i<8; i++) { out2[nBits+i] <== (domain >> i) & 1; } for (i=nBits+8; i<blockSize; i++) { out2[i] <== 0; } component aux = OrArray(8); for (i=0; i<8; i++) { aux.a[i] <== out2[blockSize-8+i]; aux.b[i] <== (0x80 >> i) & 1; } for (i=0; i<8; i++) { out[blockSize-8+i] <== aux.out[i]; } for (i=0; i<blockSize-8; i++) { out[i]<==out2[i]; } }
template KeccakfRound(r) { signal input in[25*64]; signal output out[25*64]; var i;
component theta = Theta(); component rhopi = RhoPi(); component chi = Chi(); component iota = Iota(r);
for (i=0; i<25*64; i++) { theta.in[i] <== in[i]; } for (i=0; i<25*64; i++) { rhopi.in[i] <== theta.out[i]; } for (i=0; i<25*64; i++) { chi.in[i] <== rhopi.out[i]; } for (i=0; i<25*64; i++) { iota.in[i] <== chi.out[i]; } for (i=0; i<25*64; i++) { out[i] <== iota.out[i]; } }
template Absorb() { var blockSizeBytes=136;
signal input s[25*64]; signal input block[blockSizeBytes*8]; signal output out[25*64]; var i; var j;
component aux[blockSizeBytes/8]; component newS = Keccakf();
for (i=0; i<blockSizeBytes/8; i++) { aux[i] = XorArray(64); for (j=0; j<64; j++) { aux[i].a[j] <== s[i*64+j]; aux[i].b[j] <== block[i*64+j]; } for (j=0; j<64; j++) { newS.in[i*64+j] <== aux[i].out[j]; } } // fill the missing s that was not covered by the loop over // blockSizeBytes/8 for (i=(blockSizeBytes/8)*64; i<25*64; i++) { newS.in[i] <== s[i]; } for (i=0; i<25*64; i++) { out[i] <== newS.out[i]; } }
template Final(nBits) { signal input in[nBits]; signal output out[25*64]; var blockSize=136*8; var i;
// pad component pad = Pad(nBits); for (i=0; i<nBits; i++) { pad.in[i] <== in[i]; } // absorb component abs = Absorb(); for (i=0; i<blockSize; i++) { abs.block[i] <== pad.out[i]; } for (i=0; i<25*64; i++) { abs.s[i] <== 0; } for (i=0; i<25*64; i++) { out[i] <== abs.out[i]; } }
template Squeeze(nBits) { signal input s[25*64]; signal output out[nBits]; var i; var j;
for (i=0; i<25; i++) { for (j=0; j<64; j++) { if (i*64+j<nBits) { out[i*64+j] <== s[i*64+j]; } } } }
template Keccakf() { signal input in[25*64]; signal output out[25*64]; var i; var j;
// 24 rounds component round[24]; signal midRound[24*25*64]; for (i=0; i<24; i++) { round[i] = KeccakfRound(i); if (i==0) { for (j=0; j<25*64; j++) { midRound[j] <== in[j]; } } for (j=0; j<25*64; j++) { round[i].in[j] <== midRound[i*25*64+j]; } if (i<23) { for (j=0; j<25*64; j++) { midRound[(i+1)*25*64+j] <== round[i].out[j]; } } }
for (i=0; i<25*64; i++) { out[i] <== round[23].out[i]; } }
template Keccak(nBits) { signal input in[nBits]; signal output out[nBits]; var i;
component f = Final(nBits); for (i=0; i<nBits; i++) { f.in[i] <== in[i]; } component squeeze = Squeeze(nBits); for (i=0; i<25*64; i++) { squeeze.s[i] <== f.out[i]; } for (i=0; i<nBits; i++) { out[i] <== squeeze.out[i]; } }
|