Skip to content

Commit

Permalink
add complete test case
Browse files Browse the repository at this point in the history
  • Loading branch information
lonerapier committed Jan 17, 2025
1 parent 110c44a commit e83ed0a
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 8 deletions.
8 changes: 4 additions & 4 deletions circuits/http/verification.circom
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pragma circom 2.1.9;

include "machine.circom";
// TODO: we don't need this if we do a poly digest of the plaintext in authentication circuit
include "../utils/hash.circom";

template HTTPVerification(DATA_BYTES, MAX_NUMBER_OF_HEADERS) {
Expand All @@ -19,7 +18,8 @@ template HTTPVerification(DATA_BYTES, MAX_NUMBER_OF_HEADERS) {
}
signal pt_digest <== PolynomialDigest(DATA_BYTES)(zeroed_data, ciphertext_digest);

signal input main_digests[MAX_NUMBER_OF_HEADERS + 1]; // Contains digests of start line and all intended headers (up to `MAX_NUMBER_OF_HEADERS`)
// Contains digests of start line and all intended headers (up to `MAX_NUMBER_OF_HEADERS`)
signal input main_digests[MAX_NUMBER_OF_HEADERS + 1];
signal not_contained[MAX_NUMBER_OF_HEADERS + 1];
var num_to_match = MAX_NUMBER_OF_HEADERS + 1;
for(var i = 0 ; i < MAX_NUMBER_OF_HEADERS + 1 ; i++) {
Expand Down Expand Up @@ -106,7 +106,7 @@ template HTTPVerification(DATA_BYTES, MAX_NUMBER_OF_HEADERS) {
State[DATA_BYTES - 1].next_parsing_body === 1;
State[DATA_BYTES - 1].next_line_status === 0;

// TODO: Need to subtract all the header digests here and also wrap them in poseidon. We can use the ones from the input to make this cheaper since they're verified in this circuit!
// subtract all the header digests here and also wrap them in poseidon.
signal body_digest_hashed <== Poseidon(1)([body_digest[DATA_BYTES - 1]]);
signal option_hash[MAX_NUMBER_OF_HEADERS + 1];
signal main_digests_hashed[MAX_NUMBER_OF_HEADERS + 1];
Expand All @@ -117,5 +117,5 @@ template HTTPVerification(DATA_BYTES, MAX_NUMBER_OF_HEADERS) {
accumulated_main_digests_hashed += main_digests_hashed[i];
}

step_out[0] <== step_in[0] + body_digest_hashed - accumulated_main_digests_hashed - pt_digest; // TODO: data_digest is really plaintext_digest from before, consider changing names
step_out[0] <== step_in[0] + body_digest_hashed - accumulated_main_digests_hashed - pt_digest;
}
2 changes: 1 addition & 1 deletion circuits/test/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ interface ManifestResponse {
};
}

interface Manifest {
export interface Manifest {
response: ManifestResponse;
}

Expand Down
114 changes: 111 additions & 3 deletions circuits/test/full/full.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { assert } from "chai";
import { circomkit, WitnessTester, uintArray32ToBits, http_response_plaintext, http_response_ciphertext, http_start_line, http_header_0, http_header_1, http_body, PolynomialDigest, strToBytes, JsonMaskType, jsonTreeHasher, compressTreeHash, modAdd, InitialDigest, MockManifest, http_response_ciphertext_dup } from "../common";
import { test_case, TestCaseManifest } from "./testCase.test";

import { toInput } from "../chacha20/authentication.test";
import { poseidon1 } from "poseidon-lite";
import { DataHasher } from "../common/poseidon";
Expand Down Expand Up @@ -39,9 +41,9 @@ function to_nonce(iv: Uint8Array, seq: number): Uint8Array {
let nonce = new Uint8Array(12);
nonce.fill(0);

for (let i = 0; i < 8; i++) {
nonce[12 - i] = (seq >> (8 * i)) & 0xff;
}
// nonce[4..].copy_from_slice(&seq.to_be_bytes());
const seqBytes = new Uint8Array(new BigUint64Array([BigInt(seq)]).buffer).reverse();
nonce.set(seqBytes, 4);

nonce.forEach((_, i) => {
nonce[i] ^= iv[i];
Expand Down Expand Up @@ -279,4 +281,110 @@ describe("Example NIVC Proof", async () => {
}, ["step_out"]);
assert.deepEqual(json_extraction.step_out, value_digest);
});

it("github example", async () => {

let http_response_plaintext = test_case.plaintext;
let http_response_ciphertext = test_case.ciphertext;
let key = test_case.key;
let iv = test_case.iv;
let manifest = TestCaseManifest();

let http_response_combined = http_response_plaintext[0].concat(http_response_plaintext[1]);
let http_response_padded = http_response_combined.concat(Array(DATA_BYTES - http_response_combined.length).fill(-1));
let http_response1_padded = http_response_plaintext[0].concat(Array(DATA_BYTES - http_response_plaintext[0].length).fill(-1));
let http_response1_0_padded = http_response_plaintext[0].concat(Array(DATA_BYTES - http_response_plaintext[0].length).fill(0));
let http_response2_padded = http_response_plaintext[1].concat(Array(DATA_BYTES - http_response_plaintext[1].length).fill(-1));
let http_response2_0_padded = http_response_plaintext[1].concat(Array(DATA_BYTES - http_response_plaintext[1].length).fill(0));
let ciphertext1_padded = http_response_ciphertext[0].concat(Array(DATA_BYTES - http_response_ciphertext[0].length).fill(-1));
let ciphertext2_padded = http_response_ciphertext[1].concat(Array(DATA_BYTES - http_response_ciphertext[1].length).fill(-1));

const [ciphertext_digest, init_nivc_input] = InitialDigest(manifest, [ciphertext1_padded, ciphertext2_padded], MAX_STACK_HEIGHT);

const counterBits = uintArray32ToBits([1])[0];
const keyIn = toInput(Buffer.from(key));

let nonce1 = to_nonce(Uint8Array.from(iv), 1);
const nonceIn = toInput(Buffer.from(nonce1));
let plaintext_authentication1 = await PlaintextAuthentication.compute({
step_in: init_nivc_input,
plaintext: http_response1_padded,
key: keyIn,
nonce: nonceIn,
counter: counterBits,
plaintext_index_counter: 0,
ciphertext_digest,
}, ["step_out"]);

let pt1Digest = PolynomialDigest(http_response1_0_padded, ciphertext_digest, BigInt(0));
let ct1Digest = DataHasher(ciphertext1_padded);
assert.deepEqual(plaintext_authentication1.step_out, init_nivc_input - ct1Digest + pt1Digest);

let nonce2 = to_nonce(Uint8Array.from(iv), 2);
const nonceIn2 = toInput(Buffer.from(nonce2));
let plaintext_authentication2 = await PlaintextAuthentication.compute({
step_in: plaintext_authentication1.step_out,
plaintext: http_response2_padded,
key: keyIn,
nonce: nonceIn2,
counter: counterBits,
plaintext_index_counter: http_response_plaintext[0].length,
ciphertext_digest,
}, ["step_out"]);

let pt2Digest = PolynomialDigest(http_response2_0_padded, ciphertext_digest, BigInt(http_response_plaintext[0].length));
let ct2Digest = DataHasher(ciphertext2_padded);
assert.deepEqual(plaintext_authentication2.step_out, modAdd(init_nivc_input - ct1Digest - ct2Digest, pt1Digest + pt2Digest));

const http_response_plaintext_digest = PolynomialDigest(http_response_combined, ciphertext_digest, BigInt(0));

// Run HTTPVerification
const start_line_digest = PolynomialDigest(http_start_line, ciphertext_digest, BigInt(0));
let header_0 = test_case.header_0;
const header_0_digest = PolynomialDigest(header_0, ciphertext_digest, BigInt(0));

let main_digests = Array(MAX_NUMBER_OF_HEADERS + 1).fill(0);
main_digests[0] = start_line_digest;
main_digests[1] = header_0_digest;

let step_in = BigInt(plaintext_authentication2.step_out.toString(10));
let http_verification = await HTTPVerification.compute({
step_in,
ciphertext_digest,
data: http_response_padded,
main_digests,
}, ["step_out"]);
console.log("http_verification", http_verification.step_out);
let http_body = http_response_plaintext[1];
const padded_http_body = http_body.concat(Array(DATA_BYTES - http_body.length).fill(0));
let http_verification_step_out = BigInt((http_verification.step_out as number[])[0]);
let body_digest = PolynomialDigest(http_body, ciphertext_digest, BigInt(0));

const body_digest_hashed = poseidon1([body_digest]);
const start_line_digest_digest_hashed = poseidon1([start_line_digest]);
const header_0_digest_hashed = poseidon1([header_0_digest]);
const correct_http_verification_step_out = modAdd(step_in - http_response_plaintext_digest - start_line_digest_digest_hashed - header_0_digest_hashed, body_digest_hashed);
assert.deepEqual(http_verification_step_out, correct_http_verification_step_out);

// Run JSONExtraction
const KEY0 = strToBytes("hello");
const targetValue = strToBytes("world");
const keySequence: JsonMaskType[] = [
{ type: "Object", value: KEY0 },
];

const [stack, treeHashes] = jsonTreeHasher(ciphertext_digest, keySequence, MAX_STACK_HEIGHT);
const sequence_digest = compressTreeHash(ciphertext_digest, [stack, treeHashes]);
const value_digest = PolynomialDigest(targetValue, ciphertext_digest, BigInt(0));

let json_extraction = await JSONExtraction.compute({
step_in: http_verification_step_out,
ciphertext_digest,
data: padded_http_body,
value_digest,
sequence_digest,
}, ["step_out"]);
console.log("json_extraction", json_extraction.step_out);
assert.deepEqual(json_extraction.step_out, value_digest);
});
});
31 changes: 31 additions & 0 deletions circuits/test/full/testCase.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { strToBytes, Manifest, JsonMaskType } from "../common";

export const test_case = {
"plaintext": [[72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 58, 32, 99, 108, 111, 115, 101, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 50, 50, 13, 10, 67, 97, 99, 104, 101, 45, 67, 111, 110, 116, 114, 111, 108, 58, 32, 109, 97, 120, 45, 97, 103, 101, 61, 51, 48, 48, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45, 83, 101, 99, 117, 114, 105, 116, 121, 45, 80, 111, 108, 105, 99, 121, 58, 32, 100, 101, 102, 97, 117, 108, 116, 45, 115, 114, 99, 32, 39, 110, 111, 110, 101, 39, 59, 32, 115, 116, 121, 108, 101, 45, 115, 114, 99, 32, 39, 117, 110, 115, 97, 102, 101, 45, 105, 110, 108, 105, 110, 101, 39, 59, 32, 115, 97, 110, 100, 98, 111, 120, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 116, 102, 45, 56, 13, 10, 69, 84, 97, 103, 58, 32, 34, 101, 48, 101, 54, 53, 49, 48, 99, 49, 102, 99, 49, 51, 98, 51, 97, 54, 51, 97, 99, 98, 99, 48, 54, 49, 53, 101, 101, 48, 55, 97, 52, 57, 53, 50, 56, 55, 51, 97, 56, 100, 97, 55, 55, 48, 50, 55, 100, 48, 48, 52, 49, 50, 102, 99, 99, 102, 49, 97, 53, 99, 101, 50, 57, 34, 13, 10, 83, 116, 114, 105, 99, 116, 45, 84, 114, 97, 110, 115, 112, 111, 114, 116, 45, 83, 101, 99, 117, 114, 105, 116, 121, 58, 32, 109, 97, 120, 45, 97, 103, 101, 61, 51, 49, 53, 51, 54, 48, 48, 48, 13, 10, 88, 45, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 45, 79, 112, 116, 105, 111, 110, 115, 58, 32, 110, 111, 115, 110, 105, 102, 102, 13, 10, 88, 45, 70, 114, 97, 109, 101, 45, 79, 112, 116, 105, 111, 110, 115, 58, 32, 100, 101, 110, 121, 13, 10, 88, 45, 88, 83, 83, 45, 80, 114, 111, 116, 101, 99, 116, 105, 111, 110, 58, 32, 49, 59, 32, 109, 111, 100, 101, 61, 98, 108, 111, 99, 107, 13, 10, 88, 45, 71, 105, 116, 72, 117, 98, 45, 82, 101, 113, 117, 101, 115, 116, 45, 73, 100, 58, 32, 53, 53, 68, 50, 58, 51, 49, 70, 66, 52, 66, 58, 57, 69, 50, 66, 49, 58, 69, 57, 51, 66, 68, 58, 54, 55, 56, 65, 50, 54, 55, 50, 13, 10, 65, 99, 99, 101, 112, 116, 45, 82, 97, 110, 103, 101, 115, 58, 32, 98, 121, 116, 101, 115, 13, 10, 68, 97, 116, 101, 58, 32, 70, 114, 105, 44, 32, 49, 55, 32, 74, 97, 110, 32, 50, 48, 50, 53, 32, 48, 57, 58, 52, 52, 58, 49, 57, 32, 71, 77, 84, 13, 10, 86, 105, 97, 58, 32, 49, 46, 49, 32, 118, 97, 114, 110, 105, 115, 104, 13, 10, 88, 45, 83, 101, 114, 118, 101, 100, 45, 66, 121, 58, 32, 99, 97, 99, 104, 101, 45, 104, 121, 100, 49, 49, 48, 48, 48, 51, 53, 45, 72, 89, 68, 13, 10, 88, 45, 67, 97, 99, 104, 101, 58, 32, 77, 73, 83, 83, 13, 10, 88, 45, 67, 97, 99, 104, 101, 45, 72, 105, 116, 115, 58, 32, 48, 13, 10, 88, 45, 84, 105, 109, 101, 114, 58, 32, 83, 49, 55, 51, 55, 49, 48, 55, 48, 53, 57, 46, 57, 54, 51, 54, 48, 55, 44, 86, 83, 48, 44, 86, 69, 50, 55, 52, 13, 10, 86, 97, 114, 121, 58, 32, 65, 117, 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 44, 65, 99, 99, 101, 112, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 44, 79, 114, 105, 103, 105, 110, 13, 10, 65, 99, 99, 101, 115, 115, 45, 67, 111, 110, 116, 114, 111, 108, 45, 65, 108, 108, 111, 119, 45, 79, 114, 105, 103, 105, 110, 58, 32, 42, 13, 10, 67, 114, 111, 115, 115, 45, 79, 114, 105, 103, 105, 110, 45, 82, 101, 115, 111, 117, 114, 99, 101, 45, 80, 111, 108, 105, 99, 121, 58, 32, 99, 114, 111, 115, 115, 45, 111, 114, 105, 103, 105, 110, 13, 10, 88, 45, 70, 97, 115, 116, 108, 121, 45, 82, 101, 113, 117, 101, 115, 116, 45, 73, 68, 58, 32, 53, 54, 53, 55, 51, 100, 53, 54, 49, 52, 54, 48, 102, 48, 57, 52, 97, 56, 54, 57, 101, 49, 100, 53, 102, 98, 97, 50, 54, 100, 99, 101, 52, 100, 54, 49, 55, 99, 50, 101, 13, 10, 69, 120, 112, 105, 114, 101, 115, 58, 32, 70, 114, 105, 44, 32, 49, 55, 32, 74, 97, 110, 32, 50, 48, 50, 53, 32, 48, 57, 58, 52, 57, 58, 49, 57, 32, 71, 77, 84, 13, 10, 83, 111, 117, 114, 99, 101, 45, 65, 103, 101, 58, 32, 48, 13, 10, 13, 10], [123, 10, 32, 32, 34, 104, 101, 108, 108, 111, 34, 58, 32, 34, 119, 111, 114, 108, 100, 34, 10, 125]],
"ciphertext": [[212, 211, 72, 95, 188, 93, 171, 80, 240, 211, 106, 143, 28, 70, 130, 157, 76, 194, 90, 207, 102, 233, 239, 157, 229, 161, 195, 78, 133, 251, 249, 56, 29, 75, 167, 251, 29, 32, 194, 210, 102, 2, 193, 170, 83, 144, 56, 185, 71, 10, 75, 211, 123, 222, 28, 175, 61, 104, 124, 117, 45, 205, 100, 163, 126, 77, 251, 245, 171, 147, 19, 104, 106, 53, 142, 20, 233, 217, 163, 148, 180, 39, 208, 156, 42, 119, 64, 47, 183, 117, 141, 98, 254, 229, 29, 128, 130, 204, 67, 13, 141, 196, 68, 7, 110, 246, 66, 149, 248, 35, 109, 45, 215, 134, 171, 156, 136, 14, 74, 86, 150, 152, 14, 75, 158, 189, 225, 252, 255, 98, 217, 235, 45, 152, 210, 43, 73, 98, 40, 139, 83, 83, 58, 253, 108, 137, 134, 239, 212, 128, 122, 200, 223, 60, 176, 159, 76, 169, 134, 132, 41, 236, 217, 38, 47, 11, 8, 22, 65, 42, 63, 245, 232, 28, 142, 215, 11, 20, 178, 153, 46, 237, 69, 6, 100, 150, 96, 184, 137, 203, 195, 45, 174, 209, 27, 223, 211, 47, 66, 74, 69, 78, 245, 13, 64, 126, 244, 133, 42, 187, 28, 44, 59, 234, 239, 223, 216, 12, 126, 77, 151, 248, 180, 210, 243, 92, 9, 111, 140, 200, 5, 240, 121, 196, 92, 19, 54, 199, 177, 130, 124, 95, 177, 99, 205, 97, 195, 24, 51, 30, 70, 186, 228, 235, 232, 73, 205, 10, 233, 102, 118, 205, 236, 250, 3, 113, 16, 94, 64, 240, 23, 1, 29, 207, 69, 184, 41, 42, 87, 88, 116, 45, 163, 79, 228, 217, 160, 13, 12, 189, 95, 125, 121, 58, 36, 250, 173, 29, 189, 125, 98, 54, 249, 26, 37, 251, 223, 28, 74, 127, 255, 178, 197, 86, 109, 234, 188, 167, 137, 204, 173, 57, 65, 36, 115, 151, 99, 2, 147, 60, 12, 48, 235, 81, 3, 243, 82, 31, 122, 35, 150, 68, 124, 228, 122, 215, 23, 115, 107, 202, 168, 157, 116, 186, 202, 213, 238, 58, 101, 107, 17, 107, 89, 251, 200, 50, 90, 20, 94, 94, 215, 238, 215, 226, 47, 129, 38, 196, 150, 92, 79, 51, 198, 42, 162, 23, 40, 172, 120, 160, 20, 183, 105, 91, 231, 166, 168, 89, 39, 160, 168, 99, 160, 15, 68, 94, 85, 76, 68, 195, 9, 54, 125, 200, 35, 30, 218, 206, 76, 176, 247, 97, 107, 46, 239, 56, 154, 138, 119, 66, 234, 74, 194, 145, 130, 230, 23, 69, 136, 71, 56, 136, 109, 106, 189, 153, 3, 7, 91, 71, 237, 242, 52, 10, 165, 116, 245, 246, 188, 156, 99, 113, 230, 45, 226, 222, 34, 67, 152, 63, 161, 154, 142, 17, 17, 113, 154, 131, 170, 142, 183, 218, 223, 241, 165, 38, 125, 156, 228, 15, 38, 133, 31, 89, 6, 192, 99, 20, 15, 5, 49, 14, 15, 224, 82, 183, 196, 234, 90, 149, 156, 107, 42, 248, 179, 205, 102, 127, 7, 152, 209, 119, 216, 124, 217, 243, 23, 130, 74, 224, 119, 82, 38, 87, 67, 156, 23, 72, 87, 254, 111, 145, 12, 218, 138, 176, 220, 201, 106, 169, 138, 19, 88, 224, 228, 87, 119, 53, 24, 42, 73, 107, 237, 50, 60, 135, 181, 235, 116, 3, 126, 97, 236, 239, 217, 77, 134, 33, 26, 139, 2, 217, 5, 128, 31, 40, 251, 77, 96, 237, 230, 234, 136, 253, 164, 210, 2, 146, 33, 100, 230, 115, 159, 76, 232, 52, 122, 106, 131, 41, 239, 194, 85, 14, 198, 38, 157, 254, 235, 132, 110, 214, 218, 125, 132, 99, 107, 173, 17, 1, 138, 64, 253, 108, 17, 125, 46, 41, 6, 76, 164, 54, 31, 194, 219, 12, 62, 217, 175, 184, 206, 164, 233, 104, 255, 54, 203, 75, 95, 44, 119, 213, 244, 163, 12, 178, 71, 82, 81, 143, 72, 163, 191, 244, 141, 15, 183, 194, 24, 226, 32, 45, 243, 5, 88, 151, 175, 117, 30, 126, 17, 45, 68, 89, 78, 163, 33, 96, 248, 164, 146, 158, 143, 28, 152, 161, 103, 200, 198, 73, 124, 204, 37, 179, 178, 153, 94, 131, 172, 156, 198, 225, 17, 188, 103, 87, 123, 14, 232, 34, 68, 147, 141, 60, 223, 208, 10, 247, 199, 251, 71, 19, 77, 210, 5, 212, 91, 148, 199, 127, 58, 71, 173, 86, 24, 52, 129, 245, 63, 187, 13, 242, 140, 74, 63, 149, 115, 236, 230, 68, 219, 30, 194, 171, 238, 104, 208, 125, 72, 24, 201, 94, 31, 48, 71, 65, 13, 76, 216, 226, 210, 162, 225, 157, 213, 197, 236, 141, 150, 199, 9, 81, 39, 15, 193, 254, 161, 183, 75, 170, 191, 149, 169, 81, 233, 69, 43, 80, 209, 111, 122, 181, 13, 127, 109, 41, 224, 95, 210, 252, 130, 91, 190, 97, 115, 1, 43, 161, 37, 27, 238, 160, 8, 40, 210, 124, 183, 106, 152, 243, 89, 246, 1, 235, 242, 250, 194, 153, 78, 252, 155, 88, 57, 93, 66, 179, 172, 112, 21, 136, 134, 181, 121, 22, 137, 223, 226, 108, 190, 49, 217, 193, 243, 53, 132, 216, 142, 154, 64, 60, 160, 134], [166, 14, 37, 201, 179, 42, 196, 229, 65, 36, 34, 155, 207, 66, 18, 125, 60, 107, 190, 196, 98, 136]],
"key": [199, 85, 215, 51, 193, 79, 188, 150, 234, 65, 25, 99, 54, 218, 85, 36, 255, 242, 86, 238, 247, 228, 121, 198, 255, 26, 251, 71, 72, 88, 255, 219],
"iv": [168, 108, 222, 57, 204, 45, 63, 152, 117, 106, 59, 112],
"header_0": [67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 116, 102, 45, 56],
}

export function TestCaseManifest(): Manifest {
const headers: Record<string, string[]> = {
"Content-Type": ["text/plain; charset=utf-8"],
};

const jsonSequence: JsonMaskType[] = [
{ type: "Object", value: strToBytes("hello") }
];

return {
response: {
status: "200",
version: "HTTP/1.1",
message: "OK",
headers: headers,
body: {
json: jsonSequence
}
}
};
}

0 comments on commit e83ed0a

Please sign in to comment.