From f6a9735aa7e9e5f3af53f75a38a690706ca49667 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 6 Nov 2024 17:25:43 -0700 Subject: [PATCH 01/19] init aes hashchain --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 71 +++++----------------- circuits/test/utils/hash.test.ts | 21 +++++++ circuits/utils/hash.circom | 7 +++ 3 files changed, 42 insertions(+), 57 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index d0f97ca..30ffecc 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -2,76 +2,33 @@ pragma circom 2.1.9; include "gctr-nivc.circom"; include "../../utils/array.circom"; +include "../../utils/hash.circom"; // Compute AES-GCTR template AESGCTRFOLD(DATA_BYTES) { - // ------------------------------------------------------------------------------------------------------------------ // - // ~~ Set sizes at compile time ~~ assert(DATA_BYTES % 16 == 0); - // Value for accumulating both packed plaintext and ciphertext as well as counter - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; - // ------------------------------------------------------------------------------------------------------------------ // - - + signal input key[16]; signal input iv[12]; signal input aad[16]; + signal input ctr[4]; signal input plainText[16]; - // step_in[0..DATA_BYTES] => accumulate plaintext blocks - // step_in[DATA_BYTES..DATA_BYTES*2] => accumulate ciphertext blocks - // step_in[DATA_BYTES_LEN*2..DATA_BYTES*2+4] => accumulate counter - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; - - - // We extract the number from the 4 byte word counter - component last_counter_bits = BytesToBits(4); - for(var i = 0; i < 4; i ++) { - last_counter_bits.in[i] <== step_in[DATA_BYTES + i]; - } - component last_counter_num = Bits2Num(32); - // pass in reverse order - for (var i = 0; i< 32; i++){ - last_counter_num.in[i] <== last_counter_bits.out[31 - i]; - } - signal index <== last_counter_num.out - 1; - - // folds one block - component aes = AESGCTRFOLDABLE(); - aes.key <== key; - aes.iv <== iv; - aes.aad <== aad; - aes.plainText <== plainText; + signal input step_in[1]; + signal output step_out[1]; - for(var i = 0; i < 4; i++) { - aes.lastCounter[i] <== step_in[DATA_BYTES + i]; - } + component aes = AESGCTRFOLDABLE(); + aes.key <== key; + aes.iv <== iv; + aes.aad <== aad; + aes.plainText <== plainText; + aes.lastCounter <== ctr; - // Write out the plaintext and ciphertext to our accumulation arrays, both at once. - signal textToPack[16][2]; + var packedPlaintext = 0; for(var i = 0 ; i < 16 ; i++) { - textToPack[i][0] <== plainText[i]; - textToPack[i][1] <== aes.cipherText[i]; - } - signal nextPackedChunk[16] <== GenericBytePackArray(16,2)(textToPack); - - signal prevAccumulatedPackedText[DATA_BYTES]; - for(var i = 0 ; i < DATA_BYTES ; i++) { - prevAccumulatedPackedText[i] <== step_in[i]; - } - component nextAccumulatedPackedText = WriteToIndex(DATA_BYTES, 16); - nextAccumulatedPackedText.array_to_write_to <== prevAccumulatedPackedText; - nextAccumulatedPackedText.array_to_write_at_index <== nextPackedChunk; - nextAccumulatedPackedText.index <== index * 16; - - for(var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { - if(i < DATA_BYTES) { - step_out[i] <== nextAccumulatedPackedText.out[i]; - } else { - step_out[i] <== aes.counter[i - DATA_BYTES]; - } + packedPlaintext += plainText[i] * 2**i; } + step_out[0] <== PoseidonChainer()([step_in[0],packedPlaintext]); } diff --git a/circuits/test/utils/hash.test.ts b/circuits/test/utils/hash.test.ts index 1661367..565c127 100644 --- a/circuits/test/utils/hash.test.ts +++ b/circuits/test/utils/hash.test.ts @@ -47,4 +47,25 @@ describe("hash", () => { ); }); }); + + describe("PoseidonChainer", () => { + let circuit: WitnessTester<["in"], ["out"]>; + + before(async () => { + circuit = await circomkit.WitnessTester(`PoseidonChainer`, { + file: "utils/hash", + template: "PoseidonChainer", + }); + console.log("#constraints:", await circuit.getConstraintCount()); + }); + + it("witness: in = [69,420]", async () => { + const input = [69, 420]; + + await circuit.expectPass( + { in: input }, + { out: "1151215739047799093319595745775265667199521703808900505592836422736499172874" } + ); + }); + }); }); \ No newline at end of file diff --git a/circuits/utils/hash.circom b/circuits/utils/hash.circom index e2e1823..6c0c1b5 100644 --- a/circuits/utils/hash.circom +++ b/circuits/utils/hash.circom @@ -57,4 +57,11 @@ template PoseidonModular(numElements) { } out <== _out; +} + +template PoseidonChainer() { + signal input in[2]; + signal output out; + + out <== Poseidon(2)(in); } \ No newline at end of file From 0852d1713892dada45d974106d1148e7e9483f26 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 6 Nov 2024 17:50:40 -0700 Subject: [PATCH 02/19] working AES out --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 5 +- .../test/aes-gcm/nivc/aes-gctr-nivc.test.ts | 83 ++++++++----------- circuits/test/utils/hash.test.ts | 4 +- 3 files changed, 38 insertions(+), 54 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 30ffecc..46804f1 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -4,11 +4,10 @@ include "gctr-nivc.circom"; include "../../utils/array.circom"; include "../../utils/hash.circom"; - // Compute AES-GCTR template AESGCTRFOLD(DATA_BYTES) { assert(DATA_BYTES % 16 == 0); - + signal input key[16]; signal input iv[12]; signal input aad[16]; @@ -27,7 +26,7 @@ template AESGCTRFOLD(DATA_BYTES) { var packedPlaintext = 0; for(var i = 0 ; i < 16 ; i++) { - packedPlaintext += plainText[i] * 2**i; + packedPlaintext += plainText[i] * 2**(8*i); } step_out[0] <== PoseidonChainer()([step_in[0],packedPlaintext]); } diff --git a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts index c80fae5..b517b8e 100644 --- a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts +++ b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts @@ -1,13 +1,22 @@ import { assert } from "chai"; import { WitnessTester } from "circomkit"; import { circomkit } from "../../common"; +import { PoseidonModular } from "../../common/poseidon"; -describe("aes-gctr-nivc", () => { - let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad", "step_in"], ["step_out"]>; +function bytesToBigInt(bytes: number[] | Uint8Array): bigint { + let result = BigInt(0); + + for (let i = 0; i < 16; i++) { + result += BigInt(bytes[i]) * BigInt(2 ** (8 * i)); + } + return result; +} + +describe("aes-gctr-nivc", () => { + let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad", "ctr", "step_in"], ["step_out"]>; const DATA_BYTES_0 = 16; - const TOTAL_BYTES_ACROSS_NIVC_0 = DATA_BYTES_0 + 4; it("all correct for self generated single zero pt block case", async () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { @@ -20,19 +29,13 @@ describe("aes-gctr-nivc", () => { let plainText = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let iv = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let ct = [0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78]; + // let ct = [0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78]; - const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_0).fill(0x00); - counter.forEach((value, index) => { - step_in[DATA_BYTES_0 + index] = value; - }); - - const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, step_in: step_in }, ["step_out"]) + const ctr = [0x00, 0x00, 0x00, 0x01]; + const step_in = 0; - let packed = plainText.map((x, i) => x + (ct[i] * 256)); - let expected = [...packed, 0x00, 0x00, 0x00, 0x02]; - assert.deepEqual(witness.step_out, expected.map(BigInt)); + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, ctr: ctr, step_in: step_in }, ["step_out"]) + assert.deepEqual(witness.step_out, PoseidonModular([step_in, bytesToBigInt(plainText)])); }); it("all correct for self generated single non zero pt block", async () => { @@ -46,33 +49,24 @@ describe("aes-gctr-nivc", () => { let plainText = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let ct = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; + // let ct = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; - const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_0).fill(0x00); - counter.forEach((value, index) => { - step_in[DATA_BYTES_0 + index] = value; - }); + const ctr = [0x00, 0x00, 0x00, 0x01]; + const step_in = 0; - const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, step_in: step_in }, ["step_out"]) - - let packed = plainText.map((x, i) => x + (ct[i] * 256)); - let expected = [...packed, 0x00, 0x00, 0x00, 0x02]; - assert.deepEqual(witness.step_out, expected.map(BigInt)); + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, ctr: ctr, step_in: step_in }, ["step_out"]) + assert.deepEqual(witness.step_out, PoseidonModular([step_in, bytesToBigInt(plainText)])); }); const DATA_BYTES_1 = 32; - const TOTAL_BYTES_ACROSS_NIVC_1 = DATA_BYTES_1 + 4; - - let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; let plainText1 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; let plainText2 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let ct_part1 = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; - let ct_part2 = [0x26, 0x75, 0x65, 0x30, 0x71, 0x3e, 0x4c, 0x06, 0x5a, 0xf1, 0xd3, 0xc4, 0xf5, 0x6e, 0x02, 0x04]; + // let ct_part1 = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; + // let ct_part2 = [0x26, 0x75, 0x65, 0x30, 0x71, 0x3e, 0x4c, 0x06, 0x5a, 0xf1, 0xd3, 0xc4, 0xf5, 0x6e, 0x02, 0x04]; it("all correct for self generated two block case first fold", async () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { @@ -81,17 +75,11 @@ describe("aes-gctr-nivc", () => { params: [DATA_BYTES_1], // input len is 32 bytes }); - const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_1).fill(0x00); - counter.forEach((value, index) => { - step_in[DATA_BYTES_1 + index] = value; - }); - - const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, step_in: step_in }, ["step_out"]) + const ctr = [0x00, 0x00, 0x00, 0x01]; + const step_in = 0; - let packed1 = plainText1.map((x, i) => x + (ct_part1[i] * 256)); - let expected = packed1.concat(zero_block).concat([0x00, 0x00, 0x00, 0x02]); - assert.deepEqual(witness.step_out, expected.map(BigInt)); + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, ctr: ctr, step_in: step_in }, ["step_out"]) + assert.deepEqual(witness.step_out, PoseidonModular([step_in, bytesToBigInt(plainText1)])); }); it("all correct for self generated two block case second fold", async () => { @@ -101,15 +89,12 @@ describe("aes-gctr-nivc", () => { params: [DATA_BYTES_1], // input len is 32 bytes }); - let packed1 = plainText1.map((x, i) => x + (ct_part1[i] * 256)); - let packed2 = plainText2.map((x, i) => x + (ct_part2[i] * 256)); - let step_in = packed1.concat(zero_block).concat([0x00, 0x00, 0x00, 0x02]); - step_in = step_in.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_1 - step_in.length).fill(0)); - - - let expected = packed1.concat(packed2).concat([0x00, 0x00, 0x00, 0x03]); + const ctr_0 = [0x00, 0x00, 0x00, 0x01]; + const ctr_1 = [0x00, 0x00, 0x00, 0x02]; + const step_in_0 = 0; - const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText2, aad: aad, step_in: step_in }, ["step_out"]) - assert.deepEqual(witness.step_out, expected.map(BigInt)); + const witness_0 = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, ctr: ctr_0, step_in: step_in_0 }, ["step_out"]) + const witness_1 = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText2, aad: aad, ctr: ctr_1, step_in: witness_0.step_out }, ["step_out"]) + assert.deepEqual(witness_1.step_out, PoseidonModular([BigInt(witness_0.step_out.toString()), bytesToBigInt(plainText2)])); }); }); \ No newline at end of file diff --git a/circuits/test/utils/hash.test.ts b/circuits/test/utils/hash.test.ts index 565c127..e05222a 100644 --- a/circuits/test/utils/hash.test.ts +++ b/circuits/test/utils/hash.test.ts @@ -61,10 +61,10 @@ describe("hash", () => { it("witness: in = [69,420]", async () => { const input = [69, 420]; - + const hash = PoseidonModular(input); await circuit.expectPass( { in: input }, - { out: "1151215739047799093319595745775265667199521703808900505592836422736499172874" } + { out: hash } ); }); }); From f51f444b9f081c0d93017cca57b443ef4344720b Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 6 Nov 2024 17:51:12 -0700 Subject: [PATCH 03/19] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b993580..f37dbe5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "web-prover-circuits", "description": "ZK Circuits for WebProofs", - "version": "0.3.1", + "version": "0.4.0", "license": "Apache-2.0", "repository": { "type": "git", From 0436408daa1ce53adaefc3a8c657982c45b60517 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 7 Nov 2024 09:14:53 -0700 Subject: [PATCH 04/19] add template `DataHasher` --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 5 +-- .../nivc/parse_and_lock_start_line.circom | 18 ++------ circuits/test/utils/hash.test.ts | 43 +++++++++++++++++++ circuits/utils/hash.circom | 19 ++++++++ 4 files changed, 67 insertions(+), 18 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 46804f1..158a0fc 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -5,9 +5,7 @@ include "../../utils/array.circom"; include "../../utils/hash.circom"; // Compute AES-GCTR -template AESGCTRFOLD(DATA_BYTES) { - assert(DATA_BYTES % 16 == 0); - +template AESGCTRFOLD() { signal input key[16]; signal input iv[12]; signal input aad[16]; @@ -31,3 +29,4 @@ template AESGCTRFOLD(DATA_BYTES) { step_out[0] <== PoseidonChainer()([step_in[0],packedPlaintext]); } +component main { public [step_in] } = AESGCTRFOLD(); \ No newline at end of file diff --git a/circuits/http/nivc/parse_and_lock_start_line.circom b/circuits/http/nivc/parse_and_lock_start_line.circom index 5b00255..fba6931 100644 --- a/circuits/http/nivc/parse_and_lock_start_line.circom +++ b/circuits/http/nivc/parse_and_lock_start_line.circom @@ -7,23 +7,11 @@ include "../../utils/bytes.circom"; // TODO: Note that TOTAL_BYTES will match what we have for AESGCMFOLD step_out // I have not gone through to double check the sizes of everything yet. template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) { - // ------------------------------------------------------------------------------------------------------------------ // - // ~~ Set sizes at compile time ~~ - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // AES ct/pt + ctr - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; + signal input step_in[1]; + signal output step_out[1]; // Get the plaintext - signal packedData[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - packedData[i] <== step_in[i]; - } - component unpackData = UnpackDoubleByteArray(DATA_BYTES); - unpackData.in <== packedData; - signal data[DATA_BYTES] <== unpackData.lower; + signal input data[DATA_BYTES]; signal input beginning[MAX_BEGINNING_LENGTH]; signal input beginning_length; diff --git a/circuits/test/utils/hash.test.ts b/circuits/test/utils/hash.test.ts index e05222a..95e2d80 100644 --- a/circuits/test/utils/hash.test.ts +++ b/circuits/test/utils/hash.test.ts @@ -68,4 +68,47 @@ describe("hash", () => { ); }); }); + + describe("DataHasher", () => { + let circuit: WitnessTester<["in"], ["out"]>; + + before(async () => { + circuit = await circomkit.WitnessTester(`DataHasher`, { + file: "utils/hash", + template: "DataHasher", + params: [16], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + }); + + it("witness: in = [0,...x16]", async () => { + const input = Array(16).fill(0); + const hash = PoseidonModular([0, 0]); + await circuit.expectPass( + { in: input }, + { out: hash } + ); + }); + + it("witness: in = [1,0,...x15]", async () => { + let input = Array(16).fill(0); + input[0] = 1; + const hash = PoseidonModular([0, 1]); + await circuit.expectPass( + { in: input }, + { out: hash } + ); + }); + + it("witness: in = [0,0,...x15,1]", async () => { + let input = Array(16).fill(0); + input[15] = 1; + const hash = PoseidonModular([0, "1329227995784915872903807060280344576"]); + await circuit.expectPass( + { in: input }, + { out: hash } + ); + }); + + }); }); \ No newline at end of file diff --git a/circuits/utils/hash.circom b/circuits/utils/hash.circom index 6c0c1b5..8ff969d 100644 --- a/circuits/utils/hash.circom +++ b/circuits/utils/hash.circom @@ -64,4 +64,23 @@ template PoseidonChainer() { signal output out; out <== Poseidon(2)(in); +} + +template DataHasher(DATA_BYTES) { + assert(DATA_BYTES % 16 == 0); + signal input in[DATA_BYTES]; + signal output out; + + signal hashes[DATA_BYTES \ 16 + 1]; + hashes[0] <== 0; + + for(var i = 0 ; i < DATA_BYTES \ 16 ; i++) { + var packedInput = 0; + for(var j = 0 ; j < 16 ; j++) { + packedInput += in[16 * i + j] * 2**(8*j); + } + hashes[i+1] <== PoseidonChainer()([hashes[i],packedInput]); + } + + out <== hashes[DATA_BYTES \ 16]; } \ No newline at end of file From a2748a586006d9c19cb676fd8ca83c25e35c14fb Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 7 Nov 2024 09:42:51 -0700 Subject: [PATCH 05/19] NIVC through HTTP start line --- circuits.json | 14 ++ circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 2 - .../nivc/parse_and_lock_start_line.circom | 17 +- circuits/test/full/full.test.ts | 156 +++++++++--------- 4 files changed, 97 insertions(+), 92 deletions(-) diff --git a/circuits.json b/circuits.json index 3ae4177..f68813b 100644 --- a/circuits.json +++ b/circuits.json @@ -212,5 +212,19 @@ 12, 16 ] + }, + "nivc_aes": { + "file": "aes-gcm/nivc/aes-gctr-nivc", + "template": "AESGCTRFOLD" + }, + "nivc_start_line": { + "file": "http/nivc/parse_and_lock_start_line", + "template": "ParseAndLockStartLine", + "params": [ + 1024, + 50, + 200, + 50 + ] } } \ No newline at end of file diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 158a0fc..22ed2cb 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -28,5 +28,3 @@ template AESGCTRFOLD() { } step_out[0] <== PoseidonChainer()([step_in[0],packedPlaintext]); } - -component main { public [step_in] } = AESGCTRFOLD(); \ No newline at end of file diff --git a/circuits/http/nivc/parse_and_lock_start_line.circom b/circuits/http/nivc/parse_and_lock_start_line.circom index fba6931..21e1b6e 100644 --- a/circuits/http/nivc/parse_and_lock_start_line.circom +++ b/circuits/http/nivc/parse_and_lock_start_line.circom @@ -10,8 +10,11 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG signal input step_in[1]; signal output step_out[1]; - // Get the plaintext + // Authenticate the plaintext we are passing in signal input data[DATA_BYTES]; + signal dataHash <== DataHasher(DATA_BYTES)(data); + dataHash === step_in[0]; + step_out[0] <== step_in[0]; signal input beginning[MAX_BEGINNING_LENGTH]; signal input beginning_length; @@ -85,15 +88,5 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG finalMatch === 1; // -2 here for the CRLF final_length === final_end_counter - middle_end_counter - 2; - - // ------------------------------------------------------------------------------------------------------------------ // - // write out the pt again - for (var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { - // add plaintext http input to step_out and ignore the ciphertext - if(i < DATA_BYTES) { - step_out[i] <== data[i]; // PASS OUT JUST THE PLAINTEXT DATA - } else { - step_out[i] <== 0; - } - } } + diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index d657774..fbb1c8f 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -38,18 +38,18 @@ let http_response_plaintext = [ 10, 32, 32, 32, 125, 13, 10, 125]; describe("NIVC_FULL", async () => { - let aesCircuit: WitnessTester<["key", "iv", "plainText", "aad", "step_in"], ["step_out"]>; - let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; - let lockHeaderCircuit: WitnessTester<["step_in", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; - let bodyMaskCircuit: WitnessTester<["step_in"], ["step_out"]>; - let parse_circuit: WitnessTester<["step_in"], ["step_out"]>; - let json_mask_object_circuit: WitnessTester<["step_in", "key", "keyLen"], ["step_out"]>; - let json_mask_arr_circuit: WitnessTester<["step_in", "index"], ["step_out"]>; - let extract_value_circuit: WitnessTester<["step_in"], ["step_out"]>; + let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; + let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; + // let lockHeaderCircuit: WitnessTester<["step_in", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; + // let bodyMaskCircuit: WitnessTester<["step_in"], ["step_out"]>; + // let parse_circuit: WitnessTester<["step_in"], ["step_out"]>; + // let json_mask_object_circuit: WitnessTester<["step_in", "key", "keyLen"], ["step_out"]>; + // let json_mask_arr_circuit: WitnessTester<["step_in", "index"], ["step_out"]>; + // let extract_value_circuit: WitnessTester<["step_in"], ["step_out"]>; const DATA_BYTES = 320; const MAX_STACK_HEIGHT = 5; - const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; + const TOTAL_BYTES_ACROSS_NIVC = 1; const MAX_HEADER_NAME_LENGTH = 20; const MAX_HEADER_VALUE_LENGTH = 35; @@ -68,9 +68,9 @@ describe("NIVC_FULL", async () => { aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [DATA_BYTES], }); console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); + httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { file: "http/nivc/parse_and_lock_start_line", template: "ParseAndLockStartLine", @@ -78,40 +78,40 @@ describe("NIVC_FULL", async () => { }); console.log("#constraints (HTTP-PARSE-AND-LOCK-START-LINE):", await httpParseAndLockStartLineCircuit.getConstraintCount()); - lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { - file: "http/nivc/lock_header", - template: "LockHeader", - params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], - }); - console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); - - bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { - file: "http/nivc/body_mask", - template: "HTTPMaskBodyNIVC", - params: [DATA_BYTES], - }); - console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); - - json_mask_arr_circuit = await circomkit.WitnessTester(`JsonMaskArrayIndexNIVC`, { - file: "json/nivc/masker", - template: "JsonMaskArrayIndexNIVC", - params: [DATA_BYTES, MAX_STACK_HEIGHT], - }); - console.log("#constraints (JSON-MASK-ARRAY-INDEX):", await json_mask_arr_circuit.getConstraintCount()); - - json_mask_object_circuit = await circomkit.WitnessTester(`JsonMaskObjectNIVC`, { - file: "json/nivc/masker", - template: "JsonMaskObjectNIVC", - params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH], - }); - console.log("#constraints (JSON-MASK-OBJECT):", await json_mask_object_circuit.getConstraintCount()); - - extract_value_circuit = await circomkit.WitnessTester(`JsonMaskExtractFinal`, { - file: "json/nivc/extractor", - template: "MaskExtractFinal", - params: [DATA_BYTES, MAX_VALUE_LENGTH], - }); - console.log("#constraints (JSON-MASK-EXTRACT-FINAL):", await extract_value_circuit.getConstraintCount()); + // lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { + // file: "http/nivc/lock_header", + // template: "LockHeader", + // params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], + // }); + // console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); + + // bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { + // file: "http/nivc/body_mask", + // template: "HTTPMaskBodyNIVC", + // params: [DATA_BYTES], + // }); + // console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); + + // json_mask_arr_circuit = await circomkit.WitnessTester(`JsonMaskArrayIndexNIVC`, { + // file: "json/nivc/masker", + // template: "JsonMaskArrayIndexNIVC", + // params: [DATA_BYTES, MAX_STACK_HEIGHT], + // }); + // console.log("#constraints (JSON-MASK-ARRAY-INDEX):", await json_mask_arr_circuit.getConstraintCount()); + + // json_mask_object_circuit = await circomkit.WitnessTester(`JsonMaskObjectNIVC`, { + // file: "json/nivc/masker", + // template: "JsonMaskObjectNIVC", + // params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH], + // }); + // console.log("#constraints (JSON-MASK-OBJECT):", await json_mask_object_circuit.getConstraintCount()); + + // extract_value_circuit = await circomkit.WitnessTester(`JsonMaskExtractFinal`, { + // file: "json/nivc/extractor", + // template: "MaskExtractFinal", + // params: [DATA_BYTES, MAX_VALUE_LENGTH], + // }); + // console.log("#constraints (JSON-MASK-EXTRACT-FINAL):", await extract_value_circuit.getConstraintCount()); }); @@ -129,54 +129,54 @@ describe("NIVC_FULL", async () => { // console.log("DATA_BYTES", DATA_BYTES); // Run the 0th chunk of plaintext - const counter = [0x00, 0x00, 0x00, 0x01]; - const init_nivc_input = new Array(TOTAL_BYTES_ACROSS_NIVC).fill(0x00); - counter.forEach((value, index) => { - init_nivc_input[DATA_BYTES + index] = value; - }); + let ctr = [0x00, 0x00, 0x00, 0x01]; + const init_nivc_input = 0; + let pt = http_response_plaintext.slice(0, 16); - aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); - for (let i = 1; i < (DATA_BYTES / 16); i++) { + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); + let i = 0; + console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); + for (i = 1; i < (DATA_BYTES / 16); i++) { + ctr[3] += 1; // This will work since we don't run a test that overlows a byte let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); + console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); } - let out = aes_gcm.step_out as number[]; - let extendedJsonInput = out.slice(0, DATA_BYTES).concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - http_response_plaintext.length)).fill(0)); - let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedJsonInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + // let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); - let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out }, ["step_out"]); + // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out }, ["step_out"]); - let bodyMaskOut = bodyMask.step_out as number[]; - let idx = bodyMaskOut.indexOf('{'.charCodeAt(0)); + // let bodyMaskOut = bodyMask.step_out as number[]; + // let idx = bodyMaskOut.indexOf('{'.charCodeAt(0)); - let maskedInput = extendedJsonInput.fill(0, 0, idx); - maskedInput = maskedInput.fill(0, 320); + // let maskedInput = extendedJsonInput.fill(0, 0, idx); + // maskedInput = maskedInput.fill(0, 320); - let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data" - let key0Len = 4; - let key1 = [105, 116, 101, 109, 115, 0, 0, 0]; // "items" - let key1Len = 5; - let key2 = [112, 114, 111, 102, 105, 108, 101, 0]; // "profile" - let key2Len = 7; - let key3 = [110, 97, 109, 101, 0, 0, 0, 0]; // "name" - let key3Len = 4; + // let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data" + // let key0Len = 4; + // let key1 = [105, 116, 101, 109, 115, 0, 0, 0]; // "items" + // let key1Len = 5; + // let key2 = [112, 114, 111, 102, 105, 108, 101, 0]; // "profile" + // let key2Len = 7; + // let key3 = [110, 97, 109, 101, 0, 0, 0, 0]; // "name" + // let key3Len = 4; - let value = toByte("\"Taylor Swift\""); + // let value = toByte("\"Taylor Swift\""); - let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: bodyMaskOut, key: key0, keyLen: key0Len }, ["step_out"]); + // let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: bodyMaskOut, key: key0, keyLen: key0Len }, ["step_out"]); - let json_num = json_extract_key0.step_out as number[]; - console.log("json_extract_key0", json_num); - let json_extract_key1 = await json_mask_object_circuit.compute({ step_in: json_extract_key0.step_out, key: key1, keyLen: key1Len }, ["step_out"]); + // let json_num = json_extract_key0.step_out as number[]; + // console.log("json_extract_key0", json_num); + // let json_extract_key1 = await json_mask_object_circuit.compute({ step_in: json_extract_key0.step_out, key: key1, keyLen: key1Len }, ["step_out"]); - let json_extract_arr = await json_mask_arr_circuit.compute({ step_in: json_extract_key1.step_out, index: 0 }, ["step_out"]); + // let json_extract_arr = await json_mask_arr_circuit.compute({ step_in: json_extract_key1.step_out, index: 0 }, ["step_out"]); - let json_extract_key2 = await json_mask_object_circuit.compute({ step_in: json_extract_arr.step_out, key: key2, keyLen: key2Len }, ["step_out"]); + // let json_extract_key2 = await json_mask_object_circuit.compute({ step_in: json_extract_arr.step_out, key: key2, keyLen: key2Len }, ["step_out"]); - let json_extract_key3 = await json_mask_object_circuit.compute({ step_in: json_extract_key2.step_out, key: key3, keyLen: key3Len }, ["step_out"]); + // let json_extract_key3 = await json_mask_object_circuit.compute({ step_in: json_extract_key2.step_out, key: key3, keyLen: key3Len }, ["step_out"]); - await extract_value_circuit.expectPass({ step_in: json_extract_key3.step_out }, { step_out: value }); + // await extract_value_circuit.expectPass({ step_in: json_extract_key3.step_out }, { step_out: value }); }); }); \ No newline at end of file From dfdb74f8ff0eab152c1f0a853d80f2e5e0d578d5 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 7 Nov 2024 10:20:31 -0700 Subject: [PATCH 06/19] reduce http start line --- .../nivc/parse_and_lock_start_line.circom | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/circuits/http/nivc/parse_and_lock_start_line.circom b/circuits/http/nivc/parse_and_lock_start_line.circom index 21e1b6e..cae4f0a 100644 --- a/circuits/http/nivc/parse_and_lock_start_line.circom +++ b/circuits/http/nivc/parse_and_lock_start_line.circom @@ -4,9 +4,10 @@ include "../parser/machine.circom"; include "../interpreter.circom"; include "../../utils/bytes.circom"; -// TODO: Note that TOTAL_BYTES will match what we have for AESGCMFOLD step_out -// I have not gone through to double check the sizes of everything yet. template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) { + var MINIMUM_PARSE_LENGTH = MAX_BEGINNING_LENGTH + MAX_MIDDLE_LENGTH + MAX_FINAL_LENGTH; + assert(DATA_BYTES >= MINIMUM_PARSE_LENGTH); + signal input step_in[1]; signal output step_out[1]; @@ -16,6 +17,11 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG dataHash === step_in[0]; step_out[0] <== step_in[0]; + signal dataToParse[MINIMUM_PARSE_LENGTH]; + for(var i = 0 ; i < MINIMUM_PARSE_LENGTH ; i++) { + dataToParse[i] <== data[i]; + } + signal input beginning[MAX_BEGINNING_LENGTH]; signal input beginning_length; signal input middle[MAX_MIDDLE_LENGTH]; @@ -23,10 +29,11 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG signal input final[MAX_FINAL_LENGTH]; signal input final_length; - // Initialze the parser - component State[DATA_BYTES]; + // Initialze the parser, note that we only need to parse as much as the `MINIMUM_PARSE_LENGTH` + // since the start line could not possibly go past this point, or else this would fail anyway + component State[MINIMUM_PARSE_LENGTH]; State[0] = HttpStateUpdate(); - State[0].byte <== data[0]; + State[0].byte <== dataToParse[0]; State[0].parsing_start <== 1; State[0].parsing_header <== 0; State[0].parsing_field_name <== 0; @@ -41,9 +48,9 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG */ // Setup to check middle bytes - signal startLineMask[DATA_BYTES]; - signal middleMask[DATA_BYTES]; - signal finalMask[DATA_BYTES]; + signal startLineMask[MINIMUM_PARSE_LENGTH]; + signal middleMask[MINIMUM_PARSE_LENGTH]; + signal finalMask[MINIMUM_PARSE_LENGTH]; startLineMask[0] <== inStartLine()(State[0].parsing_start); middleMask[0] <== inStartMiddle()(State[0].parsing_start); finalMask[0] <== inStartEnd()(State[0].parsing_start); @@ -52,9 +59,9 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG var middle_start_counter = 1; var middle_end_counter = 1; var final_end_counter = 1; - for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) { + for(var data_idx = 1; data_idx < MINIMUM_PARSE_LENGTH; data_idx++) { State[data_idx] = HttpStateUpdate(); - State[data_idx].byte <== data[data_idx]; + State[data_idx].byte <== dataToParse[data_idx]; State[data_idx].parsing_start <== State[data_idx - 1].next_parsing_start; State[data_idx].parsing_header <== State[data_idx - 1].next_parsing_header; State[data_idx].parsing_field_name <== State[data_idx - 1].next_parsing_field_name; @@ -76,15 +83,15 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG // Additionally verify beginning had correct length beginning_length === middle_start_counter - 1; - signal beginningMatch <== SubstringMatchWithIndexPadded(DATA_BYTES, MAX_BEGINNING_LENGTH)(data, beginning, beginning_length, 0); + signal beginningMatch <== SubstringMatchWithIndexPadded(MINIMUM_PARSE_LENGTH, MAX_BEGINNING_LENGTH)(dataToParse, beginning, beginning_length, 0); // Check middle is correct by substring match and length check - signal middleMatch <== SubstringMatchWithIndexPadded(DATA_BYTES, MAX_MIDDLE_LENGTH)(data, middle, middle_length, middle_start_counter); + signal middleMatch <== SubstringMatchWithIndexPadded(MINIMUM_PARSE_LENGTH, MAX_MIDDLE_LENGTH)(dataToParse, middle, middle_length, middle_start_counter); middleMatch === 1; middle_length === middle_end_counter - middle_start_counter - 1; // Check final is correct by substring match and length check - signal finalMatch <== SubstringMatchWithIndexPadded(DATA_BYTES, MAX_FINAL_LENGTH)(data, final, final_length, middle_end_counter); + signal finalMatch <== SubstringMatchWithIndexPadded(MINIMUM_PARSE_LENGTH, MAX_FINAL_LENGTH)(dataToParse, final, final_length, middle_end_counter); finalMatch === 1; // -2 here for the CRLF final_length === final_end_counter - middle_end_counter - 2; From 51d13fc5ae646bf208f37a09541deb8371216485 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 7 Nov 2024 11:15:54 -0700 Subject: [PATCH 07/19] broken circomkit i'm so mad --- circuits.json | 9 +++ circuits/http/nivc/lock_header.circom | 37 ++++----- .../nivc/parse_and_lock_start_line.circom | 4 +- circuits/test/full/full.test.ts | 79 +++++++++++-------- 4 files changed, 73 insertions(+), 56 deletions(-) diff --git a/circuits.json b/circuits.json index f68813b..ac56ffb 100644 --- a/circuits.json +++ b/circuits.json @@ -226,5 +226,14 @@ 200, 50 ] + }, + "nivc_lock_header": { + "file": "http/nivc/lock_header", + "template": "LockHeader", + "params": [ + 1024, + 50, + 100 + ] } } \ No newline at end of file diff --git a/circuits/http/nivc/lock_header.circom b/circuits/http/nivc/lock_header.circom index 29c31e5..8575cbb 100644 --- a/circuits/http/nivc/lock_header.circom +++ b/circuits/http/nivc/lock_header.circom @@ -4,22 +4,21 @@ include "../parser/machine.circom"; include "../interpreter.circom"; include "../../utils/array.circom"; include "circomlib/circuits/comparators.circom"; +include "@zk-email/circuits/utils/array.circom"; // TODO: should use a MAX_HEADER_NAME_LENGTH and a MAX_HEADER_VALUE_LENGTH template LockHeader(DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) { - // ------------------------------------------------------------------------------------------------------------------ // - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes pt/ct + ctr - // ------------------------------------------------------------------------------------------------------------------ // - // ------------------------------------------------------------------------------------------------------------------ // - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; + assert(DATA_BYTES >= MAX_HEADER_NAME_LENGTH + MAX_HEADER_VALUE_LENGTH); - // get the plaintext - signal data[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - } + signal input step_in[1]; + signal output step_out[1]; + + // Authenticate the plaintext we are passing in + signal input data[DATA_BYTES]; + signal dataHash <== DataHasher(DATA_BYTES)(data); + dataHash === step_in[0]; + step_out[0] <== step_in[0]; // ------------------------------------------------------------------------------------------------------------------ // // PARSE @@ -74,7 +73,11 @@ template LockHeader(DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) // find header location signal headerNameLocation <== FirstStringMatch(DATA_BYTES, MAX_HEADER_NAME_LENGTH)(data, header); + // TODO (autoparallel): This could probably be optimized by selecting a subarray of length `MAX_HEADER_NAME_LENGTH + MAX_HEADER_VALUE_LENGTH` at `headerNameLocation` // This is the assertion that we have locked down the correct header + + // signal dataSubArray[MAX_HEADER_NAME_LENGTH + MAX_HEADER_VALUE_LENGTH] <== SelectSubArray(DATA_BYTES, MAX_HEADER_NAME_LENGTH + MAX_HEADER_VALUE_LENGTH)(data, headerNameLocation, MAX_HEADER_NAME_LENGTH + MAX_HEADER_VALUE_LENGTH); + // signal headerFieldNameValueMatch <== HeaderFieldNameValueMatchPadded(MAX_HEADER_NAME_LENGTH + MAX_HEADER_VALUE_LENGTH, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH)(dataSubArray, header, headerNameLength, value, headerValueLength, headerNameLocation); signal headerFieldNameValueMatch <== HeaderFieldNameValueMatchPadded(DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH)(data, header, headerNameLength, value, headerValueLength, headerNameLocation); headerFieldNameValueMatch === 1; @@ -82,18 +85,6 @@ template LockHeader(DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) signal isParsingHeader <== IndexSelector(DATA_BYTES * 5)(httpParserState, headerNameLocation * 5 + 1); signal parsingHeader <== GreaterThan(10)([isParsingHeader, 0]); parsingHeader === 1; - - // ------------------------------------------------------------------------------------------------------------------ // - // write out the pt again - for (var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { - // add plaintext http input to step_out and ignore the ciphertext - if(i < DATA_BYTES) { - step_out[i] <== step_in[i]; - } else { - step_out[i] <== 0; - } - } - } // TODO: Handrolled template that I haven't tested YOLO. diff --git a/circuits/http/nivc/parse_and_lock_start_line.circom b/circuits/http/nivc/parse_and_lock_start_line.circom index cae4f0a..1e4021c 100644 --- a/circuits/http/nivc/parse_and_lock_start_line.circom +++ b/circuits/http/nivc/parse_and_lock_start_line.circom @@ -10,13 +10,15 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG signal input step_in[1]; signal output step_out[1]; - + log("step_in: ", step_in[0]); // Authenticate the plaintext we are passing in signal input data[DATA_BYTES]; signal dataHash <== DataHasher(DATA_BYTES)(data); dataHash === step_in[0]; step_out[0] <== step_in[0]; + log("step_out: ", step_out[0]); + signal dataToParse[MINIMUM_PARSE_LENGTH]; for(var i = 0 ; i < MINIMUM_PARSE_LENGTH ; i++) { dataToParse[i] <== data[i]; diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index fbb1c8f..07952c2 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -40,7 +40,7 @@ let http_response_plaintext = [ describe("NIVC_FULL", async () => { let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; - // let lockHeaderCircuit: WitnessTester<["step_in", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; + let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; // let bodyMaskCircuit: WitnessTester<["step_in"], ["step_out"]>; // let parse_circuit: WitnessTester<["step_in"], ["step_out"]>; // let json_mask_object_circuit: WitnessTester<["step_in", "key", "keyLen"], ["step_out"]>; @@ -65,11 +65,11 @@ describe("NIVC_FULL", async () => { const MAX_VALUE_LENGTH = 35; before(async () => { - aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { - file: "aes-gcm/nivc/aes-gctr-nivc", - template: "AESGCTRFOLD", - }); - console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); + // aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { + // file: "aes-gcm/nivc/aes-gctr-nivc", + // template: "AESGCTRFOLD", + // }); + // console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { file: "http/nivc/parse_and_lock_start_line", @@ -78,12 +78,12 @@ describe("NIVC_FULL", async () => { }); console.log("#constraints (HTTP-PARSE-AND-LOCK-START-LINE):", await httpParseAndLockStartLineCircuit.getConstraintCount()); - // lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { - // file: "http/nivc/lock_header", - // template: "LockHeader", - // params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], - // }); - // console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); + lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { + file: "http/nivc/lock_header", + template: "LockHeader", + params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], + }); + console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); // bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { // file: "http/nivc/body_mask", @@ -124,27 +124,42 @@ describe("NIVC_FULL", async () => { let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); it("NIVC_CHAIN", async () => { - // fold 16 bytes at a time - let aes_gcm: CircuitSignals = { step_out: [] }; - // console.log("DATA_BYTES", DATA_BYTES); - // Run the 0th chunk of plaintext - let ctr = [0x00, 0x00, 0x00, 0x01]; - const init_nivc_input = 0; - - let pt = http_response_plaintext.slice(0, 16); - aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); - let i = 0; - console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); - for (i = 1; i < (DATA_BYTES / 16); i++) { - ctr[3] += 1; // This will work since we don't run a test that overlows a byte - let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); - console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); - } - let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - - // let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + // let ctr = [0x00, 0x00, 0x00, 0x01]; + // const init_nivc_input = 0; + + // let pt = http_response_plaintext.slice(0, 16); + // let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); + // let i = 0; + // console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); + // for (i = 1; i < (DATA_BYTES / 16); i++) { + // ctr[3] += 1; // This will work since we don't run a test that overlows a byte + // let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); + // aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); + // console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); + // } + // temp + let temp_step_in = [BigInt("2195365663909569734943279727560535141179588918483111718403427949138562480675")]; + + // console.log(temp_step_in); + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: temp_step_in, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + // let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + // let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.calculateWitness + // ({ step_in: temp_step_in, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }); + // console.log(parseAndLockStartLine.entries); + // const entriesArray = Array.from(parseAndLockStartLine.entries()); + // entriesArray.slice(0, 20).forEach(([index, value]) => { + // console.log(`Index ${index}: ${value.toString()}`); + // }); + // console.log(await httpParseAndLockStartLineCircuit.readWitnessSignals(parseAndLockStartLine, ["step_in"])); + // readWitnessSignals(witness: Readonly, signals: string[] | OUT): Promise; + // console.log("Start Line step_out: ", parseAndLockStartLine); + // let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + // let lockHeader = await lockHeaderCircuit.compute({ + // step_in: temp_step_in, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length + // }, ["step_out"]); + + // console.log("Lock Header step_out: ", lockHeader.step_out); // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out }, ["step_out"]); From 94257f018f90850db6c4d4a8cbb80b1ebb10088f Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 7 Nov 2024 13:03:07 -0700 Subject: [PATCH 08/19] through HTTP --- circuits.json | 7 + circuits/http/nivc/body_mask.circom | 39 ++--- circuits/http/nivc/lock_header.circom | 4 +- .../nivc/parse_and_lock_start_line.circom | 8 +- circuits/test/full/full.test.ts | 147 +++++++++++------- 5 files changed, 123 insertions(+), 82 deletions(-) diff --git a/circuits.json b/circuits.json index ac56ffb..76242d2 100644 --- a/circuits.json +++ b/circuits.json @@ -235,5 +235,12 @@ 50, 100 ] + }, + "nivc_body_mask": { + "file": "http/nivc/body_mask", + "template": "HTTPMaskBodyNIVC", + "params": [ + 1024 + ] } } \ No newline at end of file diff --git a/circuits/http/nivc/body_mask.circom b/circuits/http/nivc/body_mask.circom index 1e53c34..5a78b1a 100644 --- a/circuits/http/nivc/body_mask.circom +++ b/circuits/http/nivc/body_mask.circom @@ -1,24 +1,16 @@ pragma circom 2.1.9; include "../parser/machine.circom"; +include "../../utils/hash.circom"; template HTTPMaskBodyNIVC(DATA_BYTES) { - // ------------------------------------------------------------------------------------------------------------------ // - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes ct/pt + ctr - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Unravel from previous NIVC step ~ - // Read in from previous NIVC step (HttpParseAndLockStartLine or HTTPLockHeader) - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; - - signal data[DATA_BYTES]; - // signal parsing_body[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - // parsing_body[i] <== step_in[DATA_BYTES + i * 5 + 4]; // `parsing_body` stored in every 5th slot of step_in/out - } + signal input step_in[1]; + signal output step_out[1]; + + // Authenticate the plaintext we are passing in + signal input data[DATA_BYTES]; + signal data_hash <== DataHasher(DATA_BYTES)(data); + data_hash === step_in[0]; // ------------------------------------------------------------------------------------------------------------------ // // PARSE @@ -46,13 +38,14 @@ template HTTPMaskBodyNIVC(DATA_BYTES) { // ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ // - // ~ Write out to next NIVC step - for (var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { - if(i < DATA_BYTES) { - step_out[i] <== data[i] * State[i].next_parsing_body; - } else { - step_out[i] <== 0; - } + // Mask out just the JSON body + signal bodyMasked[DATA_BYTES]; + for (var i = 0 ; i < DATA_BYTES ; i++) { + bodyMasked[i] <== data[i] * State[i].next_parsing_body; } + + // Hash the new data so this can now be used in the chain later + signal body_mask_hash <== DataHasher(DATA_BYTES)(bodyMasked); + step_out[0] <== body_mask_hash; } diff --git a/circuits/http/nivc/lock_header.circom b/circuits/http/nivc/lock_header.circom index 8575cbb..2cb109e 100644 --- a/circuits/http/nivc/lock_header.circom +++ b/circuits/http/nivc/lock_header.circom @@ -16,8 +16,8 @@ template LockHeader(DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) // Authenticate the plaintext we are passing in signal input data[DATA_BYTES]; - signal dataHash <== DataHasher(DATA_BYTES)(data); - dataHash === step_in[0]; + signal data_hash <== DataHasher(DATA_BYTES)(data); + data_hash === step_in[0]; step_out[0] <== step_in[0]; // ------------------------------------------------------------------------------------------------------------------ // diff --git a/circuits/http/nivc/parse_and_lock_start_line.circom b/circuits/http/nivc/parse_and_lock_start_line.circom index 1e4021c..32cc4ec 100644 --- a/circuits/http/nivc/parse_and_lock_start_line.circom +++ b/circuits/http/nivc/parse_and_lock_start_line.circom @@ -10,15 +10,13 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG signal input step_in[1]; signal output step_out[1]; - log("step_in: ", step_in[0]); + // Authenticate the plaintext we are passing in signal input data[DATA_BYTES]; - signal dataHash <== DataHasher(DATA_BYTES)(data); - dataHash === step_in[0]; + signal data_hash <== DataHasher(DATA_BYTES)(data); + data_hash === step_in[0]; step_out[0] <== step_in[0]; - log("step_out: ", step_out[0]); - signal dataToParse[MINIMUM_PARSE_LENGTH]; for(var i = 0 ; i < MINIMUM_PARSE_LENGTH ; i++) { dataToParse[i] <== data[i]; diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 07952c2..13d51aa 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -1,5 +1,29 @@ -import { CircuitSignals } from "circomkit"; +import { assert } from "chai"; import { circomkit, WitnessTester, toByte } from "../common"; +import { PoseidonModular } from "../common/poseidon"; + +function dataHasher(input: number[]): bigint { + if (input.length % 16 !== 0) { + throw new Error("DATA_BYTES must be divisible by 16"); + } + + let hashes: bigint[] = [BigInt(0)]; // Initialize first hash as 0 + + for (let i = 0; i < Math.floor(input.length / 16); i++) { + let packedInput = BigInt(0); + + // Pack 16 bytes into a single number + for (let j = 0; j < 16; j++) { + packedInput += BigInt(input[16 * i + j]) * BigInt(2 ** (8 * j)); + } + + // Compute next hash using previous hash and packed input + hashes.push(PoseidonModular([hashes[i], packedInput])); + } + + // Return the last hash + return hashes[Math.floor(input.length / 16)]; +} // HTTP/1.1 200 OK // content-type: application/json; charset=utf-8 @@ -20,7 +44,7 @@ import { circomkit, WitnessTester, toByte } from "../common"; // } // 320 bytes in the HTTP response -let http_response_plaintext = [ +const http_response_plaintext = [ 72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 106, 115, 111, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 116, 102, 45, 56, 13, 10, 99, @@ -37,11 +61,39 @@ let http_response_plaintext = [ 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; +const http_body = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 123, 13, 10, 32, 32, 32, + 34, 100, 97, 116, 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, + 32, 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, 91, 13, 10, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, + 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, 111, 102, 105, 108, + 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, + 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, + 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125] +const lengthDiff = http_response_plaintext.length - http_body.length; + +// Create an array of zeros with the length difference +const padding = new Array(lengthDiff).fill(0); + +// Concatenate the padding with http_body +const padded_http_body = [...padding, ...http_body]; + +const http_response_hash = dataHasher(http_response_plaintext); +const http_body_mask_hash = dataHasher(padded_http_body); + describe("NIVC_FULL", async () => { let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; - // let bodyMaskCircuit: WitnessTester<["step_in"], ["step_out"]>; + let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; // let parse_circuit: WitnessTester<["step_in"], ["step_out"]>; // let json_mask_object_circuit: WitnessTester<["step_in", "key", "keyLen"], ["step_out"]>; // let json_mask_arr_circuit: WitnessTester<["step_in", "index"], ["step_out"]>; @@ -65,11 +117,11 @@ describe("NIVC_FULL", async () => { const MAX_VALUE_LENGTH = 35; before(async () => { - // aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { - // file: "aes-gcm/nivc/aes-gctr-nivc", - // template: "AESGCTRFOLD", - // }); - // console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); + aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { + file: "aes-gcm/nivc/aes-gctr-nivc", + template: "AESGCTRFOLD", + }); + console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { file: "http/nivc/parse_and_lock_start_line", @@ -85,12 +137,12 @@ describe("NIVC_FULL", async () => { }); console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); - // bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { - // file: "http/nivc/body_mask", - // template: "HTTPMaskBodyNIVC", - // params: [DATA_BYTES], - // }); - // console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); + bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { + file: "http/nivc/body_mask", + template: "HTTPMaskBodyNIVC", + params: [DATA_BYTES], + }); + console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); // json_mask_arr_circuit = await circomkit.WitnessTester(`JsonMaskArrayIndexNIVC`, { // file: "json/nivc/masker", @@ -124,44 +176,35 @@ describe("NIVC_FULL", async () => { let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); it("NIVC_CHAIN", async () => { - // Run the 0th chunk of plaintext - // let ctr = [0x00, 0x00, 0x00, 0x01]; - // const init_nivc_input = 0; - - // let pt = http_response_plaintext.slice(0, 16); - // let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); - // let i = 0; - // console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); - // for (i = 1; i < (DATA_BYTES / 16); i++) { - // ctr[3] += 1; // This will work since we don't run a test that overlows a byte - // let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - // aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); - // console.log("AES step_out[", i, "]: ", i, aes_gcm.step_out); - // } - // temp - let temp_step_in = [BigInt("2195365663909569734943279727560535141179588918483111718403427949138562480675")]; - - // console.log(temp_step_in); - let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: temp_step_in, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - // let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - // let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.calculateWitness - // ({ step_in: temp_step_in, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }); - // console.log(parseAndLockStartLine.entries); - // const entriesArray = Array.from(parseAndLockStartLine.entries()); - // entriesArray.slice(0, 20).forEach(([index, value]) => { - // console.log(`Index ${index}: ${value.toString()}`); - // }); - // console.log(await httpParseAndLockStartLineCircuit.readWitnessSignals(parseAndLockStartLine, ["step_in"])); - // readWitnessSignals(witness: Readonly, signals: string[] | OUT): Promise; - // console.log("Start Line step_out: ", parseAndLockStartLine); - // let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); - // let lockHeader = await lockHeaderCircuit.compute({ - // step_in: temp_step_in, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length - // }, ["step_out"]); - - // console.log("Lock Header step_out: ", lockHeader.step_out); - - // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out }, ["step_out"]); + // Run AES chain + let ctr = [0x00, 0x00, 0x00, 0x01]; + const init_nivc_input = 0; + + let pt = http_response_plaintext.slice(0, 16); + let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); + let i = 0; + console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); + for (i = 1; i < (DATA_BYTES / 16); i++) { + ctr[3] += 1; // This will work since we don't run a test that overlows a byte + let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); + console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); + } + assert.deepEqual(http_response_hash, aes_gcm.step_out); + + // Lock the start line + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + console.log("Start Line `step_out`: ", parseAndLockStartLine.step_out); + + // Lock a header + let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + console.log("Lock Header `step_out`: ", lockHeader.step_out); + + // Mask the body + // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out, data: http_response_plaintext }, ["step_out"]); + let bodyMask = await bodyMaskCircuit.compute({ step_in: http_response_hash, data: http_response_plaintext }, ["step_out"]); + console.log("Body Mask `step_out`: ", bodyMask.step_out); + assert.deepEqual(bodyMask.step_out, http_body_mask_hash); // let bodyMaskOut = bodyMask.step_out as number[]; // let idx = bodyMaskOut.indexOf('{'.charCodeAt(0)); From 16ff091da9614fdb965478789f076ad42da13da9 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 7 Nov 2024 14:14:38 -0700 Subject: [PATCH 09/19] json object extract --- circuits.json | 9 ++ circuits/http/nivc/body_mask.circom | 3 +- circuits/json/nivc/masker.circom | 98 ++++++------- circuits/test/full/full.test.ts | 209 +++++++++++++++------------- 4 files changed, 172 insertions(+), 147 deletions(-) diff --git a/circuits.json b/circuits.json index 76242d2..24cec79 100644 --- a/circuits.json +++ b/circuits.json @@ -242,5 +242,14 @@ "params": [ 1024 ] + }, + "nivc_json_object": { + "file": "json/nivc/masker", + "template": "JsonMaskObjectNIVC", + "params": [ + 1024, + 10, + 10 + ] } } \ No newline at end of file diff --git a/circuits/http/nivc/body_mask.circom b/circuits/http/nivc/body_mask.circom index 5a78b1a..d8956ed 100644 --- a/circuits/http/nivc/body_mask.circom +++ b/circuits/http/nivc/body_mask.circom @@ -45,7 +45,6 @@ template HTTPMaskBodyNIVC(DATA_BYTES) { } // Hash the new data so this can now be used in the chain later - signal body_mask_hash <== DataHasher(DATA_BYTES)(bodyMasked); - step_out[0] <== body_mask_hash; + step_out[0] <== DataHasher(DATA_BYTES)(bodyMasked); } diff --git a/circuits/json/nivc/masker.circom b/circuits/json/nivc/masker.circom index 76d4c08..74a0256 100644 --- a/circuits/json/nivc/masker.circom +++ b/circuits/json/nivc/masker.circom @@ -3,21 +3,18 @@ pragma circom 2.1.9; include "../interpreter.circom"; template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) { - // ------------------------------------------------------------------------------------------------------------------ // assert(MAX_STACK_HEIGHT >= 2); // TODO (autoparallel): idk if we need this now - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes ct/pt + ctr - // ------------------------------------------------------------------------------------------------------------------ // - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; - - // Declaration of signals. - signal data[DATA_BYTES]; + + signal input step_in[1]; signal input key[MAX_KEY_LENGTH]; signal input keyLen; - for(var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - } + signal output step_out[1]; + + // Authenticate the (potentially further masked) plaintext we are passing in + signal input data[DATA_BYTES]; + signal data_hash <== DataHasher(DATA_BYTES)(data); + data_hash === step_in[0]; // flag determining whether this byte is matched value signal is_value_match[DATA_BYTES - MAX_KEY_LENGTH]; @@ -50,46 +47,51 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) { is_key_match_for_value[1] <== Mux1()([is_key_match_for_value[0] * (1-is_next_pair_at_depth[0]), is_key_match[0] * (1-is_next_pair_at_depth[0])], is_key_match[0]); is_value_match[0] <== parsing_value[0] * is_key_match_for_value[1]; - step_out[0] <== data[0] * is_value_match[0]; + signal masked[DATA_BYTES]; + signal output maskedData[DATA_BYTES]; // TODO temp + masked[0] <== data[0] * is_value_match[0]; // TODO (autoparallel): it might be dumb to do this with the max key length but fuck it - for(var data_idx = 1; data_idx < DATA_BYTES - MAX_KEY_LENGTH; data_idx++) { - State[data_idx] = StateUpdate(MAX_STACK_HEIGHT); - State[data_idx].byte <== data[data_idx]; - State[data_idx].stack <== State[data_idx - 1].next_stack; - State[data_idx].parsing_string <== State[data_idx - 1].next_parsing_string; - State[data_idx].parsing_number <== State[data_idx - 1].next_parsing_number; - - // - parsing key - // - parsing value (different for string/numbers and array) - // - key match (key 1, key 2) - // - is next pair - // - is key match for value - // - value_mask - // - mask - - // check if inside key or not - parsing_key[data_idx] <== InsideKey()(State[data_idx].next_stack[0], State[data_idx].next_parsing_string, State[data_idx].next_parsing_number); - // check if inside value - parsing_value[data_idx] <== InsideValueObject()(State[data_idx].next_stack[0], State[data_idx].next_stack[1], State[data_idx].next_parsing_string, State[data_idx].next_parsing_number); - - // to get correct value, check: - // - key matches at current index and depth of key is as specified - // - whether next KV pair starts - // - whether key matched for a value (propogate key match until new KV pair of lower depth starts) - is_key_match[data_idx] <== KeyMatchAtIndex(DATA_BYTES, MAX_KEY_LENGTH, data_idx)(data, key, keyLen, parsing_key[data_idx]); - is_next_pair_at_depth[data_idx] <== NextKVPairAtDepth(MAX_STACK_HEIGHT)(State[data_idx].next_stack, data[data_idx], 0); - is_key_match_for_value[data_idx+1] <== Mux1()([is_key_match_for_value[data_idx] * (1-is_next_pair_at_depth[data_idx]), is_key_match[data_idx] * (1-is_next_pair_at_depth[data_idx])], is_key_match[data_idx]); - is_value_match[data_idx] <== is_key_match_for_value[data_idx+1] * parsing_value[data_idx]; - - or[data_idx - 1] <== OR()(is_value_match[data_idx], is_value_match[data_idx - 1]); - - // mask = currently parsing value and all subsequent keys matched - step_out[data_idx] <== data[data_idx] * or[data_idx - 1]; - } - for(var i = DATA_BYTES - MAX_KEY_LENGTH; i < DATA_BYTES + 4; i ++) { - step_out[i] <== 0; + for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) { + if(data_idx < DATA_BYTES - MAX_KEY_LENGTH) { + State[data_idx] = StateUpdate(MAX_STACK_HEIGHT); + State[data_idx].byte <== data[data_idx]; + State[data_idx].stack <== State[data_idx - 1].next_stack; + State[data_idx].parsing_string <== State[data_idx - 1].next_parsing_string; + State[data_idx].parsing_number <== State[data_idx - 1].next_parsing_number; + + // - parsing key + // - parsing value (different for string/numbers and array) + // - key match (key 1, key 2) + // - is next pair + // - is key match for value + // - value_mask + // - mask + + // check if inside key or not + parsing_key[data_idx] <== InsideKey()(State[data_idx].next_stack[0], State[data_idx].next_parsing_string, State[data_idx].next_parsing_number); + // check if inside value + parsing_value[data_idx] <== InsideValueObject()(State[data_idx].next_stack[0], State[data_idx].next_stack[1], State[data_idx].next_parsing_string, State[data_idx].next_parsing_number); + + // to get correct value, check: + // - key matches at current index and depth of key is as specified + // - whether next KV pair starts + // - whether key matched for a value (propogate key match until new KV pair of lower depth starts) + is_key_match[data_idx] <== KeyMatchAtIndex(DATA_BYTES, MAX_KEY_LENGTH, data_idx)(data, key, keyLen, parsing_key[data_idx]); + is_next_pair_at_depth[data_idx] <== NextKVPairAtDepth(MAX_STACK_HEIGHT)(State[data_idx].next_stack, data[data_idx], 0); + is_key_match_for_value[data_idx+1] <== Mux1()([is_key_match_for_value[data_idx] * (1-is_next_pair_at_depth[data_idx]), is_key_match[data_idx] * (1-is_next_pair_at_depth[data_idx])], is_key_match[data_idx]); + is_value_match[data_idx] <== is_key_match_for_value[data_idx+1] * parsing_value[data_idx]; + + or[data_idx - 1] <== OR()(is_value_match[data_idx], is_value_match[data_idx - 1]); + + // mask = currently parsing value and all subsequent keys matched + masked[data_idx] <== data[data_idx] * or[data_idx - 1]; // TODO here + } else { + masked[data_idx] <== 0; + } } + maskedData <== masked; + step_out[0] <== DataHasher(DATA_BYTES)(masked); } template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) { diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 13d51aa..2a2b04d 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -61,23 +61,21 @@ const http_response_plaintext = [ 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; -const http_body = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 123, 13, 10, 32, 32, 32, - 34, 100, 97, 116, 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, - 32, 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, 91, 13, 10, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, - 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, 111, 102, 105, 108, - 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, - 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, - 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125] +const http_body = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 123, 13, 10, 32, 32, 32, 34, + 100, 97, 116, 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 34, 105, 116, 101, 109, + 115, 34, 58, 32, 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, + 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 34, 112, 114, 111, 102, 105, 108, 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, + 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, + 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125, +] const lengthDiff = http_response_plaintext.length - http_body.length; // Create an array of zeros with the length difference @@ -89,13 +87,30 @@ const padded_http_body = [...padding, ...http_body]; const http_response_hash = dataHasher(http_response_plaintext); const http_body_mask_hash = dataHasher(padded_http_body); + +const json_key0_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, 91, + 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, + 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, 111, + 102, 105, 108, 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, + 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 0, + 0, 0, 0, 0, 0, 0, 0, +]; +const json_key0_mask_hash = dataHasher(json_key0_mask); + describe("NIVC_FULL", async () => { - let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; - let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; - let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; - let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; - // let parse_circuit: WitnessTester<["step_in"], ["step_out"]>; - // let json_mask_object_circuit: WitnessTester<["step_in", "key", "keyLen"], ["step_out"]>; + // let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; + // let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; + // let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; + // let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; + let json_mask_object_circuit: WitnessTester<["step_in", "data", "key", "keyLen"], ["step_out", "maskedData"]>; // let json_mask_arr_circuit: WitnessTester<["step_in", "index"], ["step_out"]>; // let extract_value_circuit: WitnessTester<["step_in"], ["step_out"]>; @@ -117,32 +132,39 @@ describe("NIVC_FULL", async () => { const MAX_VALUE_LENGTH = 35; before(async () => { - aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { - file: "aes-gcm/nivc/aes-gctr-nivc", - template: "AESGCTRFOLD", - }); - console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); + // aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { + // file: "aes-gcm/nivc/aes-gctr-nivc", + // template: "AESGCTRFOLD", + // }); + // console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); - httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { - file: "http/nivc/parse_and_lock_start_line", - template: "ParseAndLockStartLine", - params: [DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH], - }); - console.log("#constraints (HTTP-PARSE-AND-LOCK-START-LINE):", await httpParseAndLockStartLineCircuit.getConstraintCount()); + // httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { + // file: "http/nivc/parse_and_lock_start_line", + // template: "ParseAndLockStartLine", + // params: [DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH], + // }); + // console.log("#constraints (HTTP-PARSE-AND-LOCK-START-LINE):", await httpParseAndLockStartLineCircuit.getConstraintCount()); - lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { - file: "http/nivc/lock_header", - template: "LockHeader", - params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], - }); - console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); + // lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { + // file: "http/nivc/lock_header", + // template: "LockHeader", + // params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], + // }); + // console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); - bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { - file: "http/nivc/body_mask", - template: "HTTPMaskBodyNIVC", - params: [DATA_BYTES], + // bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { + // file: "http/nivc/body_mask", + // template: "HTTPMaskBodyNIVC", + // params: [DATA_BYTES], + // }); + // console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); + + json_mask_object_circuit = await circomkit.WitnessTester(`JsonMaskObjectNIVC`, { + file: "json/nivc/masker", + template: "JsonMaskObjectNIVC", + params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH], }); - console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); + console.log("#constraints (JSON-MASK-OBJECT):", await json_mask_object_circuit.getConstraintCount()); // json_mask_arr_circuit = await circomkit.WitnessTester(`JsonMaskArrayIndexNIVC`, { // file: "json/nivc/masker", @@ -151,13 +173,6 @@ describe("NIVC_FULL", async () => { // }); // console.log("#constraints (JSON-MASK-ARRAY-INDEX):", await json_mask_arr_circuit.getConstraintCount()); - // json_mask_object_circuit = await circomkit.WitnessTester(`JsonMaskObjectNIVC`, { - // file: "json/nivc/masker", - // template: "JsonMaskObjectNIVC", - // params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH], - // }); - // console.log("#constraints (JSON-MASK-OBJECT):", await json_mask_object_circuit.getConstraintCount()); - // extract_value_circuit = await circomkit.WitnessTester(`JsonMaskExtractFinal`, { // file: "json/nivc/extractor", // template: "MaskExtractFinal", @@ -176,54 +191,54 @@ describe("NIVC_FULL", async () => { let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); it("NIVC_CHAIN", async () => { - // Run AES chain - let ctr = [0x00, 0x00, 0x00, 0x01]; - const init_nivc_input = 0; - - let pt = http_response_plaintext.slice(0, 16); - let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); - let i = 0; - console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); - for (i = 1; i < (DATA_BYTES / 16); i++) { - ctr[3] += 1; // This will work since we don't run a test that overlows a byte - let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); - console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); - } - assert.deepEqual(http_response_hash, aes_gcm.step_out); - - // Lock the start line - let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - console.log("Start Line `step_out`: ", parseAndLockStartLine.step_out); - - // Lock a header - let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); - console.log("Lock Header `step_out`: ", lockHeader.step_out); + // // Run AES chain + // let ctr = [0x00, 0x00, 0x00, 0x01]; + // const init_nivc_input = 0; + + // let pt = http_response_plaintext.slice(0, 16); + // let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); + // let i = 0; + // console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); + // for (i = 1; i < (DATA_BYTES / 16); i++) { + // ctr[3] += 1; // This will work since we don't run a test that overlows a byte + // let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); + // aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); + // console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); + // } + // assert.deepEqual(http_response_hash, aes_gcm.step_out); + + // // Lock the start line + // let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + // console.log("Start Line `step_out`: ", parseAndLockStartLine.step_out); + + // // Lock a header + // let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + // console.log("Lock Header `step_out`: ", lockHeader.step_out); + + // // Mask the body + // // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out, data: http_response_plaintext }, ["step_out"]); + // let bodyMask = await bodyMaskCircuit.compute({ step_in: http_response_hash, data: http_response_plaintext }, ["step_out"]); + // console.log("Body Mask `step_out`: ", bodyMask.step_out); + // assert.deepEqual(bodyMask.step_out, http_body_mask_hash); + + let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data" + let key0Len = 4; + let key1 = [105, 116, 101, 109, 115, 0, 0, 0]; // "items" + let key1Len = 5; + let key2 = [112, 114, 111, 102, 105, 108, 101, 0]; // "profile" + let key2Len = 7; + let key3 = [110, 97, 109, 101, 0, 0, 0, 0]; // "name" + let key3Len = 4; + + let value = toByte("\"Taylor Swift\""); - // Mask the body - // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out, data: http_response_plaintext }, ["step_out"]); - let bodyMask = await bodyMaskCircuit.compute({ step_in: http_response_hash, data: http_response_plaintext }, ["step_out"]); - console.log("Body Mask `step_out`: ", bodyMask.step_out); - assert.deepEqual(bodyMask.step_out, http_body_mask_hash); - - // let bodyMaskOut = bodyMask.step_out as number[]; - // let idx = bodyMaskOut.indexOf('{'.charCodeAt(0)); - - // let maskedInput = extendedJsonInput.fill(0, 0, idx); - // maskedInput = maskedInput.fill(0, 320); - - // let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data" - // let key0Len = 4; - // let key1 = [105, 116, 101, 109, 115, 0, 0, 0]; // "items" - // let key1Len = 5; - // let key2 = [112, 114, 111, 102, 105, 108, 101, 0]; // "profile" - // let key2Len = 7; - // let key3 = [110, 97, 109, 101, 0, 0, 0, 0]; // "name" - // let key3Len = 4; + // let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: bodyMaskOut, key: key0, keyLen: key0Len }, ["step_out"]); - // let value = toByte("\"Taylor Swift\""); - // let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: bodyMaskOut, key: key0, keyLen: key0Len }, ["step_out"]); + let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: http_body_mask_hash, data: http_body, key: key0, keyLen: key0Len }, ["step_out", "maskedData"]); + console.log(JSON.stringify(json_extract_key0.maskedData)); + console.log("JSON Extract key0 `step_out`:", JSON.stringify(json_extract_key0.step_out)); + assert.deepEqual(json_extract_key0.step_out, json_key0_mask_hash); // let json_num = json_extract_key0.step_out as number[]; // console.log("json_extract_key0", json_num); From e27a29f861fdec52cdea470b9cae77f09f0d3e28 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 7 Nov 2024 16:52:51 -0700 Subject: [PATCH 10/19] working full NIVC proof --- circuits.json | 8 ++ circuits/json/nivc/masker.circom | 36 +++-- circuits/test/full/full.test.ts | 219 ++++++++++++++++++++----------- 3 files changed, 166 insertions(+), 97 deletions(-) diff --git a/circuits.json b/circuits.json index 24cec79..5bd122d 100644 --- a/circuits.json +++ b/circuits.json @@ -251,5 +251,13 @@ 10, 10 ] + }, + "nivc_json_array": { + "file": "json/nivc/masker", + "template": "JsonMaskArrayIndexNIVC", + "params": [ + 1024, + 10 + ] } } \ No newline at end of file diff --git a/circuits/json/nivc/masker.circom b/circuits/json/nivc/masker.circom index 74a0256..2ffbf27 100644 --- a/circuits/json/nivc/masker.circom +++ b/circuits/json/nivc/masker.circom @@ -48,7 +48,6 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) { is_value_match[0] <== parsing_value[0] * is_key_match_for_value[1]; signal masked[DATA_BYTES]; - signal output maskedData[DATA_BYTES]; // TODO temp masked[0] <== data[0] * is_value_match[0]; // TODO (autoparallel): it might be dumb to do this with the max key length but fuck it @@ -77,7 +76,11 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) { // - key matches at current index and depth of key is as specified // - whether next KV pair starts // - whether key matched for a value (propogate key match until new KV pair of lower depth starts) + + // TODO (autoparallel): this can be optimized i'm sure of it, running without it saves 110k constraints on 1024b (553k with it) is_key_match[data_idx] <== KeyMatchAtIndex(DATA_BYTES, MAX_KEY_LENGTH, data_idx)(data, key, keyLen, parsing_key[data_idx]); + + // TODO (autoparallel): this could also likely be optimized, costs like 140k constraints itself is_next_pair_at_depth[data_idx] <== NextKVPairAtDepth(MAX_STACK_HEIGHT)(State[data_idx].next_stack, data[data_idx], 0); is_key_match_for_value[data_idx+1] <== Mux1()([is_key_match_for_value[data_idx] * (1-is_next_pair_at_depth[data_idx]), is_key_match[data_idx] * (1-is_next_pair_at_depth[data_idx])], is_key_match[data_idx]); is_value_match[data_idx] <== is_key_match_for_value[data_idx+1] * parsing_value[data_idx]; @@ -90,25 +93,21 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) { masked[data_idx] <== 0; } } - maskedData <== masked; step_out[0] <== DataHasher(DATA_BYTES)(masked); } template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) { - // ------------------------------------------------------------------------------------------------------------------ // assert(MAX_STACK_HEIGHT >= 2); // TODO (autoparallel): idk if we need this now - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes ct/pt + ctr - // ------------------------------------------------------------------------------------------------------------------ // - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; - - // Declaration of signals. - signal data[DATA_BYTES]; + + signal input step_in[1]; signal input index; - for(var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - } + signal output step_out[1]; + + // Authenticate the (potentially further masked) plaintext we are passing in + signal input data[DATA_BYTES]; + signal data_hash <== DataHasher(DATA_BYTES)(data); + data_hash === step_in[0]; component State[DATA_BYTES]; State[0] = StateUpdate(MAX_STACK_HEIGHT); @@ -123,9 +122,8 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) { signal or[DATA_BYTES - 1]; parsing_array[0] <== InsideArrayIndexObject()(State[0].next_stack[0], State[0].next_stack[1], State[0].next_parsing_string, State[0].next_parsing_number, index); - step_out[0] <== data[0] * parsing_array[0]; // TODO (autoparallel): is this totally correcot or do we need an or, i think it's right - - + signal masked[DATA_BYTES]; + masked[0] <== data[0] * parsing_array[0]; for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) { State[data_idx] = StateUpdate(MAX_STACK_HEIGHT); State[data_idx].byte <== data[data_idx]; @@ -136,9 +134,7 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) { parsing_array[data_idx] <== InsideArrayIndexObject()(State[data_idx].next_stack[0], State[data_idx].next_stack[1], State[data_idx].next_parsing_string, State[data_idx].next_parsing_number, index); or[data_idx - 1] <== OR()(parsing_array[data_idx], parsing_array[data_idx - 1]); - step_out[data_idx] <== data[data_idx] * or[data_idx - 1]; - } - for(var i = DATA_BYTES ; i < TOTAL_BYTES_ACROSS_NIVC; i++) { - step_out[i] <== 0; + masked[data_idx] <== data[data_idx] * or[data_idx - 1]; } + step_out[0] <== DataHasher(DATA_BYTES)(masked); } diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 2a2b04d..ae011be 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -105,13 +105,75 @@ const json_key0_mask = [ ]; const json_key0_mask_hash = dataHasher(json_key0_mask); +const json_key1_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 13, 10, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, 111, 102, 105, 108, 101, 34, + 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, 97, + 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; +const json_key1_mask_hash = dataHasher(json_key1_mask); + +const json_arr_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, + 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, 111, 102, 105, 108, 101, 34, 58, 32, 123, 13, + 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, + 58, 32, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; +const json_arr_mask_hash = dataHasher(json_arr_mask); + +const json_key2_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, + 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key2_mask_hash = dataHasher(json_key2_mask); + +const json_key3_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, + 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key3_mask_hash = dataHasher(json_key3_mask); + describe("NIVC_FULL", async () => { - // let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; - // let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; - // let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; - // let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; - let json_mask_object_circuit: WitnessTester<["step_in", "data", "key", "keyLen"], ["step_out", "maskedData"]>; - // let json_mask_arr_circuit: WitnessTester<["step_in", "index"], ["step_out"]>; + let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; + let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; + let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; + let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; + let json_mask_object_circuit: WitnessTester<["step_in", "data", "key", "keyLen"], ["step_out"]>; + let json_mask_arr_circuit: WitnessTester<["step_in", "data", "index"], ["step_out"]>; // let extract_value_circuit: WitnessTester<["step_in"], ["step_out"]>; const DATA_BYTES = 320; @@ -132,32 +194,32 @@ describe("NIVC_FULL", async () => { const MAX_VALUE_LENGTH = 35; before(async () => { - // aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { - // file: "aes-gcm/nivc/aes-gctr-nivc", - // template: "AESGCTRFOLD", - // }); - // console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); + aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { + file: "aes-gcm/nivc/aes-gctr-nivc", + template: "AESGCTRFOLD", + }); + console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); - // httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { - // file: "http/nivc/parse_and_lock_start_line", - // template: "ParseAndLockStartLine", - // params: [DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH], - // }); - // console.log("#constraints (HTTP-PARSE-AND-LOCK-START-LINE):", await httpParseAndLockStartLineCircuit.getConstraintCount()); + httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { + file: "http/nivc/parse_and_lock_start_line", + template: "ParseAndLockStartLine", + params: [DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH], + }); + console.log("#constraints (HTTP-PARSE-AND-LOCK-START-LINE):", await httpParseAndLockStartLineCircuit.getConstraintCount()); - // lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { - // file: "http/nivc/lock_header", - // template: "LockHeader", - // params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], - // }); - // console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); + lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { + file: "http/nivc/lock_header", + template: "LockHeader", + params: [DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], + }); + console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); - // bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { - // file: "http/nivc/body_mask", - // template: "HTTPMaskBodyNIVC", - // params: [DATA_BYTES], - // }); - // console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); + bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { + file: "http/nivc/body_mask", + template: "HTTPMaskBodyNIVC", + params: [DATA_BYTES], + }); + console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); json_mask_object_circuit = await circomkit.WitnessTester(`JsonMaskObjectNIVC`, { file: "json/nivc/masker", @@ -166,12 +228,12 @@ describe("NIVC_FULL", async () => { }); console.log("#constraints (JSON-MASK-OBJECT):", await json_mask_object_circuit.getConstraintCount()); - // json_mask_arr_circuit = await circomkit.WitnessTester(`JsonMaskArrayIndexNIVC`, { - // file: "json/nivc/masker", - // template: "JsonMaskArrayIndexNIVC", - // params: [DATA_BYTES, MAX_STACK_HEIGHT], - // }); - // console.log("#constraints (JSON-MASK-ARRAY-INDEX):", await json_mask_arr_circuit.getConstraintCount()); + json_mask_arr_circuit = await circomkit.WitnessTester(`JsonMaskArrayIndexNIVC`, { + file: "json/nivc/masker", + template: "JsonMaskArrayIndexNIVC", + params: [DATA_BYTES, MAX_STACK_HEIGHT], + }); + console.log("#constraints (JSON-MASK-ARRAY-INDEX):", await json_mask_arr_circuit.getConstraintCount()); // extract_value_circuit = await circomkit.WitnessTester(`JsonMaskExtractFinal`, { // file: "json/nivc/extractor", @@ -191,35 +253,35 @@ describe("NIVC_FULL", async () => { let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); it("NIVC_CHAIN", async () => { - // // Run AES chain - // let ctr = [0x00, 0x00, 0x00, 0x01]; - // const init_nivc_input = 0; - - // let pt = http_response_plaintext.slice(0, 16); - // let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); - // let i = 0; - // console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); - // for (i = 1; i < (DATA_BYTES / 16); i++) { - // ctr[3] += 1; // This will work since we don't run a test that overlows a byte - // let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - // aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); - // console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); - // } - // assert.deepEqual(http_response_hash, aes_gcm.step_out); - - // // Lock the start line - // let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - // console.log("Start Line `step_out`: ", parseAndLockStartLine.step_out); - - // // Lock a header - // let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); - // console.log("Lock Header `step_out`: ", lockHeader.step_out); - - // // Mask the body - // // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out, data: http_response_plaintext }, ["step_out"]); - // let bodyMask = await bodyMaskCircuit.compute({ step_in: http_response_hash, data: http_response_plaintext }, ["step_out"]); - // console.log("Body Mask `step_out`: ", bodyMask.step_out); - // assert.deepEqual(bodyMask.step_out, http_body_mask_hash); + // Run AES chain + let ctr = [0x00, 0x00, 0x00, 0x01]; + const init_nivc_input = 0; + + let pt = http_response_plaintext.slice(0, 16); + let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); + let i = 0; + console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); + for (i = 1; i < (DATA_BYTES / 16); i++) { + ctr[3] += 1; // This will work since we don't run a test that overlows a byte + let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); + console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); + } + assert.deepEqual(http_response_hash, aes_gcm.step_out); + + // Lock the start line + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: aes_gcm.step_out, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + console.log("Start Line `step_out`: ", parseAndLockStartLine.step_out); + + // Lock a header + let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + console.log("Lock Header `step_out`: ", lockHeader.step_out); + + // Mask the body + // let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out, data: http_response_plaintext }, ["step_out"]); + let bodyMask = await bodyMaskCircuit.compute({ step_in: http_response_hash, data: http_response_plaintext }, ["step_out"]); + console.log("Body Mask `step_out`: ", bodyMask.step_out); + assert.deepEqual(bodyMask.step_out, http_body_mask_hash); let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data" let key0Len = 4; @@ -230,26 +292,29 @@ describe("NIVC_FULL", async () => { let key3 = [110, 97, 109, 101, 0, 0, 0, 0]; // "name" let key3Len = 4; - let value = toByte("\"Taylor Swift\""); - - // let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: bodyMaskOut, key: key0, keyLen: key0Len }, ["step_out"]); - + // let value = toByte("\"Taylor Swift\""); - let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: http_body_mask_hash, data: http_body, key: key0, keyLen: key0Len }, ["step_out", "maskedData"]); - console.log(JSON.stringify(json_extract_key0.maskedData)); - console.log("JSON Extract key0 `step_out`:", JSON.stringify(json_extract_key0.step_out)); + let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: bodyMask.step_out, data: http_body, key: key0, keyLen: key0Len }, ["step_out"]); + console.log("JSON Extract key0 `step_out`:", json_extract_key0.step_out); assert.deepEqual(json_extract_key0.step_out, json_key0_mask_hash); - // let json_num = json_extract_key0.step_out as number[]; - // console.log("json_extract_key0", json_num); - // let json_extract_key1 = await json_mask_object_circuit.compute({ step_in: json_extract_key0.step_out, key: key1, keyLen: key1Len }, ["step_out"]); + let json_extract_key1 = await json_mask_object_circuit.compute({ step_in: json_extract_key0.step_out, data: json_key0_mask, key: key1, keyLen: key1Len }, ["step_out"]); + assert.deepEqual(json_extract_key1.step_out, json_key1_mask_hash); + console.log("JSON Extract key1 `step_out`:", json_extract_key1.step_out); - // let json_extract_arr = await json_mask_arr_circuit.compute({ step_in: json_extract_key1.step_out, index: 0 }, ["step_out"]); + let json_extract_arr = await json_mask_arr_circuit.compute({ step_in: json_extract_key1.step_out, data: json_key1_mask, index: 0 }, ["step_out"]); + assert.deepEqual(json_extract_arr.step_out, json_arr_mask_hash); + console.log("JSON Extract arr `step_out`:", json_extract_arr.step_out); - // let json_extract_key2 = await json_mask_object_circuit.compute({ step_in: json_extract_arr.step_out, key: key2, keyLen: key2Len }, ["step_out"]); + let json_extract_key2 = await json_mask_object_circuit.compute({ step_in: json_extract_arr.step_out, data: json_arr_mask, key: key2, keyLen: key2Len }, ["step_out"]); + assert.deepEqual(json_extract_key2.step_out, json_key2_mask_hash); + console.log("JSON Extract key2 `step_out`:", json_extract_key2.step_out); - // let json_extract_key3 = await json_mask_object_circuit.compute({ step_in: json_extract_key2.step_out, key: key3, keyLen: key3Len }, ["step_out"]); + let json_extract_key3 = await json_mask_object_circuit.compute({ step_in: json_extract_key2.step_out, data: json_key2_mask, key: key3, keyLen: key3Len }, ["step_out"]); + assert.deepEqual(json_extract_key3.step_out, json_key3_mask_hash); + console.log("JSON Extract key3 `step_out`:", json_extract_key3.step_out); + // TODO (autoparallel): we need to rethink extraction here. // await extract_value_circuit.expectPass({ step_in: json_extract_key3.step_out }, { step_out: value }); }); }); \ No newline at end of file From 14e2a0f728f8a2b54112d6bd61b84eea515b18c4 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 11 Nov 2024 12:07:12 +0700 Subject: [PATCH 11/19] fix aes-nivc tests and http nivc tests --- .../target_1024b/aes_gctr_nivc_1024b.circom | 2 +- builds/target_512b/aes_gctr_nivc_512b.circom | 2 +- .../test/aes-gcm/nivc/aes-gctr-nivc.test.ts | 7 --- circuits/test/full/full.test.ts | 2 +- circuits/test/http/nivc/body_mask.test.ts | 54 +++++++++++++------ 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/builds/target_1024b/aes_gctr_nivc_1024b.circom b/builds/target_1024b/aes_gctr_nivc_1024b.circom index a48234a..c3d1ae5 100644 --- a/builds/target_1024b/aes_gctr_nivc_1024b.circom +++ b/builds/target_1024b/aes_gctr_nivc_1024b.circom @@ -2,4 +2,4 @@ pragma circom 2.1.9; include "../../circuits/aes-gcm/nivc/aes-gctr-nivc.circom"; -component main { public [step_in] } = AESGCTRFOLD(1024); \ No newline at end of file +component main { public [step_in] } = AESGCTRFOLD(); \ No newline at end of file diff --git a/builds/target_512b/aes_gctr_nivc_512b.circom b/builds/target_512b/aes_gctr_nivc_512b.circom index f863572..c3d1ae5 100644 --- a/builds/target_512b/aes_gctr_nivc_512b.circom +++ b/builds/target_512b/aes_gctr_nivc_512b.circom @@ -2,4 +2,4 @@ pragma circom 2.1.9; include "../../circuits/aes-gcm/nivc/aes-gctr-nivc.circom"; -component main { public [step_in] } = AESGCTRFOLD(512); \ No newline at end of file +component main { public [step_in] } = AESGCTRFOLD(); \ No newline at end of file diff --git a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts index b517b8e..6ea8ea9 100644 --- a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts +++ b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts @@ -16,13 +16,11 @@ function bytesToBigInt(bytes: number[] | Uint8Array): bigint { describe("aes-gctr-nivc", () => { let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad", "ctr", "step_in"], ["step_out"]>; - const DATA_BYTES_0 = 16; it("all correct for self generated single zero pt block case", async () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [DATA_BYTES_0], // input len is 16 bytes }); let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -42,7 +40,6 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [DATA_BYTES_0], // input len is 16 bytes }); let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; @@ -58,8 +55,6 @@ describe("aes-gctr-nivc", () => { assert.deepEqual(witness.step_out, PoseidonModular([step_in, bytesToBigInt(plainText)])); }); - const DATA_BYTES_1 = 32; - let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; let plainText1 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; let plainText2 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; @@ -72,7 +67,6 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [DATA_BYTES_1], // input len is 32 bytes }); const ctr = [0x00, 0x00, 0x00, 0x01]; @@ -86,7 +80,6 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [DATA_BYTES_1], // input len is 32 bytes }); const ctr_0 = [0x00, 0x00, 0x00, 0x01]; diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index ae011be..95f3a97 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -2,7 +2,7 @@ import { assert } from "chai"; import { circomkit, WitnessTester, toByte } from "../common"; import { PoseidonModular } from "../common/poseidon"; -function dataHasher(input: number[]): bigint { +export function dataHasher(input: number[]): bigint { if (input.length % 16 !== 0) { throw new Error("DATA_BYTES must be divisible by 16"); } diff --git a/circuits/test/http/nivc/body_mask.test.ts b/circuits/test/http/nivc/body_mask.test.ts index 1e45ed4..f1d8ec6 100644 --- a/circuits/test/http/nivc/body_mask.test.ts +++ b/circuits/test/http/nivc/body_mask.test.ts @@ -1,4 +1,6 @@ import { circomkit, WitnessTester, toByte } from "../../common"; +import { assert } from "chai"; +import { dataHasher } from "../../full/full.test"; // HTTP/1.1 200 OK // content-type: application/json; charset=utf-8 @@ -36,13 +38,40 @@ let http_response_plaintext = [ 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; +const http_body = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 123, 13, 10, 32, 32, 32, 34, + 100, 97, 116, 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 34, 105, 116, 101, 109, + 115, 34, 58, 32, 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, + 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 34, 112, 114, 111, 102, 105, 108, 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, + 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, + 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125, +]; + +const lengthDiff = http_response_plaintext.length - http_body.length; + +// Create an array of zeros with the length difference +const padding = new Array(lengthDiff).fill(0); + +// Concatenate the padding with http_body +const padded_http_body = [...padding, ...http_body]; + +const http_response_hash = dataHasher(http_response_plaintext); +const http_body_mask_hash = dataHasher(padded_http_body); + describe("NIVC_HTTP", async () => { - let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; - let lockHeaderCircuit: WitnessTester<["step_in", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; - let bodyMaskCircuit: WitnessTester<["step_in"], ["step_out"]>; + let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; + let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; + let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; const DATA_BYTES = 320; - const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; + const TOTAL_BYTES_ACROSS_NIVC = 1; const MAX_HEADER_NAME_LENGTH = 20; const MAX_HEADER_VALUE_LENGTH = 35; @@ -88,18 +117,13 @@ describe("NIVC_HTTP", async () => { let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); it("HTTPParseAndExtract", async () => { - let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedJsonInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - - let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); - - let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out }, ["step_out"]); - - let bodyMaskOut = bodyMask.step_out as number[]; - let idx = bodyMaskOut.indexOf('{'.charCodeAt(0)); + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: http_response_hash, data: http_response_plaintext, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, data: http_response_plaintext, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out, data: http_response_plaintext }, ["step_out"]); + console.log("GOT TRHOUGH THIRD CIRCUIT"); - let maskedInput = extendedJsonInput.fill(0, 0, idx); - maskedInput = maskedInput.fill(0, 320); + assert.deepEqual(bodyMask.step_out, http_body_mask_hash); - bodyMaskOut === maskedInput; + // bodyMask.step_out === PoseidonModular(maskedInput); }); }); \ No newline at end of file From bfb664bce6e03eb5553c9efa765bb70cbc9ed7fa Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 11 Nov 2024 13:06:06 +0700 Subject: [PATCH 12/19] aes takes in cipher text and validates it --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 3 ++ .../test/aes-gcm/nivc/aes-gctr-nivc.test.ts | 20 ++++++------- circuits/test/full/full.test.ts | 30 +++++++++++++++++-- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 22ed2cb..75920ab 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -12,6 +12,8 @@ template AESGCTRFOLD() { signal input ctr[4]; signal input plainText[16]; + signal input cipherText[16]; + signal input step_in[1]; signal output step_out[1]; @@ -22,6 +24,7 @@ template AESGCTRFOLD() { aes.plainText <== plainText; aes.lastCounter <== ctr; + aes.cipherText === cipherText; var packedPlaintext = 0; for(var i = 0 ; i < 16 ; i++) { packedPlaintext += plainText[i] * 2**(8*i); diff --git a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts index 6ea8ea9..84139bd 100644 --- a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts +++ b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts @@ -14,7 +14,7 @@ function bytesToBigInt(bytes: number[] | Uint8Array): bigint { } describe("aes-gctr-nivc", () => { - let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad", "ctr", "step_in"], ["step_out"]>; + let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad", "ctr", "cipherText", "step_in"], ["step_out"]>; it("all correct for self generated single zero pt block case", async () => { @@ -27,12 +27,12 @@ describe("aes-gctr-nivc", () => { let plainText = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let iv = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - // let ct = [0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78]; + let ct = [0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78]; const ctr = [0x00, 0x00, 0x00, 0x01]; const step_in = 0; - const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, ctr: ctr, step_in: step_in }, ["step_out"]) + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, ctr: ctr, cipherText: ct, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, PoseidonModular([step_in, bytesToBigInt(plainText)])); }); @@ -46,12 +46,12 @@ describe("aes-gctr-nivc", () => { let plainText = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - // let ct = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; + let ct = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; const ctr = [0x00, 0x00, 0x00, 0x01]; const step_in = 0; - const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, ctr: ctr, step_in: step_in }, ["step_out"]) + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, ctr: ctr, cipherText: ct, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, PoseidonModular([step_in, bytesToBigInt(plainText)])); }); @@ -60,8 +60,8 @@ describe("aes-gctr-nivc", () => { let plainText2 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - // let ct_part1 = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; - // let ct_part2 = [0x26, 0x75, 0x65, 0x30, 0x71, 0x3e, 0x4c, 0x06, 0x5a, 0xf1, 0xd3, 0xc4, 0xf5, 0x6e, 0x02, 0x04]; + let ct_part1 = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; + let ct_part2 = [0x26, 0x75, 0x65, 0x30, 0x71, 0x3e, 0x4c, 0x06, 0x5a, 0xf1, 0xd3, 0xc4, 0xf5, 0x6e, 0x02, 0x04]; it("all correct for self generated two block case first fold", async () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { @@ -72,7 +72,7 @@ describe("aes-gctr-nivc", () => { const ctr = [0x00, 0x00, 0x00, 0x01]; const step_in = 0; - const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, ctr: ctr, step_in: step_in }, ["step_out"]) + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, ctr: ctr, cipherText: ct_part1, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, PoseidonModular([step_in, bytesToBigInt(plainText1)])); }); @@ -86,8 +86,8 @@ describe("aes-gctr-nivc", () => { const ctr_1 = [0x00, 0x00, 0x00, 0x02]; const step_in_0 = 0; - const witness_0 = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, ctr: ctr_0, step_in: step_in_0 }, ["step_out"]) - const witness_1 = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText2, aad: aad, ctr: ctr_1, step_in: witness_0.step_out }, ["step_out"]) + const witness_0 = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, ctr: ctr_0, cipherText: ct_part1, step_in: step_in_0 }, ["step_out"]) + const witness_1 = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText2, aad: aad, ctr: ctr_1, cipherText: ct_part2, step_in: witness_0.step_out }, ["step_out"]) assert.deepEqual(witness_1.step_out, PoseidonModular([BigInt(witness_0.step_out.toString()), bytesToBigInt(plainText2)])); }); }); \ No newline at end of file diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 95f3a97..ae56f39 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -61,6 +61,28 @@ const http_response_plaintext = [ 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; +const http_response_ciphertext = [ + 75, 220, 142, 158, 79, 135, 141, 163, 211, 26, 242, 137, 81, 253, 181, 117, + 253, 246, 197, 197, 61, 46, 55, 87, 218, 137, 240, 143, 241, 177, 225, 129, + 80, 114, 125, 72, 45, 18, 224, 179, 79, 231, 153, 198, 163, 252, 197, 219, + 233, 46, 202, 120, 99, 253, 76, 9, 70, 11, 200, 218, 228, 251, 133, 248, + 233, 177, 19, 241, 205, 128, 65, 76, 10, 31, 71, 198, 177, 78, 108, 246, + 175, 152, 42, 97, 255, 182, 157, 245, 123, 95, 130, 101, 129, 138, 236, 146, + 47, 22, 22, 13, 125, 1, 109, 158, 189, 131, 44, 43, 203, 118, 79, 181, + 86, 33, 235, 186, 75, 20, 7, 147, 102, 75, 90, 222, 255, 140, 94, 52, + 191, 145, 192, 71, 239, 245, 247, 175, 117, 136, 173, 235, 250, 189, 74, 155, + 103, 25, 164, 187, 22, 26, 39, 37, 113, 248, 170, 146, 73, 75, 45, 208, + 125, 49, 101, 11, 120, 215, 93, 160, 14, 147, 129, 181, 150, 59, 167, 197, + 230, 122, 77, 245, 247, 215, 136, 98, 1, 180, 213, 30, 214, 88, 83, 42, + 33, 112, 61, 4, 197, 75, 134, 149, 22, 228, 24, 95, 131, 35, 44, 181, + 135, 31, 173, 36, 23, 192, 177, 127, 156, 199, 167, 212, 66, 235, 194, 102, + 61, 144, 121, 59, 187, 179, 212, 34, 117, 47, 96, 3, 169, 73, 204, 88, + 36, 48, 158, 220, 237, 198, 180, 105, 7, 188, 109, 24, 201, 217, 186, 191, + 232, 63, 93, 153, 118, 214, 157, 167, 15, 216, 191, 152, 41, 106, 24, 127, + 8, 144, 78, 218, 133, 125, 89, 97, 10, 246, 8, 244, 112, 169, 190, 206, + 14, 217, 109, 147, 130, 61, 214, 237, 143, 77, 14, 14, 70, 56, 94, 97, + 207, 214, 106, 249, 37, 7, 186, 95, 174, 146, 203, 148, 173, 172, 13, 113 +]; const http_body = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -168,7 +190,7 @@ const json_key3_mask = [ const json_key3_mask_hash = dataHasher(json_key3_mask); describe("NIVC_FULL", async () => { - let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "step_in"], ["step_out"]>; + let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "cipherText", "step_in"], ["step_out"]>; let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; @@ -258,13 +280,15 @@ describe("NIVC_FULL", async () => { const init_nivc_input = 0; let pt = http_response_plaintext.slice(0, 16); - let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); + let ct = http_response_ciphertext.slice(0, 16); + let aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), cipherText: ct, step_in: init_nivc_input }, ["step_out"]); let i = 0; console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); for (i = 1; i < (DATA_BYTES / 16); i++) { ctr[3] += 1; // This will work since we don't run a test that overlows a byte let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); + let ct = http_response_ciphertext.slice(i * 16, i * 16 + 16); + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), ctr: ctr, plainText: pt, aad: Array(16).fill(0), cipherText: ct, step_in: aes_gcm.step_out }, ["step_out"]); console.log("AES `step_out[", i, "]`: ", aes_gcm.step_out); } assert.deepEqual(http_response_hash, aes_gcm.step_out); From 7f39b6ccf06ad533a0fb9bb2875a08ef9d2333f1 Mon Sep 17 00:00:00 2001 From: lonerapier Date: Mon, 11 Nov 2024 16:33:37 +0530 Subject: [PATCH 13/19] fix: http lock header and parse tests --- circuits/test/full/full.test.ts | 1 - circuits/test/http/nivc/lock_header.test.ts | 22 ++++++++++--------- .../nivc/parse_and_lock_start_line.test.ts | 17 ++++++++------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index ae56f39..fd87b82 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -200,7 +200,6 @@ describe("NIVC_FULL", async () => { const DATA_BYTES = 320; const MAX_STACK_HEIGHT = 5; - const TOTAL_BYTES_ACROSS_NIVC = 1; const MAX_HEADER_NAME_LENGTH = 20; const MAX_HEADER_VALUE_LENGTH = 35; diff --git a/circuits/test/http/nivc/lock_header.test.ts b/circuits/test/http/nivc/lock_header.test.ts index 81d3dd6..ebc7e78 100644 --- a/circuits/test/http/nivc/lock_header.test.ts +++ b/circuits/test/http/nivc/lock_header.test.ts @@ -1,12 +1,12 @@ import { circomkit, WitnessTester, toByte } from "../../common"; import { readHTTPInputFile } from "../../common/http"; +import { dataHasher } from "../../full/full.test"; describe("HTTPLockHeader", async () => { - let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; - let lockHeaderCircuit: WitnessTester<["step_in", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; + let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; + let lockHeaderCircuit: WitnessTester<["step_in", "data", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; - const DATA_BYTES = 320; - const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; + const DATA_BYTES = 336; const MAX_BEGINNING_LENGTH = 10; const MAX_MIDDLE_LENGTH = 50; @@ -32,7 +32,8 @@ describe("HTTPLockHeader", async () => { function generatePassCase(input: number[], beginning: number[], middle: number[], final: number[], headerName: number[], headerValue: number[], desc: string) { it(`should pass: \"${headerName}: ${headerValue}\", ${desc}`, async () => { - let extendedInput = input.concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - input.length)).fill(0)); + let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); + const http_response_hash = dataHasher(extendedInput); let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); @@ -41,15 +42,16 @@ describe("HTTPLockHeader", async () => { let headerNamePadded = headerName.concat(Array(MAX_HEADER_NAME_LENGTH - headerName.length).fill(0)); let headerValuePadded = headerValue.concat(Array(MAX_HEADER_VALUE_LENGTH - headerValue.length).fill(0)); - let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: http_response_hash, data: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - await lockHeaderCircuit.expectPass({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }); + await lockHeaderCircuit.expectPass({ step_in: parseAndLockStartLine.step_out, data: extendedInput, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }); }); } function generateFailCase(input: number[], beginning: number[], middle: number[], final: number[], headerName: number[], headerValue: number[], desc: string) { it(`should fail: ${desc}`, async () => { - let extendedInput = input.concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - input.length)).fill(0)); + let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); + const http_response_hash = dataHasher(extendedInput); let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); @@ -58,9 +60,9 @@ describe("HTTPLockHeader", async () => { let headerNamePadded = headerName.concat(Array(MAX_HEADER_NAME_LENGTH - headerName.length).fill(0)); let headerValuePadded = headerValue.concat(Array(MAX_HEADER_VALUE_LENGTH - headerValue.length).fill(0)); - let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: http_response_hash, data: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); - await lockHeaderCircuit.expectFail({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }); + await lockHeaderCircuit.expectFail({ step_in: parseAndLockStartLine.step_out, data: extendedInput, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }); }); } diff --git a/circuits/test/http/nivc/parse_and_lock_start_line.test.ts b/circuits/test/http/nivc/parse_and_lock_start_line.test.ts index ff0c29b..c525842 100644 --- a/circuits/test/http/nivc/parse_and_lock_start_line.test.ts +++ b/circuits/test/http/nivc/parse_and_lock_start_line.test.ts @@ -1,11 +1,11 @@ import { circomkit, WitnessTester, toByte } from "../../common"; import { readHTTPInputFile } from "../../common/http"; +import { dataHasher } from "../../full/full.test"; describe("HTTPParseAndLockStartLine", async () => { - let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; + let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; - const DATA_BYTES = 320; - const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; + const DATA_BYTES = 336; const MAX_BEGINNING_LENGTH = 10; const MAX_MIDDLE_LENGTH = 50; @@ -22,25 +22,28 @@ describe("HTTPParseAndLockStartLine", async () => { function generatePassCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { it(`(valid) witness: ${desc}`, async () => { - let extendedInput = input.concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - input.length)).fill(0)); + let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); + const http_response_hash = dataHasher(extendedInput); let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); - await httpParseAndLockStartLineCircuit.expectPass({ step_in: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }); + await httpParseAndLockStartLineCircuit.expectPass({ step_in: [http_response_hash], data: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }); }); } function generateFailCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { it(`(valid) witness: ${desc}`, async () => { - let extendedInput = input.concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - input.length)).fill(0)); + let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); + const http_response_hash = dataHasher(extendedInput); + let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); - await httpParseAndLockStartLineCircuit.expectFail({ step_in: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }); + await httpParseAndLockStartLineCircuit.expectFail({ step_in: [http_response_hash], data: extendedInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }); }); } From 6efe92fa537f6a11bb0c0557cc5ab0ebc1c77e78 Mon Sep 17 00:00:00 2001 From: lonerapier Date: Mon, 11 Nov 2024 17:03:45 +0530 Subject: [PATCH 14/19] extract final test passes --- circuits/json/nivc/extractor.circom | 40 +++++++++++++++++------------ circuits/test/full/full.test.ts | 25 +++++++++++------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/circuits/json/nivc/extractor.circom b/circuits/json/nivc/extractor.circom index b5ba6b3..5df4839 100644 --- a/circuits/json/nivc/extractor.circom +++ b/circuits/json/nivc/extractor.circom @@ -2,40 +2,46 @@ pragma circom 2.1.9; include "circomlib/circuits/gates.circom"; include "@zk-email/circuits/utils/array.circom"; +include "../../utils/hash.circom"; template MaskExtractFinal(DATA_BYTES, MAX_VALUE_LENGTH) { // ------------------------------------------------------------------------------------------------------------------ // - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes pt/ct + ctr - // ------------------------------------------------------------------------------------------------------------------ // - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; + signal input step_in[1]; + signal input data[DATA_BYTES]; + + signal output step_out[1]; signal is_zero_mask[DATA_BYTES]; signal is_prev_starting_index[DATA_BYTES]; signal value_starting_index[DATA_BYTES]; - signal data[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - } + // for (var i = 0 ; i < DATA_BYTES ; i++) { + // data[i] <== step_in[i]; + // } + signal data_hash <== DataHasher(DATA_BYTES)(data); + data_hash === step_in[0]; value_starting_index[0] <== 0; is_prev_starting_index[0] <== 0; - is_zero_mask[0] <== IsZero()(step_in[0]); + is_zero_mask[0] <== IsZero()(data[0]); for (var i=1 ; i < DATA_BYTES ; i++) { - is_zero_mask[i] <== IsZero()(step_in[i]); + is_zero_mask[i] <== IsZero()(data[i]); is_prev_starting_index[i] <== IsZero()(value_starting_index[i-1]); value_starting_index[i] <== value_starting_index[i-1] + i * (1-is_zero_mask[i]) * is_prev_starting_index[i]; } // TODO: Clear step out? signal value[MAX_VALUE_LENGTH] <== SelectSubArray(DATA_BYTES, MAX_VALUE_LENGTH)(data, value_starting_index[DATA_BYTES-1], MAX_VALUE_LENGTH); - for (var i = 0 ; i < MAX_VALUE_LENGTH ; i++) { - // log(i, value[i]); - step_out[i] <== value[i]; - } - for (var i = MAX_VALUE_LENGTH ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { - step_out[i] <== 0; - } + + step_out[0] <== DataHasher(MAX_VALUE_LENGTH)(value); + // for (var i = 0 ; i < MAX_VALUE_LENGTH ; i++) { + // // log(i, value[i]); + // step_out[i] <== value[i]; + // } + // for (var i = MAX_VALUE_LENGTH ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { + // step_out[i] <== 0; + // } + + // TODO: Do anything with last depth? // step_out[TOTAL_BYTES_ACROSS_NIVC - 1] <== 0; } \ No newline at end of file diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index fd87b82..8182a20 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -196,7 +196,7 @@ describe("NIVC_FULL", async () => { let bodyMaskCircuit: WitnessTester<["step_in", "data"], ["step_out"]>; let json_mask_object_circuit: WitnessTester<["step_in", "data", "key", "keyLen"], ["step_out"]>; let json_mask_arr_circuit: WitnessTester<["step_in", "data", "index"], ["step_out"]>; - // let extract_value_circuit: WitnessTester<["step_in"], ["step_out"]>; + let extract_value_circuit: WitnessTester<["step_in", "data"], ["step_out"]>; const DATA_BYTES = 320; const MAX_STACK_HEIGHT = 5; @@ -212,7 +212,8 @@ describe("NIVC_FULL", async () => { const final = [79, 75]; // OK const MAX_KEY_LENGTH = 8; - const MAX_VALUE_LENGTH = 35; + // TODO (Sambhav): max value length has to be divisible to 16 + const MAX_VALUE_LENGTH = 32; before(async () => { aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { @@ -256,12 +257,12 @@ describe("NIVC_FULL", async () => { }); console.log("#constraints (JSON-MASK-ARRAY-INDEX):", await json_mask_arr_circuit.getConstraintCount()); - // extract_value_circuit = await circomkit.WitnessTester(`JsonMaskExtractFinal`, { - // file: "json/nivc/extractor", - // template: "MaskExtractFinal", - // params: [DATA_BYTES, MAX_VALUE_LENGTH], - // }); - // console.log("#constraints (JSON-MASK-EXTRACT-FINAL):", await extract_value_circuit.getConstraintCount()); + extract_value_circuit = await circomkit.WitnessTester(`JsonMaskExtractFinal`, { + file: "json/nivc/extractor", + template: "MaskExtractFinal", + params: [DATA_BYTES, MAX_VALUE_LENGTH], + }); + console.log("#constraints (JSON-MASK-EXTRACT-FINAL):", await extract_value_circuit.getConstraintCount()); }); @@ -338,6 +339,12 @@ describe("NIVC_FULL", async () => { console.log("JSON Extract key3 `step_out`:", json_extract_key3.step_out); // TODO (autoparallel): we need to rethink extraction here. - // await extract_value_circuit.expectPass({ step_in: json_extract_key3.step_out }, { step_out: value }); + let finalOutput = toByte("\"Taylor Swift\""); + let finalOutputPadded = finalOutput.concat(Array(Math.max(0, MAX_VALUE_LENGTH - finalOutput.length)).fill(0)); + let final_value_hash = dataHasher(finalOutputPadded); + // await extract_value_circuit.expectPass({ step_in: json_extract_key3.step_out, data: json_key3_mask }, { step_out: final_value_hash }); + let extractValue = await extract_value_circuit.compute({ step_in: json_extract_key3.step_out, data: json_key3_mask }, ["step_out"]); + console.log("finalValue", extractValue.step_out); + assert.deepEqual(extractValue.step_out, final_value_hash); }); }); \ No newline at end of file From 0940c0bff165c9b27d3244c33eb8cb18b30a7da4 Mon Sep 17 00:00:00 2001 From: lonerapier Date: Mon, 11 Nov 2024 17:42:39 +0530 Subject: [PATCH 15/19] move dataHasher to common --- circuits/test/common/poseidon.ts | 23 ++++++++++ circuits/test/full/full.test.ts | 43 +++++-------------- circuits/test/http/nivc/body_mask.test.ts | 8 ++-- circuits/test/http/nivc/lock_header.test.ts | 6 +-- .../nivc/parse_and_lock_start_line.test.ts | 6 +-- 5 files changed, 42 insertions(+), 44 deletions(-) diff --git a/circuits/test/common/poseidon.ts b/circuits/test/common/poseidon.ts index b6a06b5..62509cc 100644 --- a/circuits/test/common/poseidon.ts +++ b/circuits/test/common/poseidon.ts @@ -71,4 +71,27 @@ export function PoseidonModular(input: Array): bigint } return result; +} + +export function DataHasher(input: number[]): bigint { + if (input.length % 16 !== 0) { + throw new Error("DATA_BYTES must be divisible by 16"); + } + + let hashes: bigint[] = [BigInt(0)]; // Initialize first hash as 0 + + for (let i = 0; i < Math.floor(input.length / 16); i++) { + let packedInput = BigInt(0); + + // Pack 16 bytes into a single number + for (let j = 0; j < 16; j++) { + packedInput += BigInt(input[16 * i + j]) * BigInt(2 ** (8 * j)); + } + + // Compute next hash using previous hash and packed input + hashes.push(PoseidonModular([hashes[i], packedInput])); + } + + // Return the last hash + return hashes[Math.floor(input.length / 16)]; } \ No newline at end of file diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 8182a20..1b5089b 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -1,29 +1,8 @@ import { assert } from "chai"; import { circomkit, WitnessTester, toByte } from "../common"; -import { PoseidonModular } from "../common/poseidon"; +import { DataHasher } from "../common/poseidon"; -export function dataHasher(input: number[]): bigint { - if (input.length % 16 !== 0) { - throw new Error("DATA_BYTES must be divisible by 16"); - } - let hashes: bigint[] = [BigInt(0)]; // Initialize first hash as 0 - - for (let i = 0; i < Math.floor(input.length / 16); i++) { - let packedInput = BigInt(0); - - // Pack 16 bytes into a single number - for (let j = 0; j < 16; j++) { - packedInput += BigInt(input[16 * i + j]) * BigInt(2 ** (8 * j)); - } - - // Compute next hash using previous hash and packed input - hashes.push(PoseidonModular([hashes[i], packedInput])); - } - - // Return the last hash - return hashes[Math.floor(input.length / 16)]; -} // HTTP/1.1 200 OK // content-type: application/json; charset=utf-8 @@ -97,7 +76,7 @@ const http_body = [ 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125, -] +]; const lengthDiff = http_response_plaintext.length - http_body.length; // Create an array of zeros with the length difference @@ -106,8 +85,8 @@ const padding = new Array(lengthDiff).fill(0); // Concatenate the padding with http_body const padded_http_body = [...padding, ...http_body]; -const http_response_hash = dataHasher(http_response_plaintext); -const http_body_mask_hash = dataHasher(padded_http_body); +const http_response_hash = DataHasher(http_response_plaintext); +const http_body_mask_hash = DataHasher(padded_http_body); const json_key0_mask = [ @@ -125,7 +104,7 @@ const json_key0_mask = [ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 0, 0, 0, 0, 0, 0, 0, 0, ]; -const json_key0_mask_hash = dataHasher(json_key0_mask); +const json_key0_mask_hash = DataHasher(json_key0_mask); const json_key1_mask = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -141,7 +120,7 @@ const json_key1_mask = [ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; -const json_key1_mask_hash = dataHasher(json_key1_mask); +const json_key1_mask_hash = DataHasher(json_key1_mask); const json_arr_mask = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -157,7 +136,7 @@ const json_arr_mask = [ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; -const json_arr_mask_hash = dataHasher(json_arr_mask); +const json_arr_mask_hash = DataHasher(json_arr_mask); const json_key2_mask = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -172,7 +151,7 @@ const json_key2_mask = [ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key2_mask_hash = dataHasher(json_key2_mask); +const json_key2_mask_hash = DataHasher(json_key2_mask); const json_key3_mask = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -187,7 +166,7 @@ const json_key3_mask = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key3_mask_hash = dataHasher(json_key3_mask); +const json_key3_mask_hash = DataHasher(json_key3_mask); describe("NIVC_FULL", async () => { let aesCircuit: WitnessTester<["key", "iv", "aad", "ctr", "plainText", "cipherText", "step_in"], ["step_out"]>; @@ -212,7 +191,6 @@ describe("NIVC_FULL", async () => { const final = [79, 75]; // OK const MAX_KEY_LENGTH = 8; - // TODO (Sambhav): max value length has to be divisible to 16 const MAX_VALUE_LENGTH = 32; before(async () => { @@ -341,8 +319,7 @@ describe("NIVC_FULL", async () => { // TODO (autoparallel): we need to rethink extraction here. let finalOutput = toByte("\"Taylor Swift\""); let finalOutputPadded = finalOutput.concat(Array(Math.max(0, MAX_VALUE_LENGTH - finalOutput.length)).fill(0)); - let final_value_hash = dataHasher(finalOutputPadded); - // await extract_value_circuit.expectPass({ step_in: json_extract_key3.step_out, data: json_key3_mask }, { step_out: final_value_hash }); + let final_value_hash = DataHasher(finalOutputPadded); let extractValue = await extract_value_circuit.compute({ step_in: json_extract_key3.step_out, data: json_key3_mask }, ["step_out"]); console.log("finalValue", extractValue.step_out); assert.deepEqual(extractValue.step_out, final_value_hash); diff --git a/circuits/test/http/nivc/body_mask.test.ts b/circuits/test/http/nivc/body_mask.test.ts index f1d8ec6..04067cb 100644 --- a/circuits/test/http/nivc/body_mask.test.ts +++ b/circuits/test/http/nivc/body_mask.test.ts @@ -1,6 +1,6 @@ import { circomkit, WitnessTester, toByte } from "../../common"; import { assert } from "chai"; -import { dataHasher } from "../../full/full.test"; +import { DataHasher } from "../../common/poseidon"; // HTTP/1.1 200 OK // content-type: application/json; charset=utf-8 @@ -62,8 +62,8 @@ const padding = new Array(lengthDiff).fill(0); // Concatenate the padding with http_body const padded_http_body = [...padding, ...http_body]; -const http_response_hash = dataHasher(http_response_plaintext); -const http_body_mask_hash = dataHasher(padded_http_body); +const http_response_hash = DataHasher(http_response_plaintext); +const http_body_mask_hash = DataHasher(padded_http_body); describe("NIVC_HTTP", async () => { let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; @@ -123,7 +123,5 @@ describe("NIVC_HTTP", async () => { console.log("GOT TRHOUGH THIRD CIRCUIT"); assert.deepEqual(bodyMask.step_out, http_body_mask_hash); - - // bodyMask.step_out === PoseidonModular(maskedInput); }); }); \ No newline at end of file diff --git a/circuits/test/http/nivc/lock_header.test.ts b/circuits/test/http/nivc/lock_header.test.ts index ebc7e78..14cc914 100644 --- a/circuits/test/http/nivc/lock_header.test.ts +++ b/circuits/test/http/nivc/lock_header.test.ts @@ -1,6 +1,6 @@ import { circomkit, WitnessTester, toByte } from "../../common"; import { readHTTPInputFile } from "../../common/http"; -import { dataHasher } from "../../full/full.test"; +import { DataHasher } from "../../common/poseidon"; describe("HTTPLockHeader", async () => { let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; @@ -33,7 +33,7 @@ describe("HTTPLockHeader", async () => { function generatePassCase(input: number[], beginning: number[], middle: number[], final: number[], headerName: number[], headerValue: number[], desc: string) { it(`should pass: \"${headerName}: ${headerValue}\", ${desc}`, async () => { let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); - const http_response_hash = dataHasher(extendedInput); + const http_response_hash = DataHasher(extendedInput); let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); @@ -51,7 +51,7 @@ describe("HTTPLockHeader", async () => { function generateFailCase(input: number[], beginning: number[], middle: number[], final: number[], headerName: number[], headerValue: number[], desc: string) { it(`should fail: ${desc}`, async () => { let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); - const http_response_hash = dataHasher(extendedInput); + const http_response_hash = DataHasher(extendedInput); let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); diff --git a/circuits/test/http/nivc/parse_and_lock_start_line.test.ts b/circuits/test/http/nivc/parse_and_lock_start_line.test.ts index c525842..202650c 100644 --- a/circuits/test/http/nivc/parse_and_lock_start_line.test.ts +++ b/circuits/test/http/nivc/parse_and_lock_start_line.test.ts @@ -1,6 +1,6 @@ import { circomkit, WitnessTester, toByte } from "../../common"; import { readHTTPInputFile } from "../../common/http"; -import { dataHasher } from "../../full/full.test"; +import { DataHasher } from "../../common/poseidon"; describe("HTTPParseAndLockStartLine", async () => { let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "data", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; @@ -23,7 +23,7 @@ describe("HTTPParseAndLockStartLine", async () => { function generatePassCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { it(`(valid) witness: ${desc}`, async () => { let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); - const http_response_hash = dataHasher(extendedInput); + const http_response_hash = DataHasher(extendedInput); let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); @@ -36,7 +36,7 @@ describe("HTTPParseAndLockStartLine", async () => { function generateFailCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { it(`(valid) witness: ${desc}`, async () => { let extendedInput = input.concat(Array(Math.max(0, DATA_BYTES - input.length)).fill(0)); - const http_response_hash = dataHasher(extendedInput); + const http_response_hash = DataHasher(extendedInput); let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); From c4957f99984fd7e05f2b56cd95601d1d479c8c46 Mon Sep 17 00:00:00 2001 From: lonerapier Date: Mon, 11 Nov 2024 17:43:05 +0530 Subject: [PATCH 16/19] circuit fmt --- circuits/json/nivc/extractor.circom | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/circuits/json/nivc/extractor.circom b/circuits/json/nivc/extractor.circom index 5df4839..f2de60f 100644 --- a/circuits/json/nivc/extractor.circom +++ b/circuits/json/nivc/extractor.circom @@ -5,7 +5,6 @@ include "@zk-email/circuits/utils/array.circom"; include "../../utils/hash.circom"; template MaskExtractFinal(DATA_BYTES, MAX_VALUE_LENGTH) { - // ------------------------------------------------------------------------------------------------------------------ // signal input step_in[1]; signal input data[DATA_BYTES]; @@ -15,9 +14,6 @@ template MaskExtractFinal(DATA_BYTES, MAX_VALUE_LENGTH) { signal is_prev_starting_index[DATA_BYTES]; signal value_starting_index[DATA_BYTES]; - // for (var i = 0 ; i < DATA_BYTES ; i++) { - // data[i] <== step_in[i]; - // } signal data_hash <== DataHasher(DATA_BYTES)(data); data_hash === step_in[0]; @@ -29,19 +25,8 @@ template MaskExtractFinal(DATA_BYTES, MAX_VALUE_LENGTH) { is_prev_starting_index[i] <== IsZero()(value_starting_index[i-1]); value_starting_index[i] <== value_starting_index[i-1] + i * (1-is_zero_mask[i]) * is_prev_starting_index[i]; } - // TODO: Clear step out? + signal value[MAX_VALUE_LENGTH] <== SelectSubArray(DATA_BYTES, MAX_VALUE_LENGTH)(data, value_starting_index[DATA_BYTES-1], MAX_VALUE_LENGTH); step_out[0] <== DataHasher(MAX_VALUE_LENGTH)(value); - // for (var i = 0 ; i < MAX_VALUE_LENGTH ; i++) { - // // log(i, value[i]); - // step_out[i] <== value[i]; - // } - // for (var i = MAX_VALUE_LENGTH ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { - // step_out[i] <== 0; - // } - - - // TODO: Do anything with last depth? - // step_out[TOTAL_BYTES_ACROSS_NIVC - 1] <== 0; } \ No newline at end of file From 4d37248519061f6a953e3bc37761b9b7bed27bdf Mon Sep 17 00:00:00 2001 From: lonerapier Date: Mon, 11 Nov 2024 17:43:15 +0530 Subject: [PATCH 17/19] fix json masker test --- circuits/test/json/nivc/masker_nivc.test.ts | 1104 ++++++++++++++++++- 1 file changed, 1090 insertions(+), 14 deletions(-) diff --git a/circuits/test/json/nivc/masker_nivc.test.ts b/circuits/test/json/nivc/masker_nivc.test.ts index 455dd89..d70bbab 100644 --- a/circuits/test/json/nivc/masker_nivc.test.ts +++ b/circuits/test/json/nivc/masker_nivc.test.ts @@ -1,5 +1,6 @@ import { circomkit, WitnessTester, generateDescription, readJsonFile, toByte } from "../../common"; -import { join } from "path"; +import { DataHasher } from "../../common/poseidon"; +import { assert } from "chai"; // HTTP/1.1 200 OK // content-type: application/json; charset=utf-8 @@ -30,16 +31,1075 @@ let json_input = [123, 13, 10, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 123 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; +const json_key0_mask = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 105, + 116, + 101, + 109, + 115, + 34, + 58, + 32, + 91, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 100, + 97, + 116, + 97, + 34, + 58, + 32, + 34, + 65, + 114, + 116, + 105, + 115, + 116, + 34, + 44, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 112, + 114, + 111, + 102, + 105, + 108, + 101, + 34, + 58, + 32, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 84, + 97, + 121, + 108, + 111, + 114, + 32, + 83, + 119, + 105, + 102, + 116, + 34, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 93, + 13, + 10, + 32, + 32, + 32, + 125, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +]; +const json_key0_mask_hash = DataHasher(json_key0_mask); + +const json_key1_mask = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 91, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 100, + 97, + 116, + 97, + 34, + 58, + 32, + 34, + 65, + 114, + 116, + 105, + 115, + 116, + 34, + 44, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 112, + 114, + 111, + 102, + 105, + 108, + 101, + 34, + 58, + 32, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 84, + 97, + 121, + 108, + 111, + 114, + 32, + 83, + 119, + 105, + 102, + 116, + 34, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 93, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +]; +const json_key1_mask_hash = DataHasher(json_key1_mask); + +const json_arr_mask = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 100, + 97, + 116, + 97, + 34, + 58, + 32, + 34, + 65, + 114, + 116, + 105, + 115, + 116, + 34, + 44, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 112, + 114, + 111, + 102, + 105, + 108, + 101, + 34, + 58, + 32, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 84, + 97, + 121, + 108, + 111, + 114, + 32, + 83, + 119, + 105, + 102, + 116, + 34, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 0, + 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 json_arr_mask_hash = DataHasher(json_arr_mask); + +const json_key2_mask = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 84, + 97, + 121, + 108, + 111, + 114, + 32, + 83, + 119, + 105, + 102, + 116, + 34, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 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 json_key2_mask_hash = DataHasher(json_key2_mask); + +const json_key3_mask = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 34, + 84, + 97, + 121, + 108, + 111, + 114, + 32, + 83, + 119, + 105, + 102, + 116, + 34, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 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 json_key3_mask_hash = DataHasher(json_key3_mask); + describe("NIVC Extract", async () => { - let json_mask_object_circuit: WitnessTester<["step_in", "key", "keyLen"], ["step_out"]>; - let json_mask_arr_circuit: WitnessTester<["step_in", "index"], ["step_out"]>; - let extract_value_circuit: WitnessTester<["step_in"], ["step_out"]>; + let json_mask_object_circuit: WitnessTester<["step_in", "data", "key", "keyLen"], ["step_out"]>; + let json_mask_arr_circuit: WitnessTester<["step_in", "data", "index"], ["step_out"]>; + let extract_value_circuit: WitnessTester<["step_in", "data"], ["step_out"]>; - const DATA_BYTES = 202; + const DATA_BYTES = 208; const MAX_STACK_HEIGHT = 5; const MAX_KEY_LENGTH = 8; - const MAX_VALUE_LENGTH = 35; - const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; + const MAX_VALUE_LENGTH = 32; before(async () => { json_mask_arr_circuit = await circomkit.WitnessTester(`JsonMaskArrayIndexNIVC`, { @@ -64,7 +1124,6 @@ describe("NIVC Extract", async () => { console.log("#constraints:", await extract_value_circuit.getConstraintCount()); }); - let extended_json_input = json_input.concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - json_input.length)).fill(0)); let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data" let key0Len = 4; @@ -79,17 +1138,34 @@ describe("NIVC Extract", async () => { it("parse and mask", async () => { - let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: extended_json_input, key: key0, keyLen: key0Len }, ["step_out"]); + console.log(json_input.length); + let extended_json_input = json_input.concat(Array(Math.max(0, DATA_BYTES - json_input.length)).fill(0)); + + let jsonInputHash = DataHasher(extended_json_input); + let json_extract_key0 = await json_mask_object_circuit.compute({ step_in: jsonInputHash, data: extended_json_input, key: key0, keyLen: key0Len }, ["step_out"]); + console.log("JSON Extract key0 `step_out`:", json_extract_key0.step_out); + assert.deepEqual(json_extract_key0.step_out, json_key0_mask_hash); - let json_extract_key1 = await json_mask_object_circuit.compute({ step_in: json_extract_key0.step_out, key: key1, keyLen: key1Len }, ["step_out"]); + let json_extract_key1 = await json_mask_object_circuit.compute({ step_in: json_extract_key0.step_out, data: json_key0_mask, key: key1, keyLen: key1Len }, ["step_out"]); + assert.deepEqual(json_extract_key1.step_out, json_key1_mask_hash); + console.log("JSON Extract key1 `step_out`:", json_extract_key1.step_out); - let json_extract_arr = await json_mask_arr_circuit.compute({ step_in: json_extract_key1.step_out, index: 0 }, ["step_out"]); + let json_extract_arr = await json_mask_arr_circuit.compute({ step_in: json_extract_key1.step_out, index: 0, data: json_key1_mask }, ["step_out"]); + assert.deepEqual(json_extract_arr.step_out, json_arr_mask_hash); + console.log("JSON Extract arr `step_out`:", json_extract_arr.step_out); - let json_extract_key2 = await json_mask_object_circuit.compute({ step_in: json_extract_arr.step_out, key: key2, keyLen: key2Len }, ["step_out"]); + let json_extract_key2 = await json_mask_object_circuit.compute({ step_in: json_extract_arr.step_out, data: json_arr_mask, key: key2, keyLen: key2Len }, ["step_out"]); + assert.deepEqual(json_extract_key2.step_out, json_key2_mask_hash); + console.log("JSON Extract key2 `step_out`:", json_extract_key2.step_out); - let json_extract_key3 = await json_mask_object_circuit.compute({ step_in: json_extract_key2.step_out, key: key3, keyLen: key3Len }, ["step_out"]); + let json_extract_key3 = await json_mask_object_circuit.compute({ step_in: json_extract_key2.step_out, data: json_key2_mask, key: key3, keyLen: key3Len }, ["step_out"]); + assert.deepEqual(json_extract_key3.step_out, json_key3_mask_hash); + console.log("JSON Extract key3 `step_out`:", json_extract_key3.step_out); value = value.concat(Array(MAX_VALUE_LENGTH - value.length).fill(0)); - await extract_value_circuit.expectPass({ step_in: json_extract_key3.step_out }, { step_out: value }); + let final_value_hash = DataHasher(value); + let extractValue = await extract_value_circuit.compute({ step_in: json_extract_key3.step_out, data: json_key3_mask }, ["step_out"]); + console.log("JSON Extract finalValue `step_out`:", extractValue.step_out); + assert.deepEqual(extractValue.step_out, final_value_hash); }); }); \ No newline at end of file From afb78758224d70b81b488eb3916964f8bdb7a8a8 Mon Sep 17 00:00:00 2001 From: lonerapier Date: Mon, 11 Nov 2024 18:04:02 +0530 Subject: [PATCH 18/19] fix the formatting --- circuits/test/json/nivc/masker_nivc.test.ts | 656 +------------------- 1 file changed, 22 insertions(+), 634 deletions(-) diff --git a/circuits/test/json/nivc/masker_nivc.test.ts b/circuits/test/json/nivc/masker_nivc.test.ts index d70bbab..425569d 100644 --- a/circuits/test/json/nivc/masker_nivc.test.ts +++ b/circuits/test/json/nivc/masker_nivc.test.ts @@ -31,428 +31,26 @@ let json_input = [123, 13, 10, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 123 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; -const json_key0_mask = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 105, - 116, - 101, - 109, - 115, - 34, - 58, - 32, - 91, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 100, - 97, - 116, - 97, - 34, - 58, - 32, - 34, - 65, - 114, - 116, - 105, - 115, - 116, - 34, - 44, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 112, - 114, - 111, - 102, - 105, - 108, - 101, - 34, - 58, - 32, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 110, - 97, - 109, - 101, - 34, - 58, - 32, - 34, - 84, - 97, - 121, - 108, - 111, - 114, - 32, - 83, - 119, - 105, - 102, - 116, - 34, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 93, - 13, - 10, - 32, - 32, - 32, - 125, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -]; -const json_key0_mask_hash = DataHasher(json_key0_mask); - -const json_key1_mask = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 91, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 100, - 97, - 116, - 97, - 34, - 58, - 32, - 34, - 65, - 114, - 116, - 105, - 115, - 116, - 34, - 44, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 112, - 114, - 111, - 102, - 105, - 108, - 101, - 34, - 58, - 32, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 110, - 97, - 109, - 101, - 34, - 58, - 32, - 34, - 84, - 97, - 121, - 108, - 111, - 114, - 32, - 83, - 119, - 105, - 102, - 116, - 34, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 93, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -]; +const json_key0_mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, + 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, + 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, 111, 102, 105, 108, 101, 34, 58, 32, 123, 13, 10, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, + 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, + 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0]; +const json_key0_mask_hash = DataHasher(json_key0_mask); + +const json_key1_mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, + 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 34, 112, 114, 111, 102, 105, 108, 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, + 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, + 32, 32, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; const json_key1_mask_hash = DataHasher(json_key1_mask); const json_arr_mask = [ @@ -667,8 +265,7 @@ const json_arr_mask = [ ]; const json_arr_mask_hash = DataHasher(json_arr_mask); -const json_key2_mask = [ - 0, +const json_key2_mask = [0, 0, 0, 0, @@ -879,216 +476,7 @@ const json_key2_mask = [ ]; const json_key2_mask_hash = DataHasher(json_key2_mask); -const json_key3_mask = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 34, - 84, - 97, - 121, - 108, - 111, - 114, - 32, - 83, - 119, - 105, - 102, - 116, - 34, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 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 json_key3_mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key3_mask_hash = DataHasher(json_key3_mask); describe("NIVC Extract", async () => { From 078d44e0fab2a282e7afb4be30e6664d63263512 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 11 Nov 2024 19:52:48 +0700 Subject: [PATCH 19/19] fmt --- circuits/test/json/nivc/masker_nivc.test.ts | 454 ++------------------ 1 file changed, 33 insertions(+), 421 deletions(-) diff --git a/circuits/test/json/nivc/masker_nivc.test.ts b/circuits/test/json/nivc/masker_nivc.test.ts index 425569d..0d9a265 100644 --- a/circuits/test/json/nivc/masker_nivc.test.ts +++ b/circuits/test/json/nivc/masker_nivc.test.ts @@ -21,7 +21,8 @@ import { assert } from "chai"; // } // 202 bytes in the JSON -let json_input = [123, 13, 10, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, +let json_input = [ + 123, 13, 10, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, @@ -31,7 +32,8 @@ let json_input = [123, 13, 10, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 123 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; -const json_key0_mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, +const json_key0_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, @@ -42,7 +44,8 @@ const json_key0_mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 13, 10, 3 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0]; const json_key0_mask_hash = DataHasher(json_key0_mask); -const json_key1_mask = [0, 0, 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 json_key1_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, @@ -53,430 +56,39 @@ const json_key1_mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; const json_key1_mask_hash = DataHasher(json_key1_mask); -const json_arr_mask = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 100, - 97, - 116, - 97, - 34, - 58, - 32, - 34, - 65, - 114, - 116, - 105, - 115, - 116, - 34, - 44, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 112, - 114, - 111, - 102, - 105, - 108, - 101, - 34, - 58, - 32, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 110, - 97, - 109, - 101, - 34, - 58, - 32, - 34, - 84, - 97, - 121, - 108, - 111, - 114, - 32, - 83, - 119, - 105, - 102, - 116, - 34, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 0, - 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 json_arr_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, 116, + 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, 111, 102, 105, + 108, 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, + 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, + 0, 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 json_arr_mask_hash = DataHasher(json_arr_mask); -const json_key2_mask = [0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 110, - 97, - 109, - 101, - 34, - 58, - 32, - 34, - 84, - 97, - 121, - 108, - 111, - 114, - 32, - 83, - 119, - 105, - 102, - 116, - 34, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 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 json_key2_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 110, 97, 109, + 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key2_mask_hash = DataHasher(json_key2_mask); -const json_key3_mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key3_mask = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, 105, 102, 116, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 json_key3_mask_hash = DataHasher(json_key3_mask); describe("NIVC Extract", async () => {