Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: chacha20 #51

Merged
merged 6 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/nivc/chacha20_nivc.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: 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);
Autoparallel marked this conversation as resolved.
Show resolved Hide resolved
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 | 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