Skip to content

Commit

Permalink
Merge pull request #49 from pluto/chacha20
Browse files Browse the repository at this point in the history
Chacha20
  • Loading branch information
0xJepsen authored Nov 19, 2024
2 parents 3fdfd5c + 67e2ff4 commit e7f246f
Show file tree
Hide file tree
Showing 23 changed files with 967 additions and 123 deletions.
5 changes: 0 additions & 5 deletions builds/target_1024b/aes_gctr_nivc_1024b.circom

This file was deleted.

5 changes: 5 additions & 0 deletions builds/target_1024b/chacha20_nivc_1024.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma circom 2.1.9;

include "../../circuits/chacha20/chacha20.circom";

component main = ChaCha20_NIVC(256);
6 changes: 0 additions & 6 deletions builds/target_1024b/http_body_mask_1024b.circom

This file was deleted.

5 changes: 0 additions & 5 deletions builds/target_1024b/http_lock_header_1024b.circom

This file was deleted.

This file was deleted.

5 changes: 0 additions & 5 deletions builds/target_512b/aes_gctr_nivc_512b.circom

This file was deleted.

5 changes: 5 additions & 0 deletions builds/target_512b/chacha20_nivc_512b.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma circom 2.1.9;

include "../../circuits/chacha20/nivc/chacha20_nivc.circom";

component main = ChaCha20_NIVC(128);
6 changes: 0 additions & 6 deletions builds/target_512b/http_body_mask_512b.circom

This file was deleted.

5 changes: 0 additions & 5 deletions builds/target_512b/http_lock_header_512b.circom

This file was deleted.

5 changes: 0 additions & 5 deletions builds/target_512b/http_parse_and_lock_start_line_512b.circom

This file was deleted.

88 changes: 88 additions & 0 deletions circuits/chacha20/chacha-qr.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// initially from https://github.com/reclaimprotocol/zk-symmetric-crypto
// modified for our needs
pragma circom 2.1.9;

include "../utils/generics-bits.circom";

/**
* Perform ChaCha Quarter Round
* Assume 4 words of 32 bits each
* Each word must be little endian
*/
template QR() {
signal input in[4][32];
signal output out[4][32];

var tmp[4][32] = in;

// a += b
component add1 = AddBits(32);
add1.a <== tmp[0];
add1.b <== tmp[1];

tmp[0] = add1.out;

// d ^= a
component xor1 = XorBits(32);
xor1.a <== tmp[3];
xor1.b <== tmp[0];
tmp[3] = xor1.out;

// d = RotateLeft32BitsUnsafe(d, 16)
component rot1 = RotateLeftBits(32, 16);
rot1.in <== tmp[3];
tmp[3] = rot1.out;

// c += d
component add2 = AddBits(32);
add2.a <== tmp[2];
add2.b <== tmp[3];
tmp[2] = add2.out;

// b ^= c
component xor2 = XorBits(32);
xor2.a <== tmp[1];
xor2.b <== tmp[2];
tmp[1] = xor2.out;

// b = RotateLeft32BitsUnsafe(b, 12)
component rot2 = RotateLeftBits(32, 12);
rot2.in <== tmp[1];
tmp[1] = rot2.out;

// a += b
component add3 = AddBits(32);
add3.a <== tmp[0];
add3.b <== tmp[1];
tmp[0] = add3.out;

// d ^= a
component xor3 = XorBits(32);
xor3.a <== tmp[3];
xor3.b <== tmp[0];
tmp[3] = xor3.out;

// d = RotateLeft32BitsUnsafe(d, 8)
component rot3 = RotateLeftBits(32, 8);
rot3.in <== tmp[3];
tmp[3] = rot3.out;

// c += d
component add4 = AddBits(32);
add4.a <== tmp[2];
add4.b <== tmp[3];
tmp[2] = add4.out;

// b ^= c
component xor4 = XorBits(32);
xor4.a <== tmp[1];
xor4.b <== tmp[2];
tmp[1] = xor4.out;

// b = RotateLeft32BitsUnsafe(b, 7)
component rot4 = RotateLeftBits(32, 7);
rot4.in <== tmp[1];
tmp[1] = rot4.out;

out <== tmp;
}
112 changes: 112 additions & 0 deletions circuits/chacha20/chacha-round.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// initially from https://github.com/reclaimprotocol/zk-symmetric-crypto
// modified for our needs
pragma circom 2.1.9;

include "./chacha-qr.circom";
include "../utils/generics-bits.circom";

