From 58c2b70a437ac2fcec635837b9ca796a41baefc6 Mon Sep 17 00:00:00 2001 From: confuseSUN <778398626@qq.com> Date: Tue, 25 Feb 2025 16:36:27 +0800 Subject: [PATCH 1/2] fix bug --- circuits/aes-gcm/gctr.circom | 8 ++-- circuits/aes-gcm/utils.circom | 30 +++---------- circuits/test/aes-gcm/aes-gcm.test.ts | 21 +++++++++ src/main.rs | 63 +++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 29 deletions(-) diff --git a/circuits/aes-gcm/gctr.circom b/circuits/aes-gcm/gctr.circom index bf344ec..1ce5921 100644 --- a/circuits/aes-gcm/gctr.circom +++ b/circuits/aes-gcm/gctr.circom @@ -52,17 +52,17 @@ template GCTR(INPUT_LEN) { plainTextBlocks.stream <== plainText; // Step 1: Generate counter blocks - signal CounterBlocks[nBlocks][4][4]; + signal CounterBlocks[nBlocks + 1][4][4]; CounterBlocks[0] <== initialCounterBlock; // First counter block is passed in, as a combination of the IV right padded with zeros IV is 96 bits or 12 bytes // The next counter needs to be set by incrementing the right most 32 bits (4 bytes) of the previous counter block // // component to increment the last word of the counter block - component inc32[nBlocks - 1]; + component inc32[nBlocks]; // For i = 2 to nBlocks, let CBi = inc32(CBi-1). - for (var i = 1; i < nBlocks; i++) { + for (var i = 1; i < nBlocks + 1; i++) { inc32[i - 1] = IncrementWord(); inc32[i - 1].in <== CounterBlocks[i - 1][3]; @@ -103,7 +103,7 @@ template GCTR(INPUT_LEN) { // encrypt the last counter block aes[nBlocks] = Cipher(); aes[nBlocks].key <== key; - aes[nBlocks].block <== CounterBlocks[nBlocks-1]; + aes[nBlocks].block <== CounterBlocks[nBlocks]; component aesCipherToStream = ToStream(1, 16); aesCipherToStream.blocks[0] <== aes[nBlocks].cipher; diff --git a/circuits/aes-gcm/utils.circom b/circuits/aes-gcm/utils.circom index 01167c3..b3dc313 100644 --- a/circuits/aes-gcm/utils.circom +++ b/circuits/aes-gcm/utils.circom @@ -112,7 +112,6 @@ template BitwiseRightShift(n, r) { } } - template BitwiseXor(n) { signal input a[n]; signal input b[n]; @@ -135,26 +134,7 @@ template BitwiseOr(n) { } } -// compute the OR of n inputs, each m bits wide -template OrMultiple(n, m) { - signal input inputs[n][m]; - signal output out[m]; - - signal mids[n][m]; - mids[0] <== inputs[0]; - - component ors[n-1]; - for(var i=0; i { assert.deepEqual(witness.cipherText, hexBytesToBigInt(ct)) // assert.deepEqual(witness.authTag, hexBytesToBigInt(auth_tag)); }); + + it("should work in case of non-integer multiples of block size", 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: [30], + }); + + const key = hexToBytes('31313131313131313131313131313131'); + const iv = hexToBytes('313131313131313131313131'); + const msg = hexToBytes('7465737468656c6c6f776f726c64307465737468656c6c6f776f726c6431'); + const aad = hexToBytes('00000000000000000000000000000000') + const ct = hexToBytes('2929d2bb1ae94804406cd135325933123763622c7c374c0542ae9198a16f'); + const auth_tag = hexToBytes('31837b1974685501be791364a586fa6e'); + + const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: msg, aad: aad }, ["cipherText", "authTag"]) + + assert.deepEqual(witness.cipherText, hexBytesToBigInt(ct)) + // assert.deepEqual(witness.authTag, hexBytesToBigInt(auth_tag)); + }); }); // signal input key[16]; // 128-bit key diff --git a/src/main.rs b/src/main.rs index bc8d131..917b157 100644 --- a/src/main.rs +++ b/src/main.rs @@ -98,6 +98,69 @@ mod tests { println!("ct={}", hex::encode(ct)); } + // AES GCM multiple blocks of data + // cargo test test_aes_gcm_10_blocks -- --show-output + #[tokio::test] + async fn test_aes_gcm_10_blocks1() { + 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 mut payload: Vec = Vec::new(); + for last_byte in 0..10 { + let message = format!("testhello000000{}", last_byte); + payload.extend(message.as_bytes()); + } + let aes_payload = Payload { msg: &payload, 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(payload)); + println!("ct={}", hex::encode(ct)); + } + + /// Test AES-GCM with data length not a multiple of block size + #[tokio::test] + async fn test_aes_gcm_non_multiple_length() { + 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 mut payload: Vec = Vec::new(); + for last_byte in 0..2 { + let message = format!("testhelloworld{}", last_byte); + payload.extend(message.as_bytes()); + } + let aes_payload = Payload { msg: &payload, 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(payload)); + println!("ct={}", hex::encode(ct)); + } + #[tokio::test] async fn test_ghash() { use ghash::{ From e1cbd43550ec2481b9271dc337e261ea4aa36f3e Mon Sep 17 00:00:00 2001 From: confuseSUN <778398626@qq.com> Date: Tue, 25 Feb 2025 16:39:00 +0800 Subject: [PATCH 2/2] remove repeat code --- src/main.rs | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/main.rs b/src/main.rs index 917b157..6ed1fe2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -98,38 +98,6 @@ mod tests { println!("ct={}", hex::encode(ct)); } - // AES GCM multiple blocks of data - // cargo test test_aes_gcm_10_blocks -- --show-output - #[tokio::test] - async fn test_aes_gcm_10_blocks1() { - 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 mut payload: Vec = Vec::new(); - for last_byte in 0..10 { - let message = format!("testhello000000{}", last_byte); - payload.extend(message.as_bytes()); - } - let aes_payload = Payload { msg: &payload, 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(payload)); - println!("ct={}", hex::encode(ct)); - } - /// Test AES-GCM with data length not a multiple of block size #[tokio::test] async fn test_aes_gcm_non_multiple_length() {