From e116729681b57116f7f033285bce4bd496474391 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 1 Nov 2024 16:53:31 -0600 Subject: [PATCH] fix: tests --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 16 ++-- circuits/aes-gctr-nivc.circom | 2 +- .../test/aes-gcm/nivc/aes-gctr-nivc.test.ts | 86 +++++++++++-------- circuits/test/full/full.test.ts | 14 +-- 4 files changed, 67 insertions(+), 51 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 869bb79..6f7852b 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -25,7 +25,7 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { // 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]; - signal counter; + // We extract the number from the 4 byte word counter component last_counter_bits = BytesToBits(4); @@ -37,10 +37,10 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { 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; - counter <== last_counter_num.out; + // TODO (Colin): We can probably make a template that writes to two multiple arrays at once that saves us even more constraints here instead of just using the `WriteToIndex` twice - // TODO (Colin): We can't call this `WriteToIndex` array this many times, it is too expensive. // write new plain text block. signal prevAccumulatedPlaintext[DATA_BYTES]; for(var i = 0 ; i < DATA_BYTES ; i++) { @@ -50,8 +50,8 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { component writeToIndex = WriteToIndex(DATA_BYTES, 16); writeToIndex.array_to_write_to <== prevAccumulatedPlaintext; writeToIndex.array_to_write_at_index <== plainText; - writeToIndex.index <== counter * 16; - writeToIndex.out ==> nextAccumulatedPlaintext; + writeToIndex.index <== index * 16; + nextAccumulatedPlaintext <== writeToIndex.out; // folds one block component aes = AESGCTRFOLDABLE(); @@ -73,8 +73,8 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { component writeCipherText = WriteToIndex(DATA_BYTES, 16); writeCipherText.array_to_write_to <== prevAccumulatedCiphertext; writeCipherText.array_to_write_at_index <== aes.cipherText; - writeCipherText.index <== counter * 16; - writeCipherText.out ==> nextAccumulatedCiphertext; + writeCipherText.index <== index * 16; + nextAccumulatedCiphertext <== writeCipherText.out; for(var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { if(i < DATA_BYTES) { @@ -83,6 +83,8 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { step_out[i] <== nextAccumulatedCiphertext[i - DATA_BYTES]; } else if(i < 2 * DATA_BYTES + 4) { step_out[i] <== aes.counter[i - (2 * DATA_BYTES)]; + } else { + step_out[i] <== 0; } } } diff --git a/circuits/aes-gctr-nivc.circom b/circuits/aes-gctr-nivc.circom index 2ec7580..6fb0b31 100644 --- a/circuits/aes-gctr-nivc.circom +++ b/circuits/aes-gctr-nivc.circom @@ -3,4 +3,4 @@ pragma circom 2.1.9; include "aes-gcm/nivc/aes-gctr-nivc.circom"; // the circomkit tests become unhappy when there is a main. -component main { public [step_in] } = AESGCTRFOLD(48); \ No newline at end of file +component main { public [step_in] } = AESGCTRFOLD(1024, 5); \ 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 4b63918..6ebd2bb 100644 --- a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts +++ b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts @@ -2,26 +2,36 @@ import { assert } from "chai"; import { WitnessTester } from "circomkit"; import { circomkit } from "../../common"; +const MAX_STACK_HEIGHT = 0; + describe("aes-gctr-nivc", () => { let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad", "step_in"], ["step_out"]>; + + const DATA_BYTES_0 = 16; + const TOTAL_BYTES_ACROSS_NIVC_0 = DATA_BYTES_0 * (MAX_STACK_HEIGHT + 2 + 1) + 1; + 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: [16], // input len is 16 bytes + params: [DATA_BYTES_0, MAX_STACK_HEIGHT], // input len is 16 bytes }); - let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 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 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]; - const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(32).fill(0x00).concat(counter); + const counter = [0x00, 0x00, 0x00, 0x01]; + const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_0).fill(0x00); + counter.forEach((value, index) => { + step_in[2 * DATA_BYTES_0 + index] = value; + }); let expected = plainText.concat(ct).concat([0x00, 0x00, 0x00, 0x02]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_0 - expected.length).fill(0)); const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, expected.map(BigInt)); }); @@ -30,45 +40,55 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [16], // input len is 16 bytes + params: [DATA_BYTES_0, MAX_STACK_HEIGHT], // input len is 16 bytes }); - - let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; + + let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; 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 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]; const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(32).fill(0x00).concat(counter); + const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_0).fill(0x00); + counter.forEach((value, index) => { + step_in[2 * DATA_BYTES_0 + index] = value; + }); let expected = plainText.concat(ct).concat([0x00, 0x00, 0x00, 0x02]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_0 - expected.length).fill(0)); const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, expected.map(BigInt)); }); + const DATA_BYTES_1 = 32; + const TOTAL_BYTES_ACROSS_NIVC_1 = DATA_BYTES_1 * (MAX_STACK_HEIGHT + 2 + 1) + 1; + + 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]; it("all correct for self generated two block case first fold", async () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [32], // input len is 32 bytes + params: [DATA_BYTES_1, MAX_STACK_HEIGHT], // input len is 32 bytes }); - 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]; - const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(64).fill(0x00).concat(counter); + const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_1).fill(0x00); + counter.forEach((value, index) => { + step_in[2 * DATA_BYTES_1 + index] = value; + }); let expected = plainText1.concat(zero_block).concat(ct_part1).concat(zero_block).concat([0x00, 0x00, 0x00, 0x02]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_1 - expected.length).fill(0)); const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, expected.map(BigInt)); @@ -78,21 +98,15 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [32], // input len is 32 bytes + params: [DATA_BYTES_1, MAX_STACK_HEIGHT], // input len is 32 bytes }); - 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]; - const counter = [0x00, 0x00, 0x00, 0x02]; - const step_in = plainText1.concat(zero_block).concat(ct_part1).concat(zero_block).concat(counter); + let step_in = plainText1.concat(zero_block).concat(ct_part1).concat(zero_block).concat(counter); + step_in = step_in.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_1 - step_in.length).fill(0)); + let expected = plainText1.concat(plainText2).concat(ct_part1).concat(ct_part2).concat([0x00, 0x00, 0x00, 0x03]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_1 - expected.length).fill(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)); diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index b04995a..cde3d60 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -88,7 +88,7 @@ describe("NIVC_FULL", async () => { }); - let headerName = toByte("content-type"); + let headerName = toByte("content-type") let headerValue = toByte("application/json; charset=utf-8"); let headerNamePadded = headerName.concat(Array(MAX_HEADER_NAME_LENGTH - headerName.length).fill(0)); @@ -99,21 +99,21 @@ describe("NIVC_FULL", async () => { it("NIVC_CHAIN", async () => { // fold 16 bytes at a time let aes_gcm: CircuitSignals = { step_out: [] }; - console.log("DATA_BYTES", DATA_BYTES); + // console.log("DATA_BYTES", DATA_BYTES); // Run the 0th chunk of plaintext - const init_nivc_input = Array(TOTAL_BYTES_ACROSS_NIVC).fill(0); // Blank array to write chunks to and pass through NIVC chain + 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[2 * DATA_BYTES + index] = value; + }); let pt = http_response_plaintext.slice(0, 16); - console.log("pt", pt); 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++) { - // off by one here let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - console.log("pt", pt); 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"]); } let out = aes_gcm.step_out as number[]; - console.log(JSON.stringify(out)); 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"]);