template Round() {
// in => 16 32-bit words
signal input in[16][32];
// out => 16 32-bit words
signal output out[16][32];

var tmp[16][32] = in;

component rounds[10 * 8];
component finalAdd[16];
// i-th round
var i = 0;
// col loop counter
var j = 0;
// counter for the rounds array
var k = 0;
for(i = 0; i < 10; i++) {
// columns of the matrix in a loop
// 0, 4, 8, 12
// 1, 5, 9, 13
// 2, 6, 10, 14
// 3, 7, 11, 15
for(j = 0; j < 4; j++) {
rounds[k] = QR();
rounds[k].in[0] <== tmp[j];
rounds[k].in[1] <== tmp[j + 4];
rounds[k].in[2] <== tmp[j + 8];
rounds[k].in[3] <== tmp[j + 12];

tmp[j] = rounds[k].out[0];
tmp[j + 4] = rounds[k].out[1];
tmp[j + 8] = rounds[k].out[2];
tmp[j + 12] = rounds[k].out[3];

k ++;
}

// 4 diagnals
// 0, 5, 10, 15
rounds[k] = QR();
rounds[k].in[0] <== tmp[0];
rounds[k].in[1] <== tmp[5];
rounds[k].in[2] <== tmp[10];
rounds[k].in[3] <== tmp[15];

tmp[0] = rounds[k].out[0];
tmp[5] = rounds[k].out[1];
tmp[10] = rounds[k].out[2];
tmp[15] = rounds[k].out[3];

k ++;

// 1, 6, 11, 12
rounds[k] = QR();
rounds[k].in[0] <== tmp[1];
rounds[k].in[1] <== tmp[6];
rounds[k].in[2] <== tmp[11];
rounds[k].in[3] <== tmp[12];

tmp[1] = rounds[k].out[0];
tmp[6] = rounds[k].out[1];
tmp[11] = rounds[k].out[2];
tmp[12] = rounds[k].out[3];

k ++;

// 2, 7, 8, 13
rounds[k] = QR();
rounds[k].in[0] <== tmp[2];
rounds[k].in[1] <== tmp[7];
rounds[k].in[2] <== tmp[8];
rounds[k].in[3] <== tmp[13];

tmp[2] = rounds[k].out[0];
tmp[7] = rounds[k].out[1];
tmp[8] = rounds[k].out[2];
tmp[13] = rounds[k].out[3];

k ++;

// 3, 4, 9, 14
rounds[k] = QR();
rounds[k].in[0] <== tmp[3];
rounds[k].in[1] <== tmp[4];
rounds[k].in[2] <== tmp[9];
rounds[k].in[3] <== tmp[14];

tmp[3] = rounds[k].out[0];
tmp[4] = rounds[k].out[1];
tmp[9] = rounds[k].out[2];
tmp[14] = rounds[k].out[3];

k ++;
}

// add the result to the input
for(i = 0; i < 16; i++) {
finalAdd[i] = AddBits(32);
finalAdd[i].a <== tmp[i];
finalAdd[i].b <== in[i];
tmp[i] = finalAdd[i].out;
}

out <== tmp;
}
108 changes: 108 additions & 0 deletions circuits/chacha20/chacha20.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// initially from https://github.com/reclaimprotocol/zk-symmetric-crypto
// modified for our needs
pragma circom 2.1.9;

include "./chacha-round.circom";
include "./chacha-qr.circom";
include "../utils/generics-bits.circom";

/** ChaCha20 in counter mode */
// Chacha20 opperates a 4x4 matrix of 32-bit words where the first 4 words are constants: C
// and the next 8 words are the 256 bit key: K. The next 2 words are the block counter: #
// and the last 2 words are the nonce: N.
// +---+---+---+---+
// | C | C | C | C |
// +---+---+---+---+
// | K | K | K | K |
// +---+---+---+---+
// | K | K | K | K |
// +---+---+---+---+
// | # | # | N | N |
// +---+---+---+---+
// paramaterized by n which is the number of 32-bit words to encrypt
template ChaCha20(N) {
// key => 8 32-bit words = 32 bytes
signal input key[8][32];
// nonce => 3 32-bit words = 12 bytes
signal input nonce[3][32];
// counter => 32-bit word to apply w nonce
signal input counter[32];

// the below can be both ciphertext or plaintext depending on the direction
// in => N 32-bit words => N 4 byte words
signal input in[N][32];
// out => N 32-bit words => N 4 byte words
signal output out[N][32];

var tmp[16][32] = [
[
// constant 0x61707865
0, 1, 1, 0, 0, 0, 0, 1, 0,
1, 1, 1, 0, 0, 0, 0, 0, 1,
1, 1, 1, 0, 0, 0, 0, 1, 1,
0, 0, 1, 0, 1
],
[
// constant 0x3320646e
0, 0, 1, 1, 0, 0, 1, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 0, 0, 1, 1,
0, 1, 1, 1, 0
],
[
// constant 0x79622d32
0, 1, 1, 1, 1, 0, 0, 1, 0,
1, 1, 0, 0, 0, 1, 0, 0, 0,
1, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0
],
[
// constant 0x6b206574
0, 1, 1, 0, 1, 0, 1, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 1, 0, 1, 1,
1, 0, 1, 0, 0
],
key[0], key[1], key[2], key[3],
key[4], key[5], key[6], key[7],
counter, nonce[0], nonce[1], nonce[2]
];

// 1 in 32-bit words
signal one[32];
one <== [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1
];

var i = 0;
var j = 0;

// do the ChaCha20 rounds
component rounds[N/16];
component xors[N];
component counter_adder[N/16 - 1];

for(i = 0; i < N/16; i++) {
rounds[i] = Round();
rounds[i].in <== tmp;
// XOR block with input
for(j = 0; j < 16; j++) {
xors[i*16 + j] = XorBits(32);
xors[i*16 + j].a <== in[i*16 + j];
xors[i*16 + j].b <== rounds[i].out[j];
out[i*16 + j] <== xors[i*16 + j].out;
}

if(i < N/16 - 1) {
counter_adder[i] = AddBits(32);
counter_adder[i].a <== tmp[12];
counter_adder[i].b <== one;

// increment the counter
tmp[12] = counter_adder[i].out;
}
}
}
Loading

0 comments on commit e7f246f

Please sign in to comment.