From 535c8eeb7195af6e99c502899949bbdb003c1987 Mon Sep 17 00:00:00 2001 From: devloper <3347622+devloper@users.noreply.github.com> Date: Tue, 17 Sep 2024 15:33:09 -0400 Subject: [PATCH] Fixup aes-gcm bugs, add self generated test case --- circuits/aes-gcm/aes-gcm.circom | 2 +- circuits/test/aes-gcm.test.ts | 56 ++++++++++++++++++++++++++++----- circuits/test/common/index.ts | 5 +++ src/main.rs | 29 +++++++++++++++++ 4 files changed, 83 insertions(+), 9 deletions(-) diff --git a/circuits/aes-gcm/aes-gcm.circom b/circuits/aes-gcm/aes-gcm.circom index 6cf6dd5..13004e5 100644 --- a/circuits/aes-gcm/aes-gcm.circom +++ b/circuits/aes-gcm/aes-gcm.circom @@ -36,7 +36,7 @@ template AESGCM(l) { signal output authTag[16]; // Authentication tag length is 128 bits (16 bytes) component zeroBlock = ToBlocks(16); - for (var i = 0; i < l; i++) { + for (var i = 0; i < 16; i++) { zeroBlock.stream[i] <== 0; } diff --git a/circuits/test/aes-gcm.test.ts b/circuits/test/aes-gcm.test.ts index 9835fb7..daa67f2 100644 --- a/circuits/test/aes-gcm.test.ts +++ b/circuits/test/aes-gcm.test.ts @@ -1,6 +1,6 @@ import { assert } from "chai"; import { WitnessTester } from "circomkit"; -import { circomkit, hexBytesToBigInt } from "./common"; +import { circomkit, hexBytesToBigInt, hexToBytes } from "./common"; describe("aes-gcm", () => { let circuit: WitnessTester<["key", "iv", "plainText", "aad"], ["cipherText", "tag"]>; @@ -13,19 +13,59 @@ describe("aes-gcm", () => { }); }); - 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 HashKey = [0x66,0xe9,0x4b,0xd4,0xef,0x8a,0x2c,0x3b,0x88,0x4c,0xfa,0x59,0xca,0x34,0x2b,0x2e]; - let aad = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]; - let expected_output = [0x03,0x88,0xda,0xce,0x60,0xb6,0xa3,0x92,0xf3,0x28,0xc2,0xb9,0x71,0xb2,0xfe,0x78]; - it("should have correct output", async () => { + 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]; + // TODO: Fix hashkey. + let HashKey = [0x66,0xe9,0x4b,0xd4,0xef,0x8a,0x2c,0x3b,0x88,0x4c,0xfa,0x59,0xca,0x34,0x2b,0x2e]; + let aad = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]; + let expected_output = [0x03,0x88,0xda,0xce,0x60,0xb6,0xa3,0x92,0xf3,0x28,0xc2,0xb9,0x71,0xb2,0xfe,0x78]; + const witness = await circuit.compute({ key: key, iv: iv, plainText: plainText, aad: aad }, ["cipherText", "authTag"]) assert.deepEqual(witness.cipherText, hexBytesToBigInt(expected_output)) }); + it("should work for self generated test case", async () => { + let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad"], ["cipherText", "tag"]>; + circuit_one_block = await circomkit.WitnessTester(`aes-gcm`, { + file: "aes-gcm/aes-gcm", + template: "AESGCM", + params: [16], + }); + + const key = hexToBytes('31313131313131313131313131313131'); + const iv = hexToBytes('313131313131313131313131'); + const msg = hexToBytes('7465737468656c6c6f30303030303030'); + const aad = hexToBytes('00000000000000000000000000000000') + const ct = hexToBytes('2929d2bb1ae94804402b8e776e0d3356'); + const auth_tag = hexToBytes('0cab39e1a491b092185965f7b554aea0'); + + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: msg, aad: aad }, ["cipherText", "authTag"]) + + assert.deepEqual(witness.cipherText, hexBytesToBigInt(ct)) + }); + + it("should work for multiple blocks", async () => { + let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad"], ["cipherText", "tag"]>; + circuit_one_block = await circomkit.WitnessTester(`aes-gcm`, { + file: "aes-gcm/aes-gcm", + template: "AESGCM", + params: [32], + }); + + const key = hexToBytes('31313131313131313131313131313131'); + const iv = hexToBytes('313131313131313131313131'); + const msg = hexToBytes('7465737468656c6c6f303030303030307465737468656c6c6f30303030303030'); + const aad = hexToBytes('00000000000000000000000000000000') + const ct = hexToBytes('2929d2bb1ae94804402b8e776e0d335626756530713e4c065af1d3c4f56e0204'); + const auth_tag = hexToBytes('438542d7f387568c84d23df60b223ecb'); + + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: msg, aad: aad }, ["cipherText", "authTag"]) + + assert.deepEqual(witness.cipherText, hexBytesToBigInt(ct)) + }); }); // signal input key[16]; // 128-bit key diff --git a/circuits/test/common/index.ts b/circuits/test/common/index.ts index d6441b8..385bcc6 100644 --- a/circuits/test/common/index.ts +++ b/circuits/test/common/index.ts @@ -8,6 +8,11 @@ export const circomkit = new Circomkit({ export { WitnessTester }; + +export function hexToBytes(hex: any) { + return hex.match(/.{1,2}/g).map((byte: any) => parseInt(byte, 16)); +} + export function hexBytesToBigInt(hexBytes: number[]): any[] { return hexBytes.map(byte => { let n = BigInt(byte); diff --git a/src/main.rs b/src/main.rs index 83c53a4..3d7670a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,7 @@ async fn main() -> io::Result<()> { witness.iv.extend_from_slice(&[0, 0, 0, 0]); make_json_witness(&witness, witness::CipherMode::Vanilla).unwrap(); + Ok(()) } @@ -69,4 +70,32 @@ mod tests { // generate proof proof::gen_proof_aes_gcm_siv(&witness, SIV_WTNS, SIV_R1CS); } + + // AES GCM multiple blocks of data + // cargo test test_aes_gcm_blocks -- --show-output + #[tokio::test] + async fn test_aes_gcm_blocks() { + use aes_gcm::{ + aead::{generic_array::GenericArray, Aead, NewAead, Payload}, + Aes128Gcm, + }; + + let test_key = [ + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, + ]; + let test_iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; + + let message = String::from("testhello0000000testhello0000000"); + let aes_payload = Payload { msg: &message.as_bytes(), aad: &[] }; + + let cipher = Aes128Gcm::new_from_slice(&test_key).unwrap(); + let nonce = GenericArray::from_slice(&test_iv); + let ct = cipher.encrypt(nonce, aes_payload).expect("error generating ct"); + + println!("key={}", hex::encode(test_key)); + println!("iv={}", hex::encode(test_iv)); + println!("msg={}", hex::encode(message)); + println!("ct={}", hex::encode(ct)); + } }