Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fixup aes-gcm bugs, add self generated test case #75

Merged
merged 1 commit into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion circuits/aes-gcm/aes-gcm.circom
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
56 changes: 48 additions & 8 deletions circuits/test/aes-gcm.test.ts
Original file line number Diff line number Diff line change
@@ -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"]>;
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions circuits/test/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 29 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}

Expand All @@ -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));
}
}