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

pragma circom 2.0.0;
include "./utils.circom";
include "./theta.circom";
include "./rhopi.circom";
include "./chi.circom";
include "./iota.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];
}
}