diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b3de7e5..6e1f879 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,5 +26,6 @@ jobs: cargo install --path circom - name: run tests run: | + npm cache clean --force npm install npm run test diff --git a/circuits/chi.circom b/circuits/chi.circom deleted file mode 100644 index 9a93e24..0000000 --- a/circuits/chi.circom +++ /dev/null @@ -1,227 +0,0 @@ -pragma circom 2.0.0; - -include "./utils.circom"; - -template step() { - // out = a ^ (^b) & c - signal input a[64]; - signal input b[64]; - signal input c[64]; - signal output out[64]; - var i; - - // ^b - component bXor = XorArraySingle(64); - for (i=0; i<64; i++) { - bXor.a[i] <== b[i]; - } - // (^b)&c - component bc = AndArray(64); - for (i=0; i<64; i++) { - bc.a[i] <== bXor.out[i]; - bc.b[i] <== c[i]; - } - // a^(^b)&c - component abc = XorArray(64); - for (i=0; i<64; i++) { - abc.a[i] <== a[i]; - abc.b[i] <== bc.out[i]; - } - for (i=0; i<64; i++) { - out[i] <== abc.out[i]; - } -} - -template Chi() { - signal input in[25*64]; - signal output out[25*64]; - - var i; - - component r0 = step(); - for (i=0; i<64; i++) { - r0.a[i] <== in[i]; - r0.b[i] <== in[1*64+i]; - r0.c[i] <== in[2*64+i]; - } - component r1 = step(); - for (i=0; i<64; i++) { - r1.a[i] <== in[1*64+i]; - r1.b[i] <== in[2*64+i]; - r1.c[i] <== in[3*64+i]; - } - component r2 = step(); - for (i=0; i<64; i++) { - r2.a[i] <== in[2*64+i]; - r2.b[i] <== in[3*64+i]; - r2.c[i] <== in[4*64+i]; - } - component r3 = step(); - for (i=0; i<64; i++) { - r3.a[i] <== in[3*64+i]; - r3.b[i] <== in[4*64+i]; - r3.c[i] <== in[0*64+i]; - } - component r4 = step(); - for (i=0; i<64; i++) { - r4.a[i] <== in[4*64+i]; - r4.b[i] <== in[i]; - r4.c[i] <== in[1*64+i]; - } - - component r5 = step(); - for (i=0; i<64; i++) { - r5.a[i] <== in[5*64+i]; - r5.b[i] <== in[6*64+i]; - r5.c[i] <== in[7*64+i]; - } - component r6 = step(); - for (i=0; i<64; i++) { - r6.a[i] <== in[6*64+i]; - r6.b[i] <== in[7*64+i]; - r6.c[i] <== in[8*64+i]; - } - component r7 = step(); - for (i=0; i<64; i++) { - r7.a[i] <== in[7*64+i]; - r7.b[i] <== in[8*64+i]; - r7.c[i] <== in[9*64+i]; - } - component r8 = step(); - for (i=0; i<64; i++) { - r8.a[i] <== in[8*64+i]; - r8.b[i] <== in[9*64+i]; - r8.c[i] <== in[5*64+i]; - } - component r9 = step(); - for (i=0; i<64; i++) { - r9.a[i] <== in[9*64+i]; - r9.b[i] <== in[5*64+i]; - r9.c[i] <== in[6*64+i]; - } - - component r10 = step(); - for (i=0; i<64; i++) { - r10.a[i] <== in[10*64+i]; - r10.b[i] <== in[11*64+i]; - r10.c[i] <== in[12*64+i]; - } - component r11 = step(); - for (i=0; i<64; i++) { - r11.a[i] <== in[11*64+i]; - r11.b[i] <== in[12*64+i]; - r11.c[i] <== in[13*64+i]; - } - component r12 = step(); - for (i=0; i<64; i++) { - r12.a[i] <== in[12*64+i]; - r12.b[i] <== in[13*64+i]; - r12.c[i] <== in[14*64+i]; - } - component r13 = step(); - for (i=0; i<64; i++) { - r13.a[i] <== in[13*64+i]; - r13.b[i] <== in[14*64+i]; - r13.c[i] <== in[10*64+i]; - } - component r14 = step(); - for (i=0; i<64; i++) { - r14.a[i] <== in[14*64+i]; - r14.b[i] <== in[10*64+i]; - r14.c[i] <== in[11*64+i]; - } - - component r15 = step(); - for (i=0; i<64; i++) { - r15.a[i] <== in[15*64+i]; - r15.b[i] <== in[16*64+i]; - r15.c[i] <== in[17*64+i]; - } - component r16 = step(); - for (i=0; i<64; i++) { - r16.a[i] <== in[16*64+i]; - r16.b[i] <== in[17*64+i]; - r16.c[i] <== in[18*64+i]; - } - component r17 = step(); - for (i=0; i<64; i++) { - r17.a[i] <== in[17*64+i]; - r17.b[i] <== in[18*64+i]; - r17.c[i] <== in[19*64+i]; - } - component r18 = step(); - for (i=0; i<64; i++) { - r18.a[i] <== in[18*64+i]; - r18.b[i] <== in[19*64+i]; - r18.c[i] <== in[15*64+i]; - } - component r19 = step(); - for (i=0; i<64; i++) { - r19.a[i] <== in[19*64+i]; - r19.b[i] <== in[15*64+i]; - r19.c[i] <== in[16*64+i]; - } - - component r20 = step(); - for (i=0; i<64; i++) { - r20.a[i] <== in[20*64+i]; - r20.b[i] <== in[21*64+i]; - r20.c[i] <== in[22*64+i]; - } - component r21 = step(); - for (i=0; i<64; i++) { - r21.a[i] <== in[21*64+i]; - r21.b[i] <== in[22*64+i]; - r21.c[i] <== in[23*64+i]; - } - component r22 = step(); - for (i=0; i<64; i++) { - r22.a[i] <== in[22*64+i]; - r22.b[i] <== in[23*64+i]; - r22.c[i] <== in[24*64+i]; - } - component r23 = step(); - for (i=0; i<64; i++) { - r23.a[i] <== in[23*64+i]; - r23.b[i] <== in[24*64+i]; - r23.c[i] <== in[20*64+i]; - } - component r24 = step(); - for (i=0; i<64; i++) { - r24.a[i] <== in[24*64+i]; - r24.b[i] <== in[20*64+i]; - r24.c[i] <== in[21*64+i]; - } - - for (i=0; i<64; i++) { - out[i] <== r0.out[i]; - out[1*64+i] <== r1.out[i]; - out[2*64+i] <== r2.out[i]; - out[3*64+i] <== r3.out[i]; - out[4*64+i] <== r4.out[i]; - - out[5*64+i] <== r5.out[i]; - out[6*64+i] <== r6.out[i]; - out[7*64+i] <== r7.out[i]; - out[8*64+i] <== r8.out[i]; - out[9*64+i] <== r9.out[i]; - - out[10*64+i] <== r10.out[i]; - out[11*64+i] <== r11.out[i]; - out[12*64+i] <== r12.out[i]; - out[13*64+i] <== r13.out[i]; - out[14*64+i] <== r14.out[i]; - - out[15*64+i] <== r15.out[i]; - out[16*64+i] <== r16.out[i]; - out[17*64+i] <== r17.out[i]; - out[18*64+i] <== r18.out[i]; - out[19*64+i] <== r19.out[i]; - - out[20*64+i] <== r20.out[i]; - out[21*64+i] <== r21.out[i]; - out[22*64+i] <== r22.out[i]; - out[23*64+i] <== r23.out[i]; - out[24*64+i] <== r24.out[i]; - } -} diff --git a/circuits/iota.circom b/circuits/iota.circom deleted file mode 100644 index 4f40da2..0000000 --- a/circuits/iota.circom +++ /dev/null @@ -1,41 +0,0 @@ -pragma circom 2.0.0; - -include "./utils.circom"; - -template RC(r) { - signal output out[64]; - var rc[24] = [ - 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, - 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, - 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, - 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, - 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, - 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, - 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, - 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 - ]; - for (var i=0; i<64; i++) { - out[i] <== (rc[r] >> i) & 1; - } -} - -template Iota(r) { - signal input in[25*64]; - signal output out[25*64]; - var i; - - component rc = RC(r); - - component iota = XorArray(64); - for (var i=0; i<64; i++) { - iota.a[i] <== in[i]; - iota.b[i] <== rc.out[i]; - } - for (i=0; i<64; i++) { - out[i] <== iota.out[i]; - } - for (i=64; i<25*64; i++) { - out[i] <== in[i]; - } -} - diff --git a/circuits/keccak256.circom b/circuits/keccak.circom similarity index 97% rename from circuits/keccak256.circom rename to circuits/keccak.circom index 76dc78d..61ff39f 100644 --- a/circuits/keccak256.circom +++ b/circuits/keccak.circom @@ -1,10 +1,7 @@ pragma circom 2.0.0; include "./utils.circom"; -include "./theta.circom"; -include "./rhopi.circom"; -include "./chi.circom"; -include "./iota.circom"; +include "./permutations.circom"; template Pad(nBits) { signal input in[nBits]; diff --git a/circuits/permutations.circom b/circuits/permutations.circom new file mode 100644 index 0000000..63d0ab2 --- /dev/null +++ b/circuits/permutations.circom @@ -0,0 +1,796 @@ +pragma circom 2.0.0; + +include "./utils.circom"; + + +// Theta + +template D(n, shl, shr) { + // d = b ^ (a<>shr) + signal input a[n]; + signal input b[n]; + signal output out[n]; + var i; + + component aux0 = ShR(64, shr); + for (i=0; i<64; i++) { + aux0.in[i] <== a[i]; + } + component aux1 = ShL(64, shl); + for (i=0; i<64; i++) { + aux1.in[i] <== a[i]; + } + component aux2 = OrArray(64); + for (i=0; i<64; i++) { + aux2.a[i] <== aux0.out[i]; + aux2.b[i] <== aux1.out[i]; + } + component aux3 = XorArray(64); + for (i=0; i<64; i++) { + aux3.a[i] <== b[i]; + aux3.b[i] <== aux2.out[i]; + } + for (i=0; i<64; i++) { + out[i] <== aux3.out[i]; + } +} + +template Theta() { + signal input in[25*64]; + signal output out[25*64]; + + var i; + + component c0 = Xor5(64); + for (i=0; i<64; i++) { + c0.a[i] <== in[i]; + c0.b[i] <== in[5*64+i]; + c0.c[i] <== in[10*64+i]; + c0.d[i] <== in[15*64+i]; + c0.e[i] <== in[20*64+i]; + } + + component c1 = Xor5(64); + for (i=0; i<64; i++) { + c1.a[i] <== in[1*64+i]; + c1.b[i] <== in[6*64+i]; + c1.c[i] <== in[11*64+i]; + c1.d[i] <== in[16*64+i]; + c1.e[i] <== in[21*64+i]; + } + + component c2 = Xor5(64); + for (i=0; i<64; i++) { + c2.a[i] <== in[2*64+i]; + c2.b[i] <== in[7*64+i]; + c2.c[i] <== in[12*64+i]; + c2.d[i] <== in[17*64+i]; + c2.e[i] <== in[22*64+i]; + } + + component c3 = Xor5(64); + for (i=0; i<64; i++) { + c3.a[i] <== in[3*64+i]; + c3.b[i] <== in[8*64+i]; + c3.c[i] <== in[13*64+i]; + c3.d[i] <== in[18*64+i]; + c3.e[i] <== in[23*64+i]; + } + + component c4 = Xor5(64); + for (i=0; i<64; i++) { + c4.a[i] <== in[4*64+i]; + c4.b[i] <== in[9*64+i]; + c4.c[i] <== in[14*64+i]; + c4.d[i] <== in[19*64+i]; + c4.e[i] <== in[24*64+i]; + } + + // d = c4 ^ (c1<<1 | c1>>(64-1)) + component d0 = D(64, 1, 64-1); + for (i=0; i<64; i++) { + d0.a[i] <== c1.out[i]; + d0.b[i] <== c4.out[i]; + } + // r[0] = a[0] ^ d + component r0 = XorArray(64); + for (i=0; i<64; i++) { + r0.a[i] <== in[i]; + r0.b[i] <== d0.out[i]; + } + for (i=0; i<64; i++) { + out[i] <== r0.out[i]; + } + // r[5] = a[5] ^ d + component r5 = XorArray(64); + for (i=0; i<64; i++) { + r5.a[i] <== in[5*64+i]; + r5.b[i] <== d0.out[i]; + } + for (i=0; i<64; i++) { + out[5*64+i] <== r5.out[i]; + } + // r[10] = a[10] ^ d + component r10 = XorArray(64); + for (i=0; i<64; i++) { + r10.a[i] <== in[10*64+i]; + r10.b[i] <== d0.out[i]; + } + for (i=0; i<64; i++) { + out[10*64+i] <== r10.out[i]; + } + // r[15] = a[15] ^ d + component r15 = XorArray(64); + for (i=0; i<64; i++) { + r15.a[i] <== in[15*64+i]; + r15.b[i] <== d0.out[i]; + } + for (i=0; i<64; i++) { + out[15*64+i] <== r15.out[i]; + } + // r[20] = a[20] ^ d + component r20 = XorArray(64); + for (i=0; i<64; i++) { + r20.a[i] <== in[20*64+i]; + r20.b[i] <== d0.out[i]; + } + for (i=0; i<64; i++) { + out[20*64+i] <== r20.out[i]; + } + + // d = c0 ^ (c2<<1 | c2>>(64-1)) + component d1 = D(64, 1, 64-1); + for (i=0; i<64; i++) { + d1.a[i] <== c2.out[i]; + d1.b[i] <== c0.out[i]; + } + // r[1] = a[1] ^ d + component r1 = XorArray(64); + for (i=0; i<64; i++) { + r1.a[i] <== in[1*64+i]; + r1.b[i] <== d1.out[i]; + } + for (i=0; i<64; i++) { + out[1*64+i] <== r1.out[i]; + } + // r[6] = a[6] ^ d + component r6 = XorArray(64); + for (i=0; i<64; i++) { + r6.a[i] <== in[6*64+i]; + r6.b[i] <== d1.out[i]; + } + for (i=0; i<64; i++) { + out[6*64+i] <== r6.out[i]; + } + // r[11] = a[11] ^ d + component r11 = XorArray(64); + for (i=0; i<64; i++) { + r11.a[i] <== in[11*64+i]; + r11.b[i] <== d1.out[i]; + } + for (i=0; i<64; i++) { + out[11*64+i] <== r11.out[i]; + } + // r[16] = a[16] ^ d + component r16 = XorArray(64); + for (i=0; i<64; i++) { + r16.a[i] <== in[16*64+i]; + r16.b[i] <== d1.out[i]; + } + for (i=0; i<64; i++) { + out[16*64+i] <== r16.out[i]; + } + // r[21] = a[21] ^ d + component r21 = XorArray(64); + for (i=0; i<64; i++) { + r21.a[i] <== in[21*64+i]; + r21.b[i] <== d1.out[i]; + } + for (i=0; i<64; i++) { + out[21*64+i] <== r21.out[i]; + } + + // d = c1 ^ (c3<<1 | c3>>(64-1)) + component d2 = D(64, 1, 64-1); + for (i=0; i<64; i++) { + d2.a[i] <== c3.out[i]; + d2.b[i] <== c1.out[i]; + } + // r[2] = a[2] ^ d + component r2 = XorArray(64); + for (i=0; i<64; i++) { + r2.a[i] <== in[2*64+i]; + r2.b[i] <== d2.out[i]; + } + for (i=0; i<64; i++) { + out[2*64+i] <== r2.out[i]; + } + // r[7] = a[7] ^ d + component r7 = XorArray(64); + for (i=0; i<64; i++) { + r7.a[i] <== in[7*64+i]; + r7.b[i] <== d2.out[i]; + } + for (i=0; i<64; i++) { + out[7*64+i] <== r7.out[i]; + } + // r[12] = a[12] ^ d + component r12 = XorArray(64); + for (i=0; i<64; i++) { + r12.a[i] <== in[12*64+i]; + r12.b[i] <== d2.out[i]; + } + for (i=0; i<64; i++) { + out[12*64+i] <== r12.out[i]; + } + // r[17] = a[17] ^ d + component r17 = XorArray(64); + for (i=0; i<64; i++) { + r17.a[i] <== in[17*64+i]; + r17.b[i] <== d2.out[i]; + } + for (i=0; i<64; i++) { + out[17*64+i] <== r17.out[i]; + } + // r[22] = a[22] ^ d + component r22 = XorArray(64); + for (i=0; i<64; i++) { + r22.a[i] <== in[22*64+i]; + r22.b[i] <== d2.out[i]; + } + for (i=0; i<64; i++) { + out[22*64+i] <== r22.out[i]; + } + + // d = c2 ^ (c4<<1 | c4>>(64-1)) + component d3 = D(64, 1, 64-1); + for (i=0; i<64; i++) { + d3.a[i] <== c4.out[i]; + d3.b[i] <== c2.out[i]; + } + // r[3] = a[3] ^ d + component r3 = XorArray(64); + for (i=0; i<64; i++) { + r3.a[i] <== in[3*64+i]; + r3.b[i] <== d3.out[i]; + } + for (i=0; i<64; i++) { + out[3*64+i] <== r3.out[i]; + } + // r[8] = a[8] ^ d + component r8 = XorArray(64); + for (i=0; i<64; i++) { + r8.a[i] <== in[8*64+i]; + r8.b[i] <== d3.out[i]; + } + for (i=0; i<64; i++) { + out[8*64+i] <== r8.out[i]; + } + // r[13] = a[13] ^ d + component r13 = XorArray(64); + for (i=0; i<64; i++) { + r13.a[i] <== in[13*64+i]; + r13.b[i] <== d3.out[i]; + } + for (i=0; i<64; i++) { + out[13*64+i] <== r13.out[i]; + } + // r[18] = a[18] ^ d + component r18 = XorArray(64); + for (i=0; i<64; i++) { + r18.a[i] <== in[18*64+i]; + r18.b[i] <== d3.out[i]; + } + for (i=0; i<64; i++) { + out[18*64+i] <== r18.out[i]; + } + // r[23] = a[23] ^ d + component r23 = XorArray(64); + for (i=0; i<64; i++) { + r23.a[i] <== in[23*64+i]; + r23.b[i] <== d3.out[i]; + } + for (i=0; i<64; i++) { + out[23*64+i] <== r23.out[i]; + } + + // d = c3 ^ (c0<<1 | c0>>(64-1)) + component d4 = D(64, 1, 64-1); + for (i=0; i<64; i++) { + d4.a[i] <== c0.out[i]; + d4.b[i] <== c3.out[i]; + } + // r[4] = a[4] ^ d + component r4 = XorArray(64); + for (i=0; i<64; i++) { + r4.a[i] <== in[4*64+i]; + r4.b[i] <== d4.out[i]; + } + for (i=0; i<64; i++) { + out[4*64+i] <== r4.out[i]; + } + // r[9] = a[9] ^ d + component r9 = XorArray(64); + for (i=0; i<64; i++) { + r9.a[i] <== in[9*64+i]; + r9.b[i] <== d4.out[i]; + } + for (i=0; i<64; i++) { + out[9*64+i] <== r9.out[i]; + } + // r[14] = a[14] ^ d + component r14 = XorArray(64); + for (i=0; i<64; i++) { + r14.a[i] <== in[14*64+i]; + r14.b[i] <== d4.out[i]; + } + for (i=0; i<64; i++) { + out[14*64+i] <== r14.out[i]; + } + // r[19] = a[19] ^ d + component r19 = XorArray(64); + for (i=0; i<64; i++) { + r19.a[i] <== in[19*64+i]; + r19.b[i] <== d4.out[i]; + } + for (i=0; i<64; i++) { + out[19*64+i] <== r19.out[i]; + } + // r[24] = a[24] ^ d + component r24 = XorArray(64); + for (i=0; i<64; i++) { + r24.a[i] <== in[24*64+i]; + r24.b[i] <== d4.out[i]; + } + for (i=0; i<64; i++) { + out[24*64+i] <== r24.out[i]; + } +} + +// RhoPi + +template stepRhoPi(shl, shr) { + // out = a<>shr + signal input a[64]; + signal output out[64]; + var i; + + component aux0 = ShR(64, shr); + for (i=0; i<64; i++) { + aux0.in[i] <== a[i]; + } + component aux1 = ShL(64, shl); + for (i=0; i<64; i++) { + aux1.in[i] <== a[i]; + } + component aux2 = OrArray(64); + for (i=0; i<64; i++) { + aux2.a[i] <== aux0.out[i]; + aux2.b[i] <== aux1.out[i]; + } + for (i=0; i<64; i++) { + out[i] <== aux2.out[i]; + } +} +template RhoPi() { + signal input in[25*64]; + signal output out[25*64]; + + var i; + + // r[10] = a[1]<<1|a[1]>>(64-1) + component s10 = stepRhoPi(1, 64-1); + for (i=0; i<64; i++) { + s10.a[i] <== in[1*64+i]; + } + // r[7] = a[10]<<3|a[10]>>(64-3) + component s7 = stepRhoPi(3, 64-3); + for (i=0; i<64; i++) { + s7.a[i] <== in[10*64+i]; + } + // r[11] = a[7]<<6|a[7]>>(64-6) + component s11 = stepRhoPi(6, 64-6); + for (i=0; i<64; i++) { + s11.a[i] <== in[7*64+i]; + } + // r[17] = a[11]<<10|a[11]>>(64-10) + component s17 = stepRhoPi(10, 64-10); + for (i=0; i<64; i++) { + s17.a[i] <== in[11*64+i]; + } + // r[18] = a[17]<<15|a[17]>>(64-15) + component s18 = stepRhoPi(15, 64-15); + for (i=0; i<64; i++) { + s18.a[i] <== in[17*64+i]; + } + // r[3] = a[18]<<21|a[18]>>(64-21) + component s3 = stepRhoPi(21, 64-21); + for (i=0; i<64; i++) { + s3.a[i] <== in[18*64+i]; + } + // r[5] = a[3]<<28|a[3]>>(64-28) + component s5 = stepRhoPi(28, 64-28); + for (i=0; i<64; i++) { + s5.a[i] <== in[3*64+i]; + } + // r[16] = a[5]<<36|a[5]>>(64-36) + component s16 = stepRhoPi(36, 64-36); + for (i=0; i<64; i++) { + s16.a[i] <== in[5*64+i]; + } + // r[8] = a[16]<<45|a[16]>>(64-45) + component s8 = stepRhoPi(45, 64-45); + for (i=0; i<64; i++) { + s8.a[i] <== in[16*64+i]; + } + // r[21] = a[8]<<55|a[8]>>(64-55) + component s21 = stepRhoPi(55, 64-55); + for (i=0; i<64; i++) { + s21.a[i] <== in[8*64+i]; + } + // r[24] = a[21]<<2|a[21]>>(64-2) + component s24 = stepRhoPi(2, 64-2); + for (i=0; i<64; i++) { + s24.a[i] <== in[21*64+i]; + } + // r[4] = a[24]<<14|a[24]>>(64-14) + component s4 = stepRhoPi(14, 64-14); + for (i=0; i<64; i++) { + s4.a[i] <== in[24*64+i]; + } + // r[15] = a[4]<<27|a[4]>>(64-27) + component s15 = stepRhoPi(27, 64-27); + for (i=0; i<64; i++) { + s15.a[i] <== in[4*64+i]; + } + // r[23] = a[15]<<41|a[15]>>(64-41) + component s23 = stepRhoPi(41, 64-41); + for (i=0; i<64; i++) { + s23.a[i] <== in[15*64+i]; + } + // r[19] = a[23]<<56|a[23]>>(64-56) + component s19 = stepRhoPi(56, 64-56); + for (i=0; i<64; i++) { + s19.a[i] <== in[23*64+i]; + } + // r[13] = a[19]<<8|a[19]>>(64-8) + component s13 = stepRhoPi(8, 64-8); + for (i=0; i<64; i++) { + s13.a[i] <== in[19*64+i]; + } + // r[12] = a[13]<<25|a[13]>>(64-25) + component s12 = stepRhoPi(25, 64-25); + for (i=0; i<64; i++) { + s12.a[i] <== in[13*64+i]; + } + // r[2] = a[12]<<43|a[12]>>(64-43) + component s2 = stepRhoPi(43, 64-43); + for (i=0; i<64; i++) { + s2.a[i] <== in[12*64+i]; + } + // r[20] = a[2]<<62|a[2]>>(64-62) + component s20 = stepRhoPi(62, 64-62); + for (i=0; i<64; i++) { + s20.a[i] <== in[2*64+i]; + } + // r[14] = a[20]<<18|a[20]>>(64-18) + component s14 = stepRhoPi(18, 64-18); + for (i=0; i<64; i++) { + s14.a[i] <== in[20*64+i]; + } + // r[22] = a[14]<<39|a[14]>>(64-39) + component s22 = stepRhoPi(39, 64-39); + for (i=0; i<64; i++) { + s22.a[i] <== in[14*64+i]; + } + // r[9] = a[22]<<61|a[22]>>(64-61) + component s9 = stepRhoPi(61, 64-61); + for (i=0; i<64; i++) { + s9.a[i] <== in[22*64+i]; + } + // r[6] = a[9]<<20|a[9]>>(64-20) + component s6 = stepRhoPi(20, 64-20); + for (i=0; i<64; i++) { + s6.a[i] <== in[9*64+i]; + } + // r[1] = a[6]<<44|a[6]>>(64-44) + component s1 = stepRhoPi(44, 64-44); + for (i=0; i<64; i++) { + s1.a[i] <== in[6*64+i]; + } + + for (i=0; i<64; i++) { + out[i] <== in[i]; + out[10*64+i] <== s10.out[i]; + out[7*64+i] <== s7.out[i]; + out[11*64+i] <== s11.out[i]; + out[17*64+i] <== s17.out[i]; + out[18*64+i] <== s18.out[i]; + out[3*64+i] <== s3.out[i]; + out[5*64+i] <== s5.out[i]; + out[16*64+i] <== s16.out[i]; + out[8*64+i] <== s8.out[i]; + out[21*64+i] <== s21.out[i]; + out[24*64+i] <== s24.out[i]; + out[4*64+i] <== s4.out[i]; + out[15*64+i] <== s15.out[i]; + out[23*64+i] <== s23.out[i]; + out[19*64+i] <== s19.out[i]; + out[13*64+i] <== s13.out[i]; + out[12*64+i] <== s12.out[i]; + out[2*64+i] <== s2.out[i]; + out[20*64+i] <== s20.out[i]; + out[14*64+i] <== s14.out[i]; + out[22*64+i] <== s22.out[i]; + out[9*64+i] <== s9.out[i]; + out[6*64+i] <== s6.out[i]; + out[1*64+i] <== s1.out[i]; + } +} + + +// Chi + +template stepChi() { + // out = a ^ (^b) & c + signal input a[64]; + signal input b[64]; + signal input c[64]; + signal output out[64]; + var i; + + // ^b + component bXor = XorArraySingle(64); + for (i=0; i<64; i++) { + bXor.a[i] <== b[i]; + } + // (^b)&c + component bc = AndArray(64); + for (i=0; i<64; i++) { + bc.a[i] <== bXor.out[i]; + bc.b[i] <== c[i]; + } + // a^(^b)&c + component abc = XorArray(64); + for (i=0; i<64; i++) { + abc.a[i] <== a[i]; + abc.b[i] <== bc.out[i]; + } + for (i=0; i<64; i++) { + out[i] <== abc.out[i]; + } +} + +template Chi() { + signal input in[25*64]; + signal output out[25*64]; + + var i; + + component r0 = stepChi(); + for (i=0; i<64; i++) { + r0.a[i] <== in[i]; + r0.b[i] <== in[1*64+i]; + r0.c[i] <== in[2*64+i]; + } + component r1 = stepChi(); + for (i=0; i<64; i++) { + r1.a[i] <== in[1*64+i]; + r1.b[i] <== in[2*64+i]; + r1.c[i] <== in[3*64+i]; + } + component r2 = stepChi(); + for (i=0; i<64; i++) { + r2.a[i] <== in[2*64+i]; + r2.b[i] <== in[3*64+i]; + r2.c[i] <== in[4*64+i]; + } + component r3 = stepChi(); + for (i=0; i<64; i++) { + r3.a[i] <== in[3*64+i]; + r3.b[i] <== in[4*64+i]; + r3.c[i] <== in[0*64+i]; + } + component r4 = stepChi(); + for (i=0; i<64; i++) { + r4.a[i] <== in[4*64+i]; + r4.b[i] <== in[i]; + r4.c[i] <== in[1*64+i]; + } + + component r5 = stepChi(); + for (i=0; i<64; i++) { + r5.a[i] <== in[5*64+i]; + r5.b[i] <== in[6*64+i]; + r5.c[i] <== in[7*64+i]; + } + component r6 = stepChi(); + for (i=0; i<64; i++) { + r6.a[i] <== in[6*64+i]; + r6.b[i] <== in[7*64+i]; + r6.c[i] <== in[8*64+i]; + } + component r7 = stepChi(); + for (i=0; i<64; i++) { + r7.a[i] <== in[7*64+i]; + r7.b[i] <== in[8*64+i]; + r7.c[i] <== in[9*64+i]; + } + component r8 = stepChi(); + for (i=0; i<64; i++) { + r8.a[i] <== in[8*64+i]; + r8.b[i] <== in[9*64+i]; + r8.c[i] <== in[5*64+i]; + } + component r9 = stepChi(); + for (i=0; i<64; i++) { + r9.a[i] <== in[9*64+i]; + r9.b[i] <== in[5*64+i]; + r9.c[i] <== in[6*64+i]; + } + + component r10 = stepChi(); + for (i=0; i<64; i++) { + r10.a[i] <== in[10*64+i]; + r10.b[i] <== in[11*64+i]; + r10.c[i] <== in[12*64+i]; + } + component r11 = stepChi(); + for (i=0; i<64; i++) { + r11.a[i] <== in[11*64+i]; + r11.b[i] <== in[12*64+i]; + r11.c[i] <== in[13*64+i]; + } + component r12 = stepChi(); + for (i=0; i<64; i++) { + r12.a[i] <== in[12*64+i]; + r12.b[i] <== in[13*64+i]; + r12.c[i] <== in[14*64+i]; + } + component r13 = stepChi(); + for (i=0; i<64; i++) { + r13.a[i] <== in[13*64+i]; + r13.b[i] <== in[14*64+i]; + r13.c[i] <== in[10*64+i]; + } + component r14 = stepChi(); + for (i=0; i<64; i++) { + r14.a[i] <== in[14*64+i]; + r14.b[i] <== in[10*64+i]; + r14.c[i] <== in[11*64+i]; + } + + component r15 = stepChi(); + for (i=0; i<64; i++) { + r15.a[i] <== in[15*64+i]; + r15.b[i] <== in[16*64+i]; + r15.c[i] <== in[17*64+i]; + } + component r16 = stepChi(); + for (i=0; i<64; i++) { + r16.a[i] <== in[16*64+i]; + r16.b[i] <== in[17*64+i]; + r16.c[i] <== in[18*64+i]; + } + component r17 = stepChi(); + for (i=0; i<64; i++) { + r17.a[i] <== in[17*64+i]; + r17.b[i] <== in[18*64+i]; + r17.c[i] <== in[19*64+i]; + } + component r18 = stepChi(); + for (i=0; i<64; i++) { + r18.a[i] <== in[18*64+i]; + r18.b[i] <== in[19*64+i]; + r18.c[i] <== in[15*64+i]; + } + component r19 = stepChi(); + for (i=0; i<64; i++) { + r19.a[i] <== in[19*64+i]; + r19.b[i] <== in[15*64+i]; + r19.c[i] <== in[16*64+i]; + } + + component r20 = stepChi(); + for (i=0; i<64; i++) { + r20.a[i] <== in[20*64+i]; + r20.b[i] <== in[21*64+i]; + r20.c[i] <== in[22*64+i]; + } + component r21 = stepChi(); + for (i=0; i<64; i++) { + r21.a[i] <== in[21*64+i]; + r21.b[i] <== in[22*64+i]; + r21.c[i] <== in[23*64+i]; + } + component r22 = stepChi(); + for (i=0; i<64; i++) { + r22.a[i] <== in[22*64+i]; + r22.b[i] <== in[23*64+i]; + r22.c[i] <== in[24*64+i]; + } + component r23 = stepChi(); + for (i=0; i<64; i++) { + r23.a[i] <== in[23*64+i]; + r23.b[i] <== in[24*64+i]; + r23.c[i] <== in[20*64+i]; + } + component r24 = stepChi(); + for (i=0; i<64; i++) { + r24.a[i] <== in[24*64+i]; + r24.b[i] <== in[20*64+i]; + r24.c[i] <== in[21*64+i]; + } + + for (i=0; i<64; i++) { + out[i] <== r0.out[i]; + out[1*64+i] <== r1.out[i]; + out[2*64+i] <== r2.out[i]; + out[3*64+i] <== r3.out[i]; + out[4*64+i] <== r4.out[i]; + + out[5*64+i] <== r5.out[i]; + out[6*64+i] <== r6.out[i]; + out[7*64+i] <== r7.out[i]; + out[8*64+i] <== r8.out[i]; + out[9*64+i] <== r9.out[i]; + + out[10*64+i] <== r10.out[i]; + out[11*64+i] <== r11.out[i]; + out[12*64+i] <== r12.out[i]; + out[13*64+i] <== r13.out[i]; + out[14*64+i] <== r14.out[i]; + + out[15*64+i] <== r15.out[i]; + out[16*64+i] <== r16.out[i]; + out[17*64+i] <== r17.out[i]; + out[18*64+i] <== r18.out[i]; + out[19*64+i] <== r19.out[i]; + + out[20*64+i] <== r20.out[i]; + out[21*64+i] <== r21.out[i]; + out[22*64+i] <== r22.out[i]; + out[23*64+i] <== r23.out[i]; + out[24*64+i] <== r24.out[i]; + } +} + +// Iota + +template RC(r) { + signal output out[64]; + var rc[24] = [ + 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, + 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, + 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 + ]; + for (var i=0; i<64; i++) { + out[i] <== (rc[r] >> i) & 1; + } +} + +template Iota(r) { + signal input in[25*64]; + signal output out[25*64]; + var i; + + component rc = RC(r); + + component iota = XorArray(64); + for (var i=0; i<64; i++) { + iota.a[i] <== in[i]; + iota.b[i] <== rc.out[i]; + } + for (i=0; i<64; i++) { + out[i] <== iota.out[i]; + } + for (i=64; i<25*64; i++) { + out[i] <== in[i]; + } +} + diff --git a/circuits/rhopi.circom b/circuits/rhopi.circom deleted file mode 100644 index 17035c8..0000000 --- a/circuits/rhopi.circom +++ /dev/null @@ -1,182 +0,0 @@ -pragma circom 2.0.0; - -include "./utils.circom"; - -template stepRhoPi(shl, shr) { - // out = a<>shr - signal input a[64]; - signal output out[64]; - var i; - - component aux0 = ShR(64, shr); - for (i=0; i<64; i++) { - aux0.in[i] <== a[i]; - } - component aux1 = ShL(64, shl); - for (i=0; i<64; i++) { - aux1.in[i] <== a[i]; - } - component aux2 = OrArray(64); - for (i=0; i<64; i++) { - aux2.a[i] <== aux0.out[i]; - aux2.b[i] <== aux1.out[i]; - } - for (i=0; i<64; i++) { - out[i] <== aux2.out[i]; - } -} -template RhoPi() { - signal input in[25*64]; - signal output out[25*64]; - - var i; - - // r[10] = a[1]<<1|a[1]>>(64-1) - component s10 = stepRhoPi(1, 64-1); - for (i=0; i<64; i++) { - s10.a[i] <== in[1*64+i]; - } - // r[7] = a[10]<<3|a[10]>>(64-3) - component s7 = stepRhoPi(3, 64-3); - for (i=0; i<64; i++) { - s7.a[i] <== in[10*64+i]; - } - // r[11] = a[7]<<6|a[7]>>(64-6) - component s11 = stepRhoPi(6, 64-6); - for (i=0; i<64; i++) { - s11.a[i] <== in[7*64+i]; - } - // r[17] = a[11]<<10|a[11]>>(64-10) - component s17 = stepRhoPi(10, 64-10); - for (i=0; i<64; i++) { - s17.a[i] <== in[11*64+i]; - } - // r[18] = a[17]<<15|a[17]>>(64-15) - component s18 = stepRhoPi(15, 64-15); - for (i=0; i<64; i++) { - s18.a[i] <== in[17*64+i]; - } - // r[3] = a[18]<<21|a[18]>>(64-21) - component s3 = stepRhoPi(21, 64-21); - for (i=0; i<64; i++) { - s3.a[i] <== in[18*64+i]; - } - // r[5] = a[3]<<28|a[3]>>(64-28) - component s5 = stepRhoPi(28, 64-28); - for (i=0; i<64; i++) { - s5.a[i] <== in[3*64+i]; - } - // r[16] = a[5]<<36|a[5]>>(64-36) - component s16 = stepRhoPi(36, 64-36); - for (i=0; i<64; i++) { - s16.a[i] <== in[5*64+i]; - } - // r[8] = a[16]<<45|a[16]>>(64-45) - component s8 = stepRhoPi(45, 64-45); - for (i=0; i<64; i++) { - s8.a[i] <== in[16*64+i]; - } - // r[21] = a[8]<<55|a[8]>>(64-55) - component s21 = stepRhoPi(55, 64-55); - for (i=0; i<64; i++) { - s21.a[i] <== in[8*64+i]; - } - // r[24] = a[21]<<2|a[21]>>(64-2) - component s24 = stepRhoPi(2, 64-2); - for (i=0; i<64; i++) { - s24.a[i] <== in[21*64+i]; - } - // r[4] = a[24]<<14|a[24]>>(64-14) - component s4 = stepRhoPi(14, 64-14); - for (i=0; i<64; i++) { - s4.a[i] <== in[24*64+i]; - } - // r[15] = a[4]<<27|a[4]>>(64-27) - component s15 = stepRhoPi(27, 64-27); - for (i=0; i<64; i++) { - s15.a[i] <== in[4*64+i]; - } - // r[23] = a[15]<<41|a[15]>>(64-41) - component s23 = stepRhoPi(41, 64-41); - for (i=0; i<64; i++) { - s23.a[i] <== in[15*64+i]; - } - // r[19] = a[23]<<56|a[23]>>(64-56) - component s19 = stepRhoPi(56, 64-56); - for (i=0; i<64; i++) { - s19.a[i] <== in[23*64+i]; - } - // r[13] = a[19]<<8|a[19]>>(64-8) - component s13 = stepRhoPi(8, 64-8); - for (i=0; i<64; i++) { - s13.a[i] <== in[19*64+i]; - } - // r[12] = a[13]<<25|a[13]>>(64-25) - component s12 = stepRhoPi(25, 64-25); - for (i=0; i<64; i++) { - s12.a[i] <== in[13*64+i]; - } - // r[2] = a[12]<<43|a[12]>>(64-43) - component s2 = stepRhoPi(43, 64-43); - for (i=0; i<64; i++) { - s2.a[i] <== in[12*64+i]; - } - // r[20] = a[2]<<62|a[2]>>(64-62) - component s20 = stepRhoPi(62, 64-62); - for (i=0; i<64; i++) { - s20.a[i] <== in[2*64+i]; - } - // r[14] = a[20]<<18|a[20]>>(64-18) - component s14 = stepRhoPi(18, 64-18); - for (i=0; i<64; i++) { - s14.a[i] <== in[20*64+i]; - } - // r[22] = a[14]<<39|a[14]>>(64-39) - component s22 = stepRhoPi(39, 64-39); - for (i=0; i<64; i++) { - s22.a[i] <== in[14*64+i]; - } - // r[9] = a[22]<<61|a[22]>>(64-61) - component s9 = stepRhoPi(61, 64-61); - for (i=0; i<64; i++) { - s9.a[i] <== in[22*64+i]; - } - // r[6] = a[9]<<20|a[9]>>(64-20) - component s6 = stepRhoPi(20, 64-20); - for (i=0; i<64; i++) { - s6.a[i] <== in[9*64+i]; - } - // r[1] = a[6]<<44|a[6]>>(64-44) - component s1 = stepRhoPi(44, 64-44); - for (i=0; i<64; i++) { - s1.a[i] <== in[6*64+i]; - } - - for (i=0; i<64; i++) { - out[i] <== in[i]; - out[10*64+i] <== s10.out[i]; - out[7*64+i] <== s7.out[i]; - out[11*64+i] <== s11.out[i]; - out[17*64+i] <== s17.out[i]; - out[18*64+i] <== s18.out[i]; - out[3*64+i] <== s3.out[i]; - out[5*64+i] <== s5.out[i]; - out[16*64+i] <== s16.out[i]; - out[8*64+i] <== s8.out[i]; - out[21*64+i] <== s21.out[i]; - out[24*64+i] <== s24.out[i]; - out[4*64+i] <== s4.out[i]; - out[15*64+i] <== s15.out[i]; - out[23*64+i] <== s23.out[i]; - out[19*64+i] <== s19.out[i]; - out[13*64+i] <== s13.out[i]; - out[12*64+i] <== s12.out[i]; - out[2*64+i] <== s2.out[i]; - out[20*64+i] <== s20.out[i]; - out[14*64+i] <== s14.out[i]; - out[22*64+i] <== s22.out[i]; - out[9*64+i] <== s9.out[i]; - out[6*64+i] <== s6.out[i]; - out[1*64+i] <== s1.out[i]; - } -} diff --git a/circuits/theta.circom b/circuits/theta.circom deleted file mode 100644 index aac2fd8..0000000 --- a/circuits/theta.circom +++ /dev/null @@ -1,346 +0,0 @@ -pragma circom 2.0.0; - -include "./utils.circom"; - - -template D(n, shl, shr) { - // d = b ^ (a<>shr) - signal input a[n]; - signal input b[n]; - signal output out[n]; - var i; - - component aux0 = ShR(64, shr); - for (i=0; i<64; i++) { - aux0.in[i] <== a[i]; - } - component aux1 = ShL(64, shl); - for (i=0; i<64; i++) { - aux1.in[i] <== a[i]; - } - component aux2 = OrArray(64); - for (i=0; i<64; i++) { - aux2.a[i] <== aux0.out[i]; - aux2.b[i] <== aux1.out[i]; - } - component aux3 = XorArray(64); - for (i=0; i<64; i++) { - aux3.a[i] <== b[i]; - aux3.b[i] <== aux2.out[i]; - } - for (i=0; i<64; i++) { - out[i] <== aux3.out[i]; - } -} - -template Theta() { - signal input in[25*64]; - signal output out[25*64]; - - var i; - - component c0 = Xor5(64); - for (i=0; i<64; i++) { - c0.a[i] <== in[i]; - c0.b[i] <== in[5*64+i]; - c0.c[i] <== in[10*64+i]; - c0.d[i] <== in[15*64+i]; - c0.e[i] <== in[20*64+i]; - } - - component c1 = Xor5(64); - for (i=0; i<64; i++) { - c1.a[i] <== in[1*64+i]; - c1.b[i] <== in[6*64+i]; - c1.c[i] <== in[11*64+i]; - c1.d[i] <== in[16*64+i]; - c1.e[i] <== in[21*64+i]; - } - - component c2 = Xor5(64); - for (i=0; i<64; i++) { - c2.a[i] <== in[2*64+i]; - c2.b[i] <== in[7*64+i]; - c2.c[i] <== in[12*64+i]; - c2.d[i] <== in[17*64+i]; - c2.e[i] <== in[22*64+i]; - } - - component c3 = Xor5(64); - for (i=0; i<64; i++) { - c3.a[i] <== in[3*64+i]; - c3.b[i] <== in[8*64+i]; - c3.c[i] <== in[13*64+i]; - c3.d[i] <== in[18*64+i]; - c3.e[i] <== in[23*64+i]; - } - - component c4 = Xor5(64); - for (i=0; i<64; i++) { - c4.a[i] <== in[4*64+i]; - c4.b[i] <== in[9*64+i]; - c4.c[i] <== in[14*64+i]; - c4.d[i] <== in[19*64+i]; - c4.e[i] <== in[24*64+i]; - } - - // d = c4 ^ (c1<<1 | c1>>(64-1)) - component d0 = D(64, 1, 64-1); - for (i=0; i<64; i++) { - d0.a[i] <== c1.out[i]; - d0.b[i] <== c4.out[i]; - } - // r[0] = a[0] ^ d - component r0 = XorArray(64); - for (i=0; i<64; i++) { - r0.a[i] <== in[i]; - r0.b[i] <== d0.out[i]; - } - for (i=0; i<64; i++) { - out[i] <== r0.out[i]; - } - // r[5] = a[5] ^ d - component r5 = XorArray(64); - for (i=0; i<64; i++) { - r5.a[i] <== in[5*64+i]; - r5.b[i] <== d0.out[i]; - } - for (i=0; i<64; i++) { - out[5*64+i] <== r5.out[i]; - } - // r[10] = a[10] ^ d - component r10 = XorArray(64); - for (i=0; i<64; i++) { - r10.a[i] <== in[10*64+i]; - r10.b[i] <== d0.out[i]; - } - for (i=0; i<64; i++) { - out[10*64+i] <== r10.out[i]; - } - // r[15] = a[15] ^ d - component r15 = XorArray(64); - for (i=0; i<64; i++) { - r15.a[i] <== in[15*64+i]; - r15.b[i] <== d0.out[i]; - } - for (i=0; i<64; i++) { - out[15*64+i] <== r15.out[i]; - } - // r[20] = a[20] ^ d - component r20 = XorArray(64); - for (i=0; i<64; i++) { - r20.a[i] <== in[20*64+i]; - r20.b[i] <== d0.out[i]; - } - for (i=0; i<64; i++) { - out[20*64+i] <== r20.out[i]; - } - - // d = c0 ^ (c2<<1 | c2>>(64-1)) - component d1 = D(64, 1, 64-1); - for (i=0; i<64; i++) { - d1.a[i] <== c2.out[i]; - d1.b[i] <== c0.out[i]; - } - // r[1] = a[1] ^ d - component r1 = XorArray(64); - for (i=0; i<64; i++) { - r1.a[i] <== in[1*64+i]; - r1.b[i] <== d1.out[i]; - } - for (i=0; i<64; i++) { - out[1*64+i] <== r1.out[i]; - } - // r[6] = a[6] ^ d - component r6 = XorArray(64); - for (i=0; i<64; i++) { - r6.a[i] <== in[6*64+i]; - r6.b[i] <== d1.out[i]; - } - for (i=0; i<64; i++) { - out[6*64+i] <== r6.out[i]; - } - // r[11] = a[11] ^ d - component r11 = XorArray(64); - for (i=0; i<64; i++) { - r11.a[i] <== in[11*64+i]; - r11.b[i] <== d1.out[i]; - } - for (i=0; i<64; i++) { - out[11*64+i] <== r11.out[i]; - } - // r[16] = a[16] ^ d - component r16 = XorArray(64); - for (i=0; i<64; i++) { - r16.a[i] <== in[16*64+i]; - r16.b[i] <== d1.out[i]; - } - for (i=0; i<64; i++) { - out[16*64+i] <== r16.out[i]; - } - // r[21] = a[21] ^ d - component r21 = XorArray(64); - for (i=0; i<64; i++) { - r21.a[i] <== in[21*64+i]; - r21.b[i] <== d1.out[i]; - } - for (i=0; i<64; i++) { - out[21*64+i] <== r21.out[i]; - } - - // d = c1 ^ (c3<<1 | c3>>(64-1)) - component d2 = D(64, 1, 64-1); - for (i=0; i<64; i++) { - d2.a[i] <== c3.out[i]; - d2.b[i] <== c1.out[i]; - } - // r[2] = a[2] ^ d - component r2 = XorArray(64); - for (i=0; i<64; i++) { - r2.a[i] <== in[2*64+i]; - r2.b[i] <== d2.out[i]; - } - for (i=0; i<64; i++) { - out[2*64+i] <== r2.out[i]; - } - // r[7] = a[7] ^ d - component r7 = XorArray(64); - for (i=0; i<64; i++) { - r7.a[i] <== in[7*64+i]; - r7.b[i] <== d2.out[i]; - } - for (i=0; i<64; i++) { - out[7*64+i] <== r7.out[i]; - } - // r[12] = a[12] ^ d - component r12 = XorArray(64); - for (i=0; i<64; i++) { - r12.a[i] <== in[12*64+i]; - r12.b[i] <== d2.out[i]; - } - for (i=0; i<64; i++) { - out[12*64+i] <== r12.out[i]; - } - // r[17] = a[17] ^ d - component r17 = XorArray(64); - for (i=0; i<64; i++) { - r17.a[i] <== in[17*64+i]; - r17.b[i] <== d2.out[i]; - } - for (i=0; i<64; i++) { - out[17*64+i] <== r17.out[i]; - } - // r[22] = a[22] ^ d - component r22 = XorArray(64); - for (i=0; i<64; i++) { - r22.a[i] <== in[22*64+i]; - r22.b[i] <== d2.out[i]; - } - for (i=0; i<64; i++) { - out[22*64+i] <== r22.out[i]; - } - - // d = c2 ^ (c4<<1 | c4>>(64-1)) - component d3 = D(64, 1, 64-1); - for (i=0; i<64; i++) { - d3.a[i] <== c4.out[i]; - d3.b[i] <== c2.out[i]; - } - // r[3] = a[3] ^ d - component r3 = XorArray(64); - for (i=0; i<64; i++) { - r3.a[i] <== in[3*64+i]; - r3.b[i] <== d3.out[i]; - } - for (i=0; i<64; i++) { - out[3*64+i] <== r3.out[i]; - } - // r[8] = a[8] ^ d - component r8 = XorArray(64); - for (i=0; i<64; i++) { - r8.a[i] <== in[8*64+i]; - r8.b[i] <== d3.out[i]; - } - for (i=0; i<64; i++) { - out[8*64+i] <== r8.out[i]; - } - // r[13] = a[13] ^ d - component r13 = XorArray(64); - for (i=0; i<64; i++) { - r13.a[i] <== in[13*64+i]; - r13.b[i] <== d3.out[i]; - } - for (i=0; i<64; i++) { - out[13*64+i] <== r13.out[i]; - } - // r[18] = a[18] ^ d - component r18 = XorArray(64); - for (i=0; i<64; i++) { - r18.a[i] <== in[18*64+i]; - r18.b[i] <== d3.out[i]; - } - for (i=0; i<64; i++) { - out[18*64+i] <== r18.out[i]; - } - // r[23] = a[23] ^ d - component r23 = XorArray(64); - for (i=0; i<64; i++) { - r23.a[i] <== in[23*64+i]; - r23.b[i] <== d3.out[i]; - } - for (i=0; i<64; i++) { - out[23*64+i] <== r23.out[i]; - } - - // d = c3 ^ (c0<<1 | c0>>(64-1)) - component d4 = D(64, 1, 64-1); - for (i=0; i<64; i++) { - d4.a[i] <== c0.out[i]; - d4.b[i] <== c3.out[i]; - } - // r[4] = a[4] ^ d - component r4 = XorArray(64); - for (i=0; i<64; i++) { - r4.a[i] <== in[4*64+i]; - r4.b[i] <== d4.out[i]; - } - for (i=0; i<64; i++) { - out[4*64+i] <== r4.out[i]; - } - // r[9] = a[9] ^ d - component r9 = XorArray(64); - for (i=0; i<64; i++) { - r9.a[i] <== in[9*64+i]; - r9.b[i] <== d4.out[i]; - } - for (i=0; i<64; i++) { - out[9*64+i] <== r9.out[i]; - } - // r[14] = a[14] ^ d - component r14 = XorArray(64); - for (i=0; i<64; i++) { - r14.a[i] <== in[14*64+i]; - r14.b[i] <== d4.out[i]; - } - for (i=0; i<64; i++) { - out[14*64+i] <== r14.out[i]; - } - // r[19] = a[19] ^ d - component r19 = XorArray(64); - for (i=0; i<64; i++) { - r19.a[i] <== in[19*64+i]; - r19.b[i] <== d4.out[i]; - } - for (i=0; i<64; i++) { - out[19*64+i] <== r19.out[i]; - } - // r[24] = a[24] ^ d - component r24 = XorArray(64); - for (i=0; i<64; i++) { - r24.a[i] <== in[24*64+i]; - r24.b[i] <== d4.out[i]; - } - for (i=0; i<64; i++) { - out[24*64+i] <== r24.out[i]; - } -} diff --git a/go-keccak256-bits-impl/stepmappings.go b/go-keccak256-bits-impl/permutations.go similarity index 100% rename from go-keccak256-bits-impl/stepmappings.go rename to go-keccak256-bits-impl/permutations.go diff --git a/go-keccak256-bits-impl/stepmappingsRef.go b/go-keccak256-bits-impl/permutationsRef.go similarity index 100% rename from go-keccak256-bits-impl/stepmappingsRef.go rename to go-keccak256-bits-impl/permutationsRef.go diff --git a/go-keccak256-bits-impl/stepmappings_test.go b/go-keccak256-bits-impl/permutations_test.go similarity index 98% rename from go-keccak256-bits-impl/stepmappings_test.go rename to go-keccak256-bits-impl/permutations_test.go index 6548773..ca4b067 100644 --- a/go-keccak256-bits-impl/stepmappings_test.go +++ b/go-keccak256-bits-impl/permutations_test.go @@ -56,7 +56,7 @@ func TestTheta2(t *testing.T) { qt.Assert(t, bitsToU64Array(s[:]), qt.DeepEquals, sU64[:]) qt.Assert(t, bitsToU64Array(s[:]), qt.DeepEquals, []uint64{3749081831850030700, 1297317621190464868, 10017560217643747862, 7854780639862409219, 13836147678645575967, 3749090635727681271, 1297915755455157604, 12323429615135705749, 7855062122598582297, 16141814766035214620, 3749090628446369381, 1297071330560683876, 10017586606556924438, 7854780639837253643, 13835971756788491039, 3749090634251287159, 1297070162329376100, 9369068259580659222, 7854780645071013913, 14484490034407743775, 8360757404916954740, 1801500877105239396, 10017570663003408994, 3243123208712177690, 14628605291203076459}) - fmt.Println(bitsToU64(s[1*64:2*64]), s[1*64:2*64]) + // fmt.Println(bitsToU64(s[1*64:2*64]), s[1*64:2*64]) // compute again theta on the current state s = theta(s) diff --git a/test/circuits/absorb_test.circom b/test/circuits/absorb_test.circom index 7b7ca3d..fcc734e 100644 --- a/test/circuits/absorb_test.circom +++ b/test/circuits/absorb_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = Absorb(); diff --git a/test/circuits/chi_test.circom b/test/circuits/chi_test.circom index bd84539..d7e8620 100644 --- a/test/circuits/chi_test.circom +++ b/test/circuits/chi_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/chi.circom"; +include "../../circuits/permutations.circom"; component main = Chi(); diff --git a/test/circuits/final_test.circom b/test/circuits/final_test.circom index 1820fce..89e1adb 100644 --- a/test/circuits/final_test.circom +++ b/test/circuits/final_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = Final(32*8); diff --git a/test/circuits/iota10_test.circom b/test/circuits/iota10_test.circom index 8b4f5e2..9f9f6fc 100644 --- a/test/circuits/iota10_test.circom +++ b/test/circuits/iota10_test.circom @@ -1,6 +1,6 @@ pragma circom 2.0.0; -include "../../circuits/iota.circom"; +include "../../circuits/permutations.circom"; component main = Iota(10); diff --git a/test/circuits/iota3_test.circom b/test/circuits/iota3_test.circom index 1a747d2..5b642d3 100644 --- a/test/circuits/iota3_test.circom +++ b/test/circuits/iota3_test.circom @@ -1,6 +1,6 @@ pragma circom 2.0.0; -include "../../circuits/iota.circom"; +include "../../circuits/permutations.circom"; component main = Iota(3); diff --git a/test/circuits/keccak256_test.circom b/test/circuits/keccak256_test.circom index 4433b5f..789e566 100644 --- a/test/circuits/keccak256_test.circom +++ b/test/circuits/keccak256_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = Keccak(32*8); diff --git a/test/circuits/keccakfRound0_test.circom b/test/circuits/keccakfRound0_test.circom index af298fd..8e24633 100644 --- a/test/circuits/keccakfRound0_test.circom +++ b/test/circuits/keccakfRound0_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = KeccakfRound(0); diff --git a/test/circuits/keccakfRound20_test.circom b/test/circuits/keccakfRound20_test.circom index 674de0b..ea86c55 100644 --- a/test/circuits/keccakfRound20_test.circom +++ b/test/circuits/keccakfRound20_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = KeccakfRound(20); diff --git a/test/circuits/keccakf_test.circom b/test/circuits/keccakf_test.circom index f3ff679..e481144 100644 --- a/test/circuits/keccakf_test.circom +++ b/test/circuits/keccakf_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = Keccakf(); diff --git a/test/circuits/pad_test.circom b/test/circuits/pad_test.circom index 25d1644..135d97d 100644 --- a/test/circuits/pad_test.circom +++ b/test/circuits/pad_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = Pad(32*8); diff --git a/test/circuits/rhopi_test.circom b/test/circuits/rhopi_test.circom index 01d6947..200eee5 100644 --- a/test/circuits/rhopi_test.circom +++ b/test/circuits/rhopi_test.circom @@ -1,6 +1,6 @@ pragma circom 2.0.0; -include "../../circuits/rhopi.circom"; +include "../../circuits/permutations.circom"; component main = RhoPi(); diff --git a/test/circuits/squeeze_test.circom b/test/circuits/squeeze_test.circom index 2c0f35c..a7a293e 100644 --- a/test/circuits/squeeze_test.circom +++ b/test/circuits/squeeze_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/keccak256.circom"; +include "../../circuits/keccak.circom"; component main = Squeeze(32*8); diff --git a/test/circuits/theta_test.circom b/test/circuits/theta_test.circom index b3bccbe..dcbecd5 100644 --- a/test/circuits/theta_test.circom +++ b/test/circuits/theta_test.circom @@ -1,5 +1,5 @@ pragma circom 2.0.0; -include "../../circuits/theta.circom"; +include "../../circuits/permutations.circom"; component main = Theta(); diff --git a/test/keccak-intermediate.js b/test/keccak-intermediate.js new file mode 100644 index 0000000..e57f2c7 --- /dev/null +++ b/test/keccak-intermediate.js @@ -0,0 +1,283 @@ +const path = require("path"); + +const chai = require("chai"); +const assert = chai.assert; + +const wasm_tester = require("circom_tester").wasm; +const c_tester = require("circom_tester").c; + +const utils = require("./utils"); + +describe("Keccak-Pad test", function () { + this.timeout(100000); + + it ("Pad (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "pad_test.circom")); + + const input = + [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]; + const expectedOut = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128]; + + const stateIn = utils.bytesToBits(input); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(136*8)); + const stateOutBytes = utils.bitsToBytes(stateOut); + // console.log(stateOutBytes, expectedOut); + assert.deepEqual(stateOutBytes, expectedOut); + }); +}); + +describe("absorb test", function () { + this.timeout(100000); + + let cir; + before(async () => { + // const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom")); + cir = await c_tester(path.join(__dirname, "circuits", "absorb_test.circom")); + await cir.loadConstraints(); + console.log("n_constraints", cir.constraints.length); + }); + + it ("absorb 1 (testvector generated from go)", async () => { + const s = utils.strsToBigInts(["0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", + "19", "20", "21", "22", "23", "24"]); + + const block = utils.strsToBigInts(["0", "1", "2", "3", "4", "5", "6", + "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", + "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", + "28","29", "30", "31", "1", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0","0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "128"]); + + const expectedOut = utils.strsToBigInts(["8342348566319207042", + "319359607942176202", "14410076088654599075", + "15666111399434436772", "9558421567405313402", + "3396178318116504023", "794353847439963108", + "12717011319735989377", "3503398863218919239", + "5517201702366862678", "15999361614129160496", + "1325524015888689985", "11971708408118944333", + "14874486179441062217", "12554876384974234666", + "11129975558302206043", "11257826431949606534", + "2740710607956478714", "15000019752453010167", + "15593606854132419294", + "2598425978562809333","8872504799797239246", "1212062965004664308", + "5443427421087086722", "10946808592826700411"]); + + const sIn = utils.u64ArrayToBits(s); + const blockIn = utils.bytesToBits(block); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "s": sIn, "block": blockIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + + it ("absorb 2 (testvector generated from go)", async () => { + const s = utils.strsToBigInts(["8342348566319207042", + "319359607942176202", "14410076088654599075", + "15666111399434436772", "9558421567405313402", + "3396178318116504023", "794353847439963108", + "12717011319735989377", "3503398863218919239", + "5517201702366862678", "15999361614129160496", + "1325524015888689985", "11971708408118944333", + "14874486179441062217", "12554876384974234666", + "11129975558302206043", "11257826431949606534", + "2740710607956478714", "15000019752453010167", + "15593606854132419294", + "2598425978562809333","8872504799797239246", "1212062965004664308", + "5443427421087086722", "10946808592826700411"]); + + const block = utils.strsToBigInts(["0", "1", "2", "3", "4", "5", "6", + "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", + "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", + "28","29", "30", "31", "1", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0","0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "128"]); + + const expectedOut = utils.strsToBigInts(["8909243822027471379", + "1111840847970088140", "12093072708540612559", + "11255033638786021658", "2082116894939842214", + "12821085060245261575", "6901785969834988344", + "3182430130277914993", "2164708585929408975", + "14402143231999718904", "16231444410553803968", + "1850945423480060493", "12856855675247400303", + "1137248620532111171", "7389129221921446308", + "12932467982741614601", "1350606937385760406", + "10983682292859713641", "10305595434820307765", + "13958651111365489854", "17206620388135196198", + "4238113785249530092", "7230868147643218103", "603011106238724524", + "16480095441097880488"]); + + const sIn = utils.u64ArrayToBits(s); + const blockIn = utils.bytesToBits(block); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "s": sIn, "block": blockIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +}); + +describe("Keccak-Final test", function () { + this.timeout(100000); + + let cir; + before(async () => { + cir = await c_tester(path.join(__dirname, "circuits", "final_test.circom")); + await cir.loadConstraints(); + console.log("n_constraints", cir.constraints.length); + }); + + it ("Final 1 (testvector generated from go)", async () => { + const input = + [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]; + const expectedOut = utils.strsToBigInts(["16953415415620100490", + "7495738965189503699", "12723370805759944158", + "3295955328722933810", "12121371508560456016", + "174876831679863147", "15944933357501475584", + "7502339663607726274", "12048918224562833898", + "16715284461100269102", "15582559130083209842", + "1743886467337678829", "2424196198791253761", + "1116417308245482383", "10367365997906434042", + "1849801549382613906", "13294939539683415102", + "4478091053375708790", "2969967870313332958", + "14618962068930014237", "2721742233407503451", + "12003265593030191290", "8109318293656735684", + "6346795302983965746", "12210038122000333046"]); + + const inIn = utils.bytesToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": inIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + + it ("Final 2 (testvector generated from go)", async () => { + const input = utils.strsToBigInts(["254", "254", "254", "254", "254", + "254", "254", "254", "254", "254", "254", "254", "254", "254", + "254", "254", "254", "254", "254", "254", "254", "254", "254", + "254", "254", "254", "254", "254", "254", "254", "254", "254"]); + const expectedOut = utils.strsToBigInts(["16852464862333879129", + "9588646233186836430", "693207875935078627", "6545910230963382296", + "3599194178366828471", "13130606490077331384", + "10374798023615518933", "7285576075118720444", + "4097382401500492461", "3968685317688314807", + "3350659309646210303", "640023485234837464", "2550030127986774041", + "8948768022010378840", "10678227883444996205", + "1395278318096830339", "2744077813166753978", + "13362598477502046010", "14601579319881128511", + "4070707967569603186", "16833768365875755098", + "1486295134719870048", "9161068934282437999", + "8245604251371175619", "8421994351908003183"]); + + const inIn = utils.bytesToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": inIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +}); + +describe("Keccak-Squeeze test", function () { + this.timeout(100000); + + let cir; + before(async () => { + cir = await c_tester(path.join(__dirname, "circuits", "squeeze_test.circom")); + await cir.loadConstraints(); + console.log("n_constraints", cir.constraints.length); + }); + + it ("Squeeze 1 (testvector generated from go)", async () => { + const input = utils.strsToBigInts(["16852464862333879129", + "9588646233186836430", "693207875935078627", "6545910230963382296", + "3599194178366828471", "13130606490077331384", + "10374798023615518933", "7285576075118720444", + "4097382401500492461", "3968685317688314807", + "3350659309646210303", "640023485234837464", "2550030127986774041", + "8948768022010378840", "10678227883444996205", + "1395278318096830339", "2744077813166753978", + "13362598477502046010", "14601579319881128511", + "4070707967569603186", "16833768365875755098", + "1486295134719870048", "9161068934282437999", + "8245604251371175619", "8421994351908003183"]); + + const expectedOut = [89, 195, 41, 13, 129, 251, 223, 233, 206, 31, 253, + 61, 242, 182, 17, 133, 227, 8, 157, 240, 227, 196, 158, 9, 24, 232, + 42, 96, 172, 190, 215, 90]; + + const inIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.bytesToBits(expectedOut); + + const witness = await cir.calculateWitness({ "s": inIn }, true); + + const stateOut = witness.slice(1, 1+(32*8)); + const stateOutBytes = utils.bitsToBytes(stateOut); + // console.log(stateOutBytes, expectedOut); + assert.deepEqual(stateOutBytes, expectedOut); + }); + it ("Squeeze 2 (testvector generated from go)", async () => { + const input = utils.strsToBigInts(["16953415415620100490", + "7495738965189503699", "12723370805759944158", + "3295955328722933810", "12121371508560456016", + "174876831679863147", "15944933357501475584", + "7502339663607726274", "12048918224562833898", + "16715284461100269102", "15582559130083209842", + "1743886467337678829", "2424196198791253761", + "1116417308245482383", "10367365997906434042", + "1849801549382613906", "13294939539683415102", + "4478091053375708790", "2969967870313332958", + "14618962068930014237", "2721742233407503451", + "12003265593030191290", "8109318293656735684", + "6346795302983965746", "12210038122000333046"]); + + const expectedOut = [138, 225, 170, 89, 127, 161, 70, 235, 211, 170, + 44, 237, 223, 54, 6, 104, 222, 165, 229, 38, 86, 126, 146, 176, 50, + 24, 22, 164, 232, 149, 189, 45]; + + const inIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.bytesToBits(expectedOut); + + const witness = await cir.calculateWitness({ "s": inIn }, true); + + const stateOut = witness.slice(1, 1+(32*8)); + const stateOutBytes = utils.bitsToBytes(stateOut); + // console.log(stateOutBytes, expectedOut); + assert.deepEqual(stateOutBytes, expectedOut); + }); +}); diff --git a/test/keccak.js b/test/keccak.js new file mode 100644 index 0000000..61feaf0 --- /dev/null +++ b/test/keccak.js @@ -0,0 +1,111 @@ +const path = require("path"); + +const chai = require("chai"); +const assert = chai.assert; + +const c_tester = require("circom_tester").c; + +const utils = require("./utils"); +const keccak256 = require("keccak256"); + +describe("Keccak full hash test", function () { + this.timeout(100000); + + let cir; + before(async () => { + cir = await c_tester(path.join(__dirname, "circuits", "keccak256_test.circom")); + await cir.loadConstraints(); + console.log("n_constraints", cir.constraints.length); + }); + + it ("Keccak 1 (testvector generated from go)", async () => { + const input = [116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + const expectedOut = [37, 17, 98, 135, 161, 178, 88, 97, 125, 150, 143, + 65, 228, 211, 170, 133, 153, 9, 88, 212, 4, 212, 175, 238, 249, + 210, 214, 116, 170, 85, 45, 21]; + + const inIn = utils.bytesToBits(input); + + const witness = await cir.calculateWitness({ "in": inIn }, true); + + const stateOut = witness.slice(1, 1+(32*8)); + const stateOutBytes = utils.bitsToBytes(stateOut); + // console.log(stateOutBytes, expectedOut); + assert.deepEqual(stateOutBytes, expectedOut); + }); + it ("Keccak 2 (testvector generated from go)", async () => { + const input = [37, 17, 98, 135, 161, 178, 88, 97, 125, 150, 143, 65, + 228, 211, 170, 133, 153, 9, 88, 212, 4, 212, 175, 238, 249, 210, + 214, 116, 170, 85, 45, 21]; + const expectedOut = [182, 104, 121, 2, 8, 48, 224, 11, 238, 244, 73, + 142, 67, 205, 166, 27, 10, 223, 142, 209, 10, 46, 171, 110, 239, + 68, 111, 116, 164, 127, 103, 141]; + + const inIn = utils.bytesToBits(input); + + const witness = await cir.calculateWitness({ "in": inIn }, true); + + const stateOut = witness.slice(1, 1+(32*8)); + const stateOutBytes = utils.bitsToBytes(stateOut); + // console.log(stateOutBytes, expectedOut); + assert.deepEqual(stateOutBytes, expectedOut); + }); + it ("Keccak 3 (testvector generated from go)", async () => { + const input = [182, 104, 121, 2, 8, 48, 224, 11, 238, 244, 73, 142, 67, + 205, 166, 27, 10, 223, 142, 209, 10, 46, 171, 110, 239, 68, 111, + 116, 164, 127, 103, 141]; + const expectedOut = [191, 235, 249, 254, 70, 24, 106, 244, 212, 163, + 52, 240, 1, 128, 235, 61, 158, 52, 138, 60, 197, 80, 113, 36, 44, + 217, 55, 211, 97, 231, 26, 7]; + + const inIn = utils.bytesToBits(input); + + const witness = await cir.calculateWitness({ "in": inIn }, true); + + const stateOut = witness.slice(1, 1+(32*8)); + const stateOutBytes = utils.bitsToBytes(stateOut); + // console.log(stateOutBytes, expectedOut); + assert.deepEqual(stateOutBytes, expectedOut); + }); + it ("Keccak 4 (testvector generated from go)", async () => { + const input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + const expectedOut = [41, 13, 236, 217, 84, 139, 98, 168, 214, 3, 69, + 169, 136, 56, 111, 200, 75, 166, 188, 149, 72, 64, 8, 246, 54, 47, + 147, 22, 14, 243, 229, 99]; + + const inIn = utils.bytesToBits(input); + + const witness = await cir.calculateWitness({ "in": inIn }, true); + + const stateOut = witness.slice(1, 1+(32*8)); + const stateOutBytes = utils.bitsToBytes(stateOut); + // console.log(stateOutBytes, expectedOut); + assert.deepEqual(stateOutBytes, expectedOut); + }); + + describe("Keccak256 circuit check with js version", function () { + this.timeout(100000); + + it ("Keccak256 circom-js 1", async () => { + let input, inputBits, expectedOut, witness, stateOut, stateOutBytes; + input = Buffer.from("0000000000000000000000000000000000000000000000000000000000000000", "hex"); + for(let i=0; i<10; i++) { + inputBits = utils.bytesToBits(input); + + let jsOutRaw = keccak256(input); + expectedOut = utils.bufferToBytes(jsOutRaw); + console.log(i, "in:", input.toString('hex'), "\n out:", jsOutRaw.toString('hex')); + + witness = await cir.calculateWitness({ "in": inputBits }, true); + stateOut = witness.slice(1, 1+(32*8)); + stateOutBytes = utils.bitsToBytes(stateOut); + assert.deepEqual(stateOutBytes, expectedOut); + + // assign output into input for next iteration + input = jsOutRaw; + } + }); + }); +}); diff --git a/test/keccak256.js b/test/keccak256.js deleted file mode 100644 index e3c966e..0000000 --- a/test/keccak256.js +++ /dev/null @@ -1,601 +0,0 @@ -const chai = require("chai"); -const path = require("path"); -const crypto = require("crypto"); -const F1Field = require("ffjavascript").F1Field; -const Scalar = require("ffjavascript").Scalar; -exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); -const Fr = new F1Field(exports.p); - -const assert = chai.assert; - -const keccak256 = require("keccak256"); - -const wasm_tester = require("circom_tester").wasm; -const c_tester = require("circom_tester").c; - -// const printSignal = require("./helpers/printsignal"); - -function bytesToU64(byteArray) { - // var value = 0; - var value = Fr.e(0); - for ( var i = byteArray.length - 1; i >= 0; i--) { - // value = (value * 256) + byteArray[i]; - value = Fr.add(Fr.mul(Fr.e(value), Fr.e(256)), Fr.e(byteArray[i])); - } - - return value; -} -function u64ToBytes(a) { - var b = Fr.e(a); - - const buff = new Uint8Array(8); - Scalar.toRprLE(buff, 0, b, 8); - return buff; -} -function u64ToBits(a) { - const aBytes = u64ToBytes(a); - return bytesToBits(aBytes); -} -function bytesToBits(b) { - const bits = []; - for (let i = 0; i < b.length; i++) { - for (let j = 0; j < 8; j++) { - if ((Number(b[i])&(1< 0) { - // bits.push(Fr.e(1)); - bits.push(1); - } else { - // bits.push(Fr.e(0)); - bits.push(0); - } - } - } - return bits -} -function u64ArrayToBits(u) { - let r = []; - for (let i = 0; i < u.length; i++) { - r = r.concat(u64ToBits(u[i])); - } - return r -} -function bitsToU64(b) { - if (b.length != 64) { - console.log("b.length = ", b.length, " max=64"); - return; - } - const by = bitsToBytes(b) - return bytesToU64(by) -} -function bitsToBytes(a) { - const b = []; - - for (let i=0; i { - let a = 3; - let aBits = u64ToBits(a); - let a2 = bitsToU64(aBits); - assert.equal(a2, a); - a = 12345; - aBits = u64ToBits(a); - a2 = bitsToU64(aBits); - assert.equal(a2, a); - - a = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - aBits = u64ArrayToBits(a); - a2 = bitsToU64Array(aBits); - assert.deepEqual(a2, a); - }); -}); - - -describe("Theta test", function () { - this.timeout(100000); - - it ("Theta (testvector generated from go)", async () => { - const cir = await wasm_tester(path.join(__dirname, "circuits", "theta_test.circom")); - - const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const expectedOut = intsToBigInts([26,9,13,29,47,31,14,8,22,34,16,3,3,19,37,21,24,30,12,56,14,29,25,9,51]); - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - it ("Theta (same test as previous, but using c_tester to ensure that circom_tester with c works as expected)", async () => { - const cir = await c_tester(path.join(__dirname, "circuits", "theta_test.circom")); - - const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const expectedOut = intsToBigInts([26,9,13,29,47,31,14,8,22,34,16,3,3,19,37,21,24,30,12,56,14,29,25,9,51]); - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - - it ("Theta (testvector generated from go)", async () => { - const cir = await wasm_tester(path.join(__dirname, "circuits", "theta_test.circom")); - // const cir = await c_tester(path.join(__dirname, "circuits", "theta_test.circom")); - - const input = strsToBigInts(["26388279066651", "246290629787648", "26388279902208", - "25165850", "246290605457408", "7784628352", "844424965783552", - "2305843009213694083", "844432714760192", "2305843009249345539", - "637534226", "14848", "641204224", "14354", "3670528", "6308236288", - "2130304761856", "648518346341354496", "6309216256", "648520476645130240", - "4611706359392501763", "792677514882318336", "20340965113972", - "4611732197915754499", "792633534417207412"]); - const expectedOut = strsToBigInts(["3749081831850030700", "1297317621190464868", - "10017560217643747862", "7854780639862409219", "13836147678645575967", - "3749090635727681271", "1297915755455157604", "12323429615135705749", - "7855062122598582297", "16141814766035214620", "3749090628446369381", - "1297071330560683876", "10017586606556924438", "7854780639837253643", - "13835971756788491039", "3749090634251287159", "1297070162329376100", - "9369068259580659222", "7854780645071013913", "14484490034407743775", - "8360757404916954740", "1801500877105239396", "10017570663003408994", - "3243123208712177690", "14628605291203076459"]); - - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - - -}); - -describe("RhoPi test", function () { - this.timeout(100000); - - it ("RhoPi (testvector generated from go)", async () => { - const cir = await wasm_tester(path.join(__dirname, "circuits", "rhopi_test.circom")); - - const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const expectedOut = strsToBigInts(["0", "105553116266496", "105553116266496", "37748736", "393216", - "805306368", "9437184", "80", "562949953421312", "13835058055282163714", - "2", "448", "436207616", "4864", "5242880", "536870912", "343597383680", - "11264", "557056", "1657324662872342528", "9223372036854775808", - "288230376151711744", "7696581394432", "32985348833280", "84"]); - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); -}); - -describe("Chi test", function () { - this.timeout(100000); - - it ("Chi (testvector generated from go)", async () => { - const cir = await wasm_tester(path.join(__dirname, "circuits", "chi_test.circom")); - - const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const expectedOut = intsToBigInts([2, 0, 6, 3, 5, 4, 14, 6, 12, 11, 14, 10, 14, 13, 15, - 14, 18, 16, 30, 3, 22, 20, 30, 19, 25]); - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); -}); - -describe("Iota test", function () { - this.timeout(100000); - - it ("Iota 3 (testvector generated from go)", async () => { - const cir = await wasm_tester(path.join(__dirname, "circuits", "iota3_test.circom")); - - const input = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const expectedOut = strsToBigInts(["9223372039002292224",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - it ("Iota 10 (testvector generated from go)", async () => { - const cir = await wasm_tester(path.join(__dirname, "circuits", "iota10_test.circom")); - - const input = strsToBigInts(["9223372039002292224",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const expectedOut = strsToBigInts(["9223372036854775817",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); -}); - -describe("Keccak-Pad test", function () { - this.timeout(100000); - - it ("Pad (testvector generated from go)", async () => { - const cir = await wasm_tester(path.join(__dirname, "circuits", "pad_test.circom")); - - const input = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]; - const expectedOut = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128]; - - const stateIn = bytesToBits(input); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(136*8)); - const stateOutBytes = bitsToBytes(stateOut); - // console.log(stateOutBytes, expectedOut); - assert.deepEqual(stateOutBytes, expectedOut); - }); -}); - -describe("keccakfRound test", function () { - this.timeout(100000); - - // apt install nlohmann-json3-dev - // apt install nasm - - it ("keccakfRound (testvector generated from go)", async () => { - // const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom")); - const cir = await c_tester(path.join(__dirname, "circuits", "keccakfRound0_test.circom")); - await cir.loadConstraints(); - // console.log("n_constraints", cir.constraints.length); - - const input = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]; - const expectedOut = strsToBigInts(["26388279066651", "246290629787648", "26388279902208", "25165850", "246290605457408", "7784628352", "844424965783552", "2305843009213694083", "844432714760192", "2305843009249345539", "637534226", "14848", "641204224", "14354", "3670528", "6308236288", "2130304761856", "648518346341354496", "6309216256", "648520476645130240", "4611706359392501763", "792677514882318336", "20340965113972", "4611732197915754499", "792633534417207412"]); - - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - - it ("keccakfRound 20 (testvector generated from go)", async () => { - // const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom")); - const cir = await c_tester(path.join(__dirname, "circuits", "keccakfRound20_test.circom")); - await cir.loadConstraints(); - // console.log("n_constraints", cir.constraints.length); - - const input = strsToBigInts(["26388279066651", "246290629787648", "26388279902208", "25165850", "246290605457408", "7784628352", "844424965783552", "2305843009213694083", "844432714760192", "2305843009249345539", "637534226", "14848", "641204224", "14354", "3670528", "6308236288", "2130304761856", "648518346341354496", "6309216256", "648520476645130240", "4611706359392501763", "792677514882318336", "20340965113972", "4611732197915754499", "792633534417207412"]); - const expectedOut = strsToBigInts(["17728382861289829725", "13654073086381141005", "9912591532945168756", "2030068283137172501", "5084683018496047808", "151244976540463006", "11718217461613725815", "11636071286320763433", "15039144509240642782", "11629028282864249197", "2594633730779457624", "14005558505838459171", "4612881094252610438", "2828009553220809993", "4838578484623267135", "1006588603063111352", "11109191860075454495", "1187545859779038208", "14661669042642437042", "5345317080454741069", "8196674451365552863", "635818354583088260", "13515759754032305626", "1708499319988748543", "7509292798507899312"]); - - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); -}); - -describe("keccakf test", function () { - this.timeout(100000); - - let cir; - before(async () => { - // const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom")); - cir = await c_tester(path.join(__dirname, "circuits", "keccakf_test.circom")); - await cir.loadConstraints(); - console.log("n_constraints", cir.constraints.length); - }); - - it ("keccakf 1 (testvector generated from go)", async () => { - const input = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]; - const expectedOut = strsToBigInts(["9472389783892099349", "2159377575142921216", "17826682512249813373", "2325963263767348549", "15086930817298358378", "11661812091723830419", "3517755057770134847", "5223775837645169598", "933274647126506074", "3451250694486589320", "825065683101361807", "6192414258352188799", "14426505790672879210", "3326742392640380689", "16749975585634164134", "17847697619892908514", "11598434253200954839", "6049795840392747215", "8610635351954084385", "18234131770974529925", "15330347418010067760", "12047099911907354591", "4763389569697138851", "6779624089296570504", "15083668107635345971"]); - - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - - it ("keccakf 2 (testvector generated from go)", async () => { - const input = strsToBigInts(["9472389783892099349", "2159377575142921216", "17826682512249813373", "2325963263767348549", "15086930817298358378", "11661812091723830419", "3517755057770134847", "5223775837645169598", "933274647126506074", "3451250694486589320", "825065683101361807", "6192414258352188799", "14426505790672879210", "3326742392640380689", "16749975585634164134", "17847697619892908514", "11598434253200954839", "6049795840392747215", "8610635351954084385", "18234131770974529925", "15330347418010067760", "12047099911907354591", "4763389569697138851", "6779624089296570504", "15083668107635345971"]); - const expectedOut = strsToBigInts(["269318771259381490", "15892848561416382510", "12485559500958802382", "4360182510883008729", "14284025675983944434", "8800366419087562177", "7881853509112258378", "9503857914080778528", "17110477940977988953", "13825318756568052601", "11460650932194163315", "13272167288297399439", "13599957064256729412", "12730838251751851758", "13736647180617564382", "5651695613583298166", "15496251216716036782", "9748494184433838858", "3637745438296580159", "3821184813198767406", "15603239432236101315", "3726326332491237029", "7819962668913661099", "2285898735263816116", "13518516210247555620"]); - - const stateIn = u64ArrayToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": stateIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); -}); - -describe("absorb test", function () { - this.timeout(100000); - - let cir; - before(async () => { - // const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom")); - cir = await c_tester(path.join(__dirname, "circuits", "absorb_test.circom")); - await cir.loadConstraints(); - console.log("n_constraints", cir.constraints.length); - }); - - it ("absorb 1 (testvector generated from go)", async () => { - const s = strsToBigInts(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"]); - - const block = strsToBigInts(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28","29", "30", "31", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0","0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "128"]); - - const expectedOut = strsToBigInts(["8342348566319207042", "319359607942176202", "14410076088654599075", "15666111399434436772", "9558421567405313402", "3396178318116504023", "794353847439963108", "12717011319735989377", "3503398863218919239", "5517201702366862678", "15999361614129160496", "1325524015888689985", "11971708408118944333", "14874486179441062217", "12554876384974234666", "11129975558302206043", "11257826431949606534", "2740710607956478714", "15000019752453010167", "15593606854132419294", "2598425978562809333","8872504799797239246", "1212062965004664308", "5443427421087086722", "10946808592826700411"]); - - const sIn = u64ArrayToBits(s); - const blockIn = bytesToBits(block); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "s": sIn, "block": blockIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - - it ("absorb 2 (testvector generated from go)", async () => { - const s = strsToBigInts(["8342348566319207042", "319359607942176202", "14410076088654599075", "15666111399434436772", "9558421567405313402", "3396178318116504023", "794353847439963108", "12717011319735989377", "3503398863218919239", "5517201702366862678", "15999361614129160496", "1325524015888689985", "11971708408118944333", "14874486179441062217", "12554876384974234666", "11129975558302206043", "11257826431949606534", "2740710607956478714", "15000019752453010167", "15593606854132419294", "2598425978562809333","8872504799797239246", "1212062965004664308", "5443427421087086722", "10946808592826700411"]); - - const block = strsToBigInts(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28","29", "30", "31", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0","0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "128"]); - - const expectedOut = strsToBigInts(["8909243822027471379", "1111840847970088140", "12093072708540612559", "11255033638786021658", "2082116894939842214", "12821085060245261575", "6901785969834988344", "3182430130277914993", "2164708585929408975", "14402143231999718904", "16231444410553803968", "1850945423480060493", "12856855675247400303", "1137248620532111171", "7389129221921446308", "12932467982741614601", "1350606937385760406", "10983682292859713641", "10305595434820307765", "13958651111365489854", "17206620388135196198", "4238113785249530092", "7230868147643218103", "603011106238724524", "16480095441097880488"]); - - const sIn = u64ArrayToBits(s); - const blockIn = bytesToBits(block); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "s": sIn, "block": blockIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); -}); - -describe("Keccak-Final test", function () { - this.timeout(100000); - - let cir; - before(async () => { - cir = await c_tester(path.join(__dirname, "circuits", "final_test.circom")); - await cir.loadConstraints(); - console.log("n_constraints", cir.constraints.length); - }); - - it ("Final 1 (testvector generated from go)", async () => { - const input = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]; - const expectedOut = strsToBigInts(["16953415415620100490", "7495738965189503699", "12723370805759944158", "3295955328722933810", "12121371508560456016", "174876831679863147", "15944933357501475584", "7502339663607726274", "12048918224562833898", "16715284461100269102", "15582559130083209842", "1743886467337678829", "2424196198791253761", "1116417308245482383", "10367365997906434042", "1849801549382613906", "13294939539683415102", "4478091053375708790", "2969967870313332958", "14618962068930014237", "2721742233407503451", "12003265593030191290", "8109318293656735684", "6346795302983965746", "12210038122000333046"]); - - const inIn = bytesToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": inIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); - - it ("Final 2 (testvector generated from go)", async () => { - const input = strsToBigInts(["254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254", "254"]); - const expectedOut = strsToBigInts(["16852464862333879129", "9588646233186836430", "693207875935078627", "6545910230963382296", "3599194178366828471", "13130606490077331384", "10374798023615518933", "7285576075118720444", "4097382401500492461", "3968685317688314807", "3350659309646210303", "640023485234837464", "2550030127986774041", "8948768022010378840", "10678227883444996205", "1395278318096830339", "2744077813166753978", "13362598477502046010", "14601579319881128511", "4070707967569603186", "16833768365875755098", "1486295134719870048", "9161068934282437999", "8245604251371175619", "8421994351908003183"]); - - const inIn = bytesToBits(input); - const expectedOutBits = u64ArrayToBits(expectedOut); - - const witness = await cir.calculateWitness({ "in": inIn }, true); - - const stateOut = witness.slice(1, 1+(25*64)); - const stateOutU64 = bitsToU64Array(stateOut); - // console.log(stateOutU64, expectedOut); - assert.deepEqual(stateOutU64, expectedOut); - }); -}); - -describe("Keccak-Squeeze test", function () { - this.timeout(100000); - - let cir; - before(async () => { - cir = await c_tester(path.join(__dirname, "circuits", "squeeze_test.circom")); - await cir.loadConstraints(); - console.log("n_constraints", cir.constraints.length); - }); - - it ("Squeeze 1 (testvector generated from go)", async () => { - const input = strsToBigInts(["16852464862333879129", "9588646233186836430", "693207875935078627", "6545910230963382296", "3599194178366828471", "13130606490077331384", "10374798023615518933", "7285576075118720444", "4097382401500492461", "3968685317688314807", "3350659309646210303", "640023485234837464", "2550030127986774041", "8948768022010378840", "10678227883444996205", "1395278318096830339", "2744077813166753978", "13362598477502046010", "14601579319881128511", "4070707967569603186", "16833768365875755098", "1486295134719870048", "9161068934282437999", "8245604251371175619", "8421994351908003183"]); - - const expectedOut = [89, 195, 41, 13, 129, 251, 223, 233, 206, 31, 253, 61, 242, 182, 17, 133, 227, 8, 157, 240, 227, 196, 158, 9, 24, 232, 42, 96, 172, 190, 215, 90]; - - const inIn = u64ArrayToBits(input); - const expectedOutBits = bytesToBits(expectedOut); - - const witness = await cir.calculateWitness({ "s": inIn }, true); - - const stateOut = witness.slice(1, 1+(32*8)); - const stateOutBytes = bitsToBytes(stateOut); - // console.log(stateOutBytes, expectedOut); - assert.deepEqual(stateOutBytes, expectedOut); - }); - it ("Squeeze 2 (testvector generated from go)", async () => { - const input = strsToBigInts(["16953415415620100490", "7495738965189503699", "12723370805759944158", "3295955328722933810", "12121371508560456016", "174876831679863147", "15944933357501475584", "7502339663607726274", "12048918224562833898", "16715284461100269102", "15582559130083209842", "1743886467337678829", "2424196198791253761", "1116417308245482383", "10367365997906434042", "1849801549382613906", "13294939539683415102", "4478091053375708790", "2969967870313332958", "14618962068930014237", "2721742233407503451", "12003265593030191290", "8109318293656735684", "6346795302983965746", "12210038122000333046"]); - - const expectedOut = [138, 225, 170, 89, 127, 161, 70, 235, 211, 170, 44, 237, 223, 54, 6, 104, 222, 165, 229, 38, 86, 126, 146, 176, 50, 24, 22, 164, 232, 149, 189, 45]; - - const inIn = u64ArrayToBits(input); - const expectedOutBits = bytesToBits(expectedOut); - - const witness = await cir.calculateWitness({ "s": inIn }, true); - - const stateOut = witness.slice(1, 1+(32*8)); - const stateOutBytes = bitsToBytes(stateOut); - // console.log(stateOutBytes, expectedOut); - assert.deepEqual(stateOutBytes, expectedOut); - }); -}); - -describe("Keccak full hash test", function () { - this.timeout(100000); - - let cir; - before(async () => { - cir = await c_tester(path.join(__dirname, "circuits", "keccak256_test.circom")); - await cir.loadConstraints(); - console.log("n_constraints", cir.constraints.length); - }); - - it ("Keccak 1 (testvector generated from go)", async () => { - const input = [116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - const expectedOut = [37, 17, 98, 135, 161, 178, 88, 97, 125, 150, 143, - 65, 228, 211, 170, 133, 153, 9, 88, 212, 4, 212, 175, 238, 249, - 210, 214, 116, 170, 85, 45, 21]; - - const inIn = bytesToBits(input); - - const witness = await cir.calculateWitness({ "in": inIn }, true); - - const stateOut = witness.slice(1, 1+(32*8)); - const stateOutBytes = bitsToBytes(stateOut); - // console.log(stateOutBytes, expectedOut); - assert.deepEqual(stateOutBytes, expectedOut); - }); - it ("Keccak 2 (testvector generated from go)", async () => { - const input = [37, 17, 98, 135, 161, 178, 88, 97, 125, 150, 143, 65, - 228, 211, 170, 133, 153, 9, 88, 212, 4, 212, 175, 238, 249, 210, - 214, 116, 170, 85, 45, 21]; - const expectedOut = [182, 104, 121, 2, 8, 48, 224, 11, 238, 244, 73, - 142, 67, 205, 166, 27, 10, 223, 142, 209, 10, 46, 171, 110, 239, - 68, 111, 116, 164, 127, 103, 141]; - - const inIn = bytesToBits(input); - - const witness = await cir.calculateWitness({ "in": inIn }, true); - - const stateOut = witness.slice(1, 1+(32*8)); - const stateOutBytes = bitsToBytes(stateOut); - // console.log(stateOutBytes, expectedOut); - assert.deepEqual(stateOutBytes, expectedOut); - }); - it ("Keccak 3 (testvector generated from go)", async () => { - const input = [182, 104, 121, 2, 8, 48, 224, 11, 238, 244, 73, 142, 67, - 205, 166, 27, 10, 223, 142, 209, 10, 46, 171, 110, 239, 68, 111, - 116, 164, 127, 103, 141]; - const expectedOut = [191, 235, 249, 254, 70, 24, 106, 244, 212, 163, - 52, 240, 1, 128, 235, 61, 158, 52, 138, 60, 197, 80, 113, 36, 44, - 217, 55, 211, 97, 231, 26, 7]; - - const inIn = bytesToBits(input); - - const witness = await cir.calculateWitness({ "in": inIn }, true); - - const stateOut = witness.slice(1, 1+(32*8)); - const stateOutBytes = bitsToBytes(stateOut); - // console.log(stateOutBytes, expectedOut); - assert.deepEqual(stateOutBytes, expectedOut); - }); - it ("Keccak 4 (testvector generated from go)", async () => { - const input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - const expectedOut = [41, 13, 236, 217, 84, 139, 98, 168, 214, 3, 69, - 169, 136, 56, 111, 200, 75, 166, 188, 149, 72, 64, 8, 246, 54, 47, - 147, 22, 14, 243, 229, 99]; - - const inIn = bytesToBits(input); - - const witness = await cir.calculateWitness({ "in": inIn }, true); - - const stateOut = witness.slice(1, 1+(32*8)); - const stateOutBytes = bitsToBytes(stateOut); - // console.log(stateOutBytes, expectedOut); - assert.deepEqual(stateOutBytes, expectedOut); - }); -}); diff --git a/test/keccakf.js b/test/keccakf.js new file mode 100644 index 0000000..c9eba89 --- /dev/null +++ b/test/keccakf.js @@ -0,0 +1,159 @@ +const path = require("path"); + +const chai = require("chai"); +const assert = chai.assert; + +const c_tester = require("circom_tester").c; + +const utils = require("./utils"); + +describe("keccakfRound test", function () { + this.timeout(100000); + + // apt install nlohmann-json3-dev + // apt install nasm + // apt install libgmp3-dev + + it ("keccakfRound (testvector generated from go)", async () => { + const cir = await c_tester(path.join(__dirname, "circuits", "keccakfRound0_test.circom")); + await cir.loadConstraints(); + // console.log("n_constraints", cir.constraints.length); + + const input = + [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]; + const expectedOut = utils.strsToBigInts(["26388279066651", + "246290629787648", "26388279902208", "25165850", "246290605457408", + "7784628352", "844424965783552", "2305843009213694083", + "844432714760192", "2305843009249345539", "637534226", "14848", + "641204224", "14354", "3670528", "6308236288", "2130304761856", + "648518346341354496", "6309216256", "648520476645130240", + "4611706359392501763", "792677514882318336", "20340965113972", + "4611732197915754499", "792633534417207412"]); + + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + + it ("keccakfRound 20 (testvector generated from go)", async () => { + const cir = await c_tester(path.join(__dirname, "circuits", "keccakfRound20_test.circom")); + await cir.loadConstraints(); + // console.log("n_constraints", cir.constraints.length); + + const input = utils.strsToBigInts(["26388279066651", "246290629787648", + "26388279902208", "25165850", "246290605457408", "7784628352", + "844424965783552", "2305843009213694083", "844432714760192", + "2305843009249345539", "637534226", "14848", "641204224", "14354", + "3670528", "6308236288", "2130304761856", "648518346341354496", + "6309216256", "648520476645130240", "4611706359392501763", + "792677514882318336", "20340965113972", "4611732197915754499", + "792633534417207412"]); + const expectedOut = utils.strsToBigInts(["17728382861289829725", + "13654073086381141005", "9912591532945168756", + "2030068283137172501", "5084683018496047808", "151244976540463006", + "11718217461613725815", "11636071286320763433", + "15039144509240642782", "11629028282864249197", + "2594633730779457624", "14005558505838459171", + "4612881094252610438", "2828009553220809993", + "4838578484623267135", "1006588603063111352", + "11109191860075454495", "1187545859779038208", + "14661669042642437042", "5345317080454741069", + "8196674451365552863", "635818354583088260", + "13515759754032305626", "1708499319988748543", + "7509292798507899312"]); + + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +}); + +describe("keccakf test", function () { + this.timeout(100000); + + let cir; + before(async () => { + cir = await c_tester(path.join(__dirname, "circuits", "keccakf_test.circom")); + await cir.loadConstraints(); + console.log("n_constraints", cir.constraints.length); + }); + + it ("keccakf 1 (testvector generated from go)", async () => { + const input = + [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]; + const expectedOut = utils.strsToBigInts(["9472389783892099349", + "2159377575142921216", "17826682512249813373", + "2325963263767348549", "15086930817298358378", + "11661812091723830419", "3517755057770134847", + "5223775837645169598", "933274647126506074", "3451250694486589320", + "825065683101361807", "6192414258352188799", + "14426505790672879210", "3326742392640380689", + "16749975585634164134", "17847697619892908514", + "11598434253200954839", "6049795840392747215", + "8610635351954084385", "18234131770974529925", + "15330347418010067760", "12047099911907354591", + "4763389569697138851", "6779624089296570504", + "15083668107635345971"]); + + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + + it ("keccakf 2 (testvector generated from go)", async () => { + const input = utils.strsToBigInts(["9472389783892099349", + "2159377575142921216", "17826682512249813373", + "2325963263767348549", "15086930817298358378", + "11661812091723830419", "3517755057770134847", + "5223775837645169598", "933274647126506074", "3451250694486589320", + "825065683101361807", "6192414258352188799", + "14426505790672879210", "3326742392640380689", + "16749975585634164134", "17847697619892908514", + "11598434253200954839", "6049795840392747215", + "8610635351954084385", "18234131770974529925", + "15330347418010067760", "12047099911907354591", + "4763389569697138851", "6779624089296570504", + "15083668107635345971"]); + const expectedOut = utils.strsToBigInts(["269318771259381490", + "15892848561416382510", "12485559500958802382", + "4360182510883008729", "14284025675983944434", + "8800366419087562177", "7881853509112258378", + "9503857914080778528", "17110477940977988953", + "13825318756568052601", "11460650932194163315", + "13272167288297399439", "13599957064256729412", + "12730838251751851758", "13736647180617564382", + "5651695613583298166", "15496251216716036782", + "9748494184433838858", "3637745438296580159", + "3821184813198767406", "15603239432236101315", + "3726326332491237029", "7819962668913661099", + "2285898735263816116", "13518516210247555620"]); + + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +}); diff --git a/test/permutations.js b/test/permutations.js new file mode 100644 index 0000000..bc75718 --- /dev/null +++ b/test/permutations.js @@ -0,0 +1,174 @@ +const path = require("path"); + +const chai = require("chai"); +const assert = chai.assert; + +const wasm_tester = require("circom_tester").wasm; +const c_tester = require("circom_tester").c; + +const utils = require("./utils"); + +describe("Theta test", function () { + this.timeout(100000); + + it ("Theta (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "theta_test.circom")); + + const input = + utils.intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const expectedOut = + utils.intsToBigInts([26,9,13,29,47,31,14,8,22,34,16,3,3,19,37,21,24,30,12,56,14,29,25,9,51]); + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + it ("Theta (same test as previous, but using c_tester to ensure that"+ + "circom_tester with c works as expected)", async () => { + const cir = await c_tester(path.join(__dirname, "circuits", "theta_test.circom")); + + const input = + utils.intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const expectedOut = + utils.intsToBigInts([26,9,13,29,47,31,14,8,22,34,16,3,3,19,37,21,24,30,12,56,14,29,25,9,51]); + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + + it ("Theta (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "theta_test.circom")); + // const cir = await c_tester(path.join(__dirname, "circuits", "theta_test.circom")); + + const input = utils.strsToBigInts(["26388279066651", "246290629787648", + "26388279902208", "25165850", "246290605457408", "7784628352", + "844424965783552", "2305843009213694083", "844432714760192", + "2305843009249345539", "637534226", "14848", "641204224", "14354", + "3670528", "6308236288", "2130304761856", "648518346341354496", + "6309216256", "648520476645130240", "4611706359392501763", + "792677514882318336", "20340965113972", "4611732197915754499", + "792633534417207412"]); + const expectedOut = utils.strsToBigInts(["3749081831850030700", + "1297317621190464868", "10017560217643747862", + "7854780639862409219", "13836147678645575967", + "3749090635727681271", "1297915755455157604", + "12323429615135705749", "7855062122598582297", + "16141814766035214620", "3749090628446369381", + "1297071330560683876", "10017586606556924438", + "7854780639837253643", "13835971756788491039", + "3749090634251287159", "1297070162329376100", + "9369068259580659222", "7854780645071013913", + "14484490034407743775", "8360757404916954740", + "1801500877105239396", "10017570663003408994", + "3243123208712177690", "14628605291203076459"]); + + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + + +}); + +describe("RhoPi test", function () { + this.timeout(100000); + + it ("RhoPi (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "rhopi_test.circom")); + + const input = + utils.intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const expectedOut = utils.strsToBigInts(["0", "105553116266496", + "105553116266496", "37748736", "393216", "805306368", "9437184", + "80", "562949953421312", "13835058055282163714", "2", "448", + "436207616", "4864", "5242880", "536870912", "343597383680", + "11264", "557056", "1657324662872342528", "9223372036854775808", + "288230376151711744", "7696581394432", "32985348833280", "84"]); + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +}); + +describe("Chi test", function () { + this.timeout(100000); + + it ("Chi (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "chi_test.circom")); + + const input = + utils.intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const expectedOut = utils.intsToBigInts([2, 0, 6, 3, 5, 4, 14, 6, 12, + 11, 14, 10, 14, 13, 15, 14, 18, 16, 30, 3, 22, 20, 30, 19, 25]); + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +}); + +describe("Iota test", function () { + this.timeout(100000); + + it ("Iota 3 (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "iota3_test.circom")); + + const input = + utils.intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const expectedOut = + utils.strsToBigInts(["9223372039002292224",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + it ("Iota 10 (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "iota10_test.circom")); + + const input = + utils.strsToBigInts(["9223372039002292224",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const expectedOut = + utils.strsToBigInts(["9223372036854775817",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + const stateIn = utils.u64ArrayToBits(input); + const expectedOutBits = utils.u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = utils.bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +}); diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 0000000..3086d7c --- /dev/null +++ b/test/utils.js @@ -0,0 +1,147 @@ +const F1Field = require("ffjavascript").F1Field; +const Scalar = require("ffjavascript").Scalar; +exports.p = + Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Fr = new F1Field(exports.p); + +const chai = require("chai"); +const assert = chai.assert; + +module.exports = { + bytesToU64, + u64ToBytes, + u64ToBits, + bytesToBits, + u64ArrayToBits, + bitsToU64, + bitsToBytes, + bitsToU64Array, + strsToBigInts, + intsToBigInts, + bigIntsToInts, + bufferToBytes +}; + +function bytesToU64(byteArray) { + // var value = 0; + var value = Fr.e(0); + for ( var i = byteArray.length - 1; i >= 0; i--) { + // value = (value * 256) + byteArray[i]; + value = Fr.add(Fr.mul(Fr.e(value), Fr.e(256)), Fr.e(byteArray[i])); + } + + return value; +} +function u64ToBytes(a) { + var b = Fr.e(a); + + const buff = new Uint8Array(8); + Scalar.toRprLE(buff, 0, b, 8); + return buff; +} +function u64ToBits(a) { + const aBytes = u64ToBytes(a); + return bytesToBits(aBytes); +} +function bytesToBits(b) { + const bits = []; + for (let i = 0; i < b.length; i++) { + for (let j = 0; j < 8; j++) { + if ((Number(b[i])&(1< 0) { + // bits.push(Fr.e(1)); + bits.push(1); + } else { + // bits.push(Fr.e(0)); + bits.push(0); + } + } + } + return bits +} +function u64ArrayToBits(u) { + let r = []; + for (let i = 0; i < u.length; i++) { + r = r.concat(u64ToBits(u[i])); + } + return r +} +function bitsToU64(b) { + if (b.length != 64) { + console.log("b.length = ", b.length, " max=64"); + return; + } + const by = bitsToBytes(b) + return bytesToU64(by) +} +function bitsToBytes(a) { + const b = []; + + for (let i=0; i { + let a = 3; + let aBits = u64ToBits(a); + let a2 = bitsToU64(aBits); + assert.equal(a2, a); + a = 12345; + aBits = u64ToBits(a); + a2 = bitsToU64(aBits); + assert.equal(a2, a); + + a = intsToBigInts([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]); + aBits = u64ArrayToBits(a); + a2 = bitsToU64Array(aBits); + assert.deepEqual(a2, a); + }); +}); +