From eecd5c3d63c9fe0e26e1b0f2e7308483e90c2a73 Mon Sep 17 00:00:00 2001 From: yash1io Date: Thu, 1 Aug 2024 23:10:26 +0530 Subject: [PATCH 1/8] add aes-ctr mode support --- circuits/ctr.circom | 116 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 circuits/ctr.circom diff --git a/circuits/ctr.circom b/circuits/ctr.circom new file mode 100644 index 0000000..3191ccd --- /dev/null +++ b/circuits/ctr.circom @@ -0,0 +1,116 @@ +pragma circom 2.1.8; + +include "cipher.circom"; +include "transformations.circom"; + +template EncryptCTR(l,nk){ + signal input plainText[l]; + signal input iv[16]; + signal input key[nk * 4]; + signal output cipher[l]; + + var n = l\16; + if(l%16 > 0){ + n = n + 1; + } + + component toBlocks[2]; + toBlocks[0] = ToBlocks(l); + toBlocks[0].stream <== plainText; + + component aes[n]; + toBlocks[1] = ToBlocks(16); + toBlocks[1].stream <== iv; + var ivBlock[4][4] = toBlocks[1].blocks[0]; + + signal cipherBlocks[n][4][4]; + component AddCipher[n]; + + for(var i=0;i 0){ + n = n + 1; + } + signal output blocks[n][4][4]; + + var i, j, k; + + for (var idx = 0; idx < l; idx++) { + blocks[i][k][j] <== stream[idx]; + k = k + 1; + if (k == 4){ + k = 0; + j = j + 1; + if (j == 4){ + j = 0; + i = i + 1; + } + } + } + + if (l%16 > 0){ + blocks[i][k][j] <== 1; + k = k + 1; + } +} + +template ToStream(n,l){ + signal input blocks[n][4][4]; + + signal output stream[l]; + + var i, j, k; + + while(i*16 + j*4 + k < l){ + stream[i*16 + j*4 + k] <== blocks[i][k][j]; + k = k + 1; + if (k == 4){ + k = 0; + j = j + 1; + if (j == 4){ + j = 0; + i = i + 1; + } + } + } +} + +template AddCipher(){ + signal input state[4][4]; + signal input cipher[4][4]; + signal output newState[4][4]; + + component xorbyte[4][4]; + + for (var i = 0; i < 4; i++) { + for (var j = 0; j < 4; j++) { + xorbyte[i][j] = XorByte(); + xorbyte[i][j].a <== state[i][j]; + xorbyte[i][j].b <== cipher[i][j]; + newState[i][j] <== xorbyte[i][j].out; + } + } +} \ No newline at end of file From d93ae942ed97c2acee642da6c0eeca282e5776b4 Mon Sep 17 00:00:00 2001 From: yash1io Date: Thu, 1 Aug 2024 23:10:56 +0530 Subject: [PATCH 2/8] tests and minor refactors --- circuits/cipher.circom | 2 +- tests/cipher.test.ts | 32 +++++++ tests/ctr.test.ts | 177 ++++++++++++++++++++++++++++++++++++ tests/key_expansion.test.ts | 6 +- 4 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 tests/ctr.test.ts diff --git a/circuits/cipher.circom b/circuits/cipher.circom index f02d040..50b806f 100644 --- a/circuits/cipher.circom +++ b/circuits/cipher.circom @@ -36,8 +36,8 @@ include "mix_columns.circom"; template Cipher(nk){ assert(nk == 4 || nk == 6 || nk == 8 ); signal input block[4][4]; - signal output cipher[4][4]; signal input key[nk * 4]; + signal output cipher[4][4]; var nr = Rounds(nk); diff --git a/tests/cipher.test.ts b/tests/cipher.test.ts index a2dca0e..4780cb8 100644 --- a/tests/cipher.test.ts +++ b/tests/cipher.test.ts @@ -32,4 +32,36 @@ describe("Cipher", () => { } ); }); + + // in : f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + // out : ec8cdf7398607cb0f2d21675ea9ea1e4 + // key : 2b7e151628aed2a6abf7158809cf4f3c + it("should perform Cipher", async () => { + circuit = await circomkit.WitnessTester(`Cipher`, { + file: "cipher", + template: "Cipher", + params: [4], + }); + console.log("@Cipher #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + block: [ + [0xf0, 0xf4, 0xf8, 0xfc], + [0xf1, 0xf5, 0xf9, 0xfd], + [0xf2, 0xf6, 0xfa, 0xfe], + [0xf3, 0xf7, 0xfb, 0xff], + ], + key: [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c], + }, + { + cipher: [ + [0xec, 0x98, 0xf2, 0xea], + [0x8c, 0x60, 0xd2, 0x9e], + [0xdf, 0x7c, 0x16, 0xa1], + [0x73, 0xb0, 0x75, 0xe4], + ], + } + ); + }); }); diff --git a/tests/ctr.test.ts b/tests/ctr.test.ts new file mode 100644 index 0000000..3be90ac --- /dev/null +++ b/tests/ctr.test.ts @@ -0,0 +1,177 @@ +import { WitnessTester } from "circomkit"; +import { circomkit } from "./common"; + +// todo: should debug cipher +describe("ToBlocks", () => { + let circuit: WitnessTester<["stream"], ["blocks"]>; + it("should convert stream to block", async () => { + circuit = await circomkit.WitnessTester(`ToBlocks`, { + file: "ctr", + template: "ToBlocks", + params: [16], + }); + console.log("@ToBLocks #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + stream: [0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2, 0x34], + }, + { + blocks: [ + [ + [0x32, 0x88, 0x31, 0xe0], + [0x43, 0x5a, 0x31, 0x37], + [0xf6, 0x30, 0x98, 0x07], + [0xa8, 0x8d, 0xa2, 0x34], + ], + ], + } + ); + }); + it("should pad 1 in block", async () => { + circuit = await circomkit.WitnessTester(`ToBlocks`, { + file: "ctr", + template: "ToBlocks", + params: [15], + }); + console.log("@ToBLocks #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + stream: [0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2], + }, + { + blocks: [ + [ + [0x32, 0x88, 0x31, 0xe0], + [0x43, 0x5a, 0x31, 0x37], + [0xf6, 0x30, 0x98, 0x07], + [0xa8, 0x8d, 0xa2, 0x01], + ], + ], + } + ); + }); + it("should pad 0's in block", async () => { + circuit = await circomkit.WitnessTester(`ToBlocks`, { + file: "ctr", + template: "ToBlocks", + params: [14], + }); + console.log("@ToBLocks #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + stream: [0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d], + }, + { + blocks: [ + [ + [0x32, 0x88, 0x31, 0xe0], + [0x43, 0x5a, 0x31, 0x37], + [0xf6, 0x30, 0x98, 0x07], + [0xa8, 0x8d, 0x01, 0x00], + ], + ], + } + ); + }); + it("should generate enough blocks", async () => { + circuit = await circomkit.WitnessTester(`ToBlocks`, { + file: "ctr", + template: "ToBlocks", + params: [17], + }); + console.log("@ToBLocks #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + stream: [0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2, 0x34, 0x12], + }, + { + blocks: [ + [ + [0x32, 0x88, 0x31, 0xe0], + [0x43, 0x5a, 0x31, 0x37], + [0xf6, 0x30, 0x98, 0x07], + [0xa8, 0x8d, 0xa2, 0x34], + ], + [ + [0x12, 0x01, 0x00, 0x00], + [0x00, 0x00, 0x00, 0x00], + [0x00, 0x00, 0x00, 0x00], + [0x00, 0x00, 0x00, 0x00], + ], + ], + } + ); + }); +}); + +describe("EncryptCTR", () => { + let circuit: WitnessTester<["plainText", "iv", "key"], ["cipher"]>; + it("should encrypt 1 block correctly", async () => { + circuit = await circomkit.WitnessTester(`EncryptCTR`, { + file: "ctr", + template: "EncryptCTR", + params: [16, 4], + }); + console.log("@ToBLocks #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + plainText: [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a], + iv: [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff], + key: [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c], + }, + { + cipher: [0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce], + } + ); + }); + + // test vectors borrowed from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CTR.pdf + // Key is + // 2B7E1516 28AED2A6 ABF71588 09CF4F3C + // Plaintext is + // 6BC1BEE2 2E409F96 E93D7E11 7393172A + // AE2D8A57 1E03AC9C 9EB76FAC 45AF8E51 + // 30C81C46 A35CE411 E5FBC119 1A0A52EF + // F69F2445 DF4F9B17 AD2B417B E66C3710 + + // Ciphertext is + // 874D6191 B620E326 1BEF6864 990DB6CE + // 9806F66B 7970FDFF 8617187B B9FFFDFF + // 5AE4DF3E DBD5D35E 5B4F0902 0DB03EAB + // 1E031DDA 2FBE03D1 792170A0 F3009CEE + + it.skip("should encrypt multiple blocks correctly", async () => { + circuit = await circomkit.WitnessTester(`EncryptCTR`, { + file: "ctr", + template: "EncryptCTR", + params: [64, 4], + }); + console.log("@EncryptCTR #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + plainText: [ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, + 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, + 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, + 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + ], + iv: [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff], + key: [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c], + }, + { + cipher: [ + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, + 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, 0x5a, 0xe4, 0xdf, 0x3e, + 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, + 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, + ], + } + ); + }); +}); diff --git a/tests/key_expansion.test.ts b/tests/key_expansion.test.ts index d1ed1f0..2c47838 100644 --- a/tests/key_expansion.test.ts +++ b/tests/key_expansion.test.ts @@ -6,7 +6,7 @@ describe("KeyExpansion", () => { const circuit: WitnessTester<["key"], ["keyExpanded"]> = await circomkit.WitnessTester(`SubBytes`, { file: "key_expansion", template: "KeyExpansion", - params: [4,10], + params: [4, 10], }); console.log("#constraints:", await circuit.getConstraintCount()); const key = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]; @@ -62,7 +62,7 @@ describe("KeyExpansion", () => { const circuit: WitnessTester<["key"], ["keyExpanded"]> = await circomkit.WitnessTester(`SubBytes`, { file: "key_expansion", template: "KeyExpansion", - params: [6,12], + params: [6, 12], }); console.log("#constraints:", await circuit.getConstraintCount()); const key = [ @@ -132,7 +132,7 @@ describe("KeyExpansion", () => { const circuit: WitnessTester<["key"], ["keyExpanded"]> = await circomkit.WitnessTester(`SubBytes`, { file: "key_expansion", template: "KeyExpansion", - params: [8,14], + params: [8, 14], }); console.log("#constraints:", await circuit.getConstraintCount()); const key = [ From d52625a22d21dc86f1b5d1d6f00316b330da48b4 Mon Sep 17 00:00:00 2001 From: yash1io Date: Fri, 2 Aug 2024 10:48:53 +0530 Subject: [PATCH 3/8] added more tests --- circuits/ctr.circom | 5 +- tests/ctr.test.ts | 124 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 107 insertions(+), 22 deletions(-) diff --git a/circuits/ctr.circom b/circuits/ctr.circom index 3191ccd..954da62 100644 --- a/circuits/ctr.circom +++ b/circuits/ctr.circom @@ -26,7 +26,7 @@ template EncryptCTR(l,nk){ signal cipherBlocks[n][4][4]; component AddCipher[n]; - for(var i=0;i { { blocks: [ [ - [0x32, 0x88, 0x31, 0xe0], - [0x43, 0x5a, 0x31, 0x37], - [0xf6, 0x30, 0x98, 0x07], - [0xa8, 0x8d, 0xa2, 0x34], + [0x32, 0x43, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0xa2], + [0xe0, 0x37, 0x07, 0x34], ], ], } @@ -43,10 +43,10 @@ describe("ToBlocks", () => { { blocks: [ [ - [0x32, 0x88, 0x31, 0xe0], - [0x43, 0x5a, 0x31, 0x37], - [0xf6, 0x30, 0x98, 0x07], - [0xa8, 0x8d, 0xa2, 0x01], + [0x32, 0x43, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0xa2], + [0xe0, 0x37, 0x07, 0x01], ], ], } @@ -67,10 +67,10 @@ describe("ToBlocks", () => { { blocks: [ [ - [0x32, 0x88, 0x31, 0xe0], - [0x43, 0x5a, 0x31, 0x37], - [0xf6, 0x30, 0x98, 0x07], - [0xa8, 0x8d, 0x01, 0x00], + [0x32, 0x43, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0x01], + [0xe0, 0x37, 0x07, 0x00], ], ], } @@ -86,19 +86,19 @@ describe("ToBlocks", () => { await circuit.expectPass( { - stream: [0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2, 0x34, 0x12], + stream: [0x32, 0x88, 0x31, 0xe0, 0x42, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2, 0x34, 0x12], }, { blocks: [ [ - [0x32, 0x88, 0x31, 0xe0], - [0x43, 0x5a, 0x31, 0x37], - [0xf6, 0x30, 0x98, 0x07], - [0xa8, 0x8d, 0xa2, 0x34], + [0x32, 0x42, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0xa2], + [0xe0, 0x37, 0x07, 0x34], ], [ - [0x12, 0x01, 0x00, 0x00], - [0x00, 0x00, 0x00, 0x00], + [0x12, 0x00, 0x00, 0x00], + [0x01, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00], ], @@ -145,7 +145,7 @@ describe("EncryptCTR", () => { // 5AE4DF3E DBD5D35E 5B4F0902 0DB03EAB // 1E031DDA 2FBE03D1 792170A0 F3009CEE - it.skip("should encrypt multiple blocks correctly", async () => { + it("should encrypt multiple blocks correctly", async () => { circuit = await circomkit.WitnessTester(`EncryptCTR`, { file: "ctr", template: "EncryptCTR", @@ -175,3 +175,87 @@ describe("EncryptCTR", () => { ); }); }); + +describe("ToStream", () => { + let circuit: WitnessTester<["blocks"], ["stream"]>; + it("should convert blocks to stream#1", async () => { + circuit = await circomkit.WitnessTester(`ToStream`, { + file: "ctr", + template: "ToStream", + params: [1, 16], + }); + console.log("@ToStream #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + blocks: [ + [ + [0x32, 0x43, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0xa2], + [0xe0, 0x37, 0x07, 0x34], + ], + ], + }, + { + stream: [0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2, 0x34], + } + ); + }); + it("should convert blocks to stream#2", async () => { + circuit = await circomkit.WitnessTester(`ToStream`, { + file: "ctr", + template: "ToStream", + params: [1, 15], + }); + console.log("@ToStream #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + blocks: [ + [ + [0x32, 0x43, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0xa2], + [0xe0, 0x37, 0x07, 0x01], + ], + ], + }, + { + stream: [0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2], + } + ); + }); + it("should convert multiple blocks to stream", async () => { + circuit = await circomkit.WitnessTester(`ToStream`, { + file: "ctr", + template: "ToStream", + params: [2, 18], + }); + console.log("@ToStream #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + blocks: [ + [ + [0x32, 0x43, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0xa2], + [0xe0, 0x37, 0x07, 0x01], + ], + [ + [0x32, 0x43, 0xf6, 0xa8], + [0x88, 0x5a, 0x30, 0x8d], + [0x31, 0x31, 0x98, 0xa2], + [0xe0, 0x37, 0x07, 0x01], + ], + ], + }, + { + stream: [ + 0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37, 0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2, 0x01, 0x32, 0x88, + ], + } + ); + }); +}); From 28b612e3e9c47a41170d4a1c97b071994504e97d Mon Sep 17 00:00:00 2001 From: yash1io Date: Fri, 2 Aug 2024 12:14:14 +0530 Subject: [PATCH 4/8] fix tests --- tests/cipher.test.ts | 4 ++-- tests/ctr.test.ts | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/cipher.test.ts b/tests/cipher.test.ts index 4780cb8..1ee70e2 100644 --- a/tests/cipher.test.ts +++ b/tests/cipher.test.ts @@ -4,7 +4,7 @@ import { circomkit } from "./common"; // todo: should debug cipher describe("Cipher", () => { let circuit: WitnessTester<["block", "key"], ["cipher"]>; - it("should perform Cipher", async () => { + it("should perform Cipher#1", async () => { circuit = await circomkit.WitnessTester(`Cipher`, { file: "cipher", template: "Cipher", @@ -36,7 +36,7 @@ describe("Cipher", () => { // in : f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff // out : ec8cdf7398607cb0f2d21675ea9ea1e4 // key : 2b7e151628aed2a6abf7158809cf4f3c - it("should perform Cipher", async () => { + it("should perform Cipher#2", async () => { circuit = await circomkit.WitnessTester(`Cipher`, { file: "cipher", template: "Cipher", diff --git a/tests/ctr.test.ts b/tests/ctr.test.ts index e38c9c3..409bf96 100644 --- a/tests/ctr.test.ts +++ b/tests/ctr.test.ts @@ -139,37 +139,37 @@ describe("EncryptCTR", () => { // 30C81C46 A35CE411 E5FBC119 1A0A52EF // F69F2445 DF4F9B17 AD2B417B E66C3710 - // Ciphertext is + // Cipher text is // 874D6191 B620E326 1BEF6864 990DB6CE // 9806F66B 7970FDFF 8617187B B9FFFDFF // 5AE4DF3E DBD5D35E 5B4F0902 0DB03EAB // 1E031DDA 2FBE03D1 792170A0 F3009CEE - + // Todo : fix ctr for multiple blocks it("should encrypt multiple blocks correctly", async () => { circuit = await circomkit.WitnessTester(`EncryptCTR`, { file: "ctr", template: "EncryptCTR", - params: [64, 4], + params: [16, 4], }); console.log("@EncryptCTR #constraints:", await circuit.getConstraintCount()); await circuit.expectPass( { plainText: [ - 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, - 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, - 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, - 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + // 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + // 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + // 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, ], iv: [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff], key: [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c], }, { cipher: [ - 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, - 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, 0x5a, 0xe4, 0xdf, 0x3e, - 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, - 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + // 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, + // 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, + // 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, ], } ); From 9b3c2bfe75127878882efccc19f811e1e380a80f Mon Sep 17 00:00:00 2001 From: yash1io Date: Sat, 3 Aug 2024 13:51:28 +0530 Subject: [PATCH 5/8] fixed and added ctr --- circuits/ctr.circom | 38 +++++++++++++++++++------- tests/ctr.test.ts | 65 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 19 deletions(-) diff --git a/circuits/ctr.circom b/circuits/ctr.circom index 954da62..dd1ebc6 100644 --- a/circuits/ctr.circom +++ b/circuits/ctr.circom @@ -14,26 +14,25 @@ template EncryptCTR(l,nk){ n = n + 1; } - component toBlocks[2]; - toBlocks[0] = ToBlocks(l); - toBlocks[0].stream <== plainText; + component toBlocks = ToBlocks(l); + toBlocks.stream <== plainText; component aes[n]; - toBlocks[1] = ToBlocks(16); - toBlocks[1].stream <== iv; - var ivBlock[4][4] = toBlocks[1].blocks[0]; signal cipherBlocks[n][4][4]; component AddCipher[n]; + component generateCtrBlocks = GenerateCounterBlocks(n); + generateCtrBlocks.iv <== iv; + signal counterBlocks[n][4][4] <== generateCtrBlocks.counterBlocks; + for(var i = 0 ; i < n; i++){ aes[i] = Cipher(nk); - ivBlock[3][3] = (ivBlock[3][3] + i)%256; aes[i].key <== key; - aes[i].block <-- ivBlock; + aes[i].block <== counterBlocks[i]; AddCipher[i] = AddCipher(); - AddCipher[i].state <== toBlocks[0].blocks[i]; + AddCipher[i].state <== toBlocks.blocks[i]; AddCipher[i].cipher <== aes[i].cipher; cipherBlocks[i] <== AddCipher[i].newState; @@ -114,4 +113,25 @@ template AddCipher(){ newState[i][j] <== xorbyte[i][j].out; } } +} + +// converts iv to counter blocks +// iv is 16 bytes +template GenerateCounterBlocks(n){ + signal input iv[16]; + signal output counterBlocks[n][4][4]; + + var ivr[16] = iv; + + component toBlocks[n]; + + for (var i = 0; i < n; i++) { + toBlocks[i] = ToBlocks(16); + toBlocks[i].stream <-- ivr; + counterBlocks[i] <== toBlocks[i].blocks[0]; + ivr[15] = (ivr[15] + 1)%256; + if (ivr[15] == 0){ + ivr[14] = (ivr[14] + 1)%256; + } + } } \ No newline at end of file diff --git a/tests/ctr.test.ts b/tests/ctr.test.ts index 409bf96..af0c858 100644 --- a/tests/ctr.test.ts +++ b/tests/ctr.test.ts @@ -144,32 +144,31 @@ describe("EncryptCTR", () => { // 9806F66B 7970FDFF 8617187B B9FFFDFF // 5AE4DF3E DBD5D35E 5B4F0902 0DB03EAB // 1E031DDA 2FBE03D1 792170A0 F3009CEE - // Todo : fix ctr for multiple blocks it("should encrypt multiple blocks correctly", async () => { circuit = await circomkit.WitnessTester(`EncryptCTR`, { file: "ctr", template: "EncryptCTR", - params: [16, 4], + params: [64, 4], }); console.log("@EncryptCTR #constraints:", await circuit.getConstraintCount()); await circuit.expectPass( { plainText: [ - 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - // 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - // 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - // 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, + 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, ], iv: [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff], key: [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c], }, { cipher: [ - 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, - // 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, - // 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, - // 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, + 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, + 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, + 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, ], } ); @@ -259,3 +258,49 @@ describe("ToStream", () => { ); }); }); + +describe("GenerateCounterBlocks", async () => { + let circuit: WitnessTester<["iv"], ["counterBlocks"]>; + it("should generate counter blocks correctly", async () => { + circuit = await circomkit.WitnessTester(`GenerateCounterBlocks`, { + file: "ctr", + template: "GenerateCounterBlocks", + params: [4], + }); + console.log("@GenerateCounterBlocks #constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass( + { + iv: [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff], + }, + { + counterBlocks: [ + [ + [0xf0, 0xf4, 0xf8, 0xfc], + [0xf1, 0xf5, 0xf9, 0xfd], + [0xf2, 0xf6, 0xfa, 0xfe], + [0xf3, 0xf7, 0xfb, 0xff], + ], + [ + [0xf0, 0xf4, 0xf8, 0xfc], + [0xf1, 0xf5, 0xf9, 0xfd], + [0xf2, 0xf6, 0xfa, 0xfe], + [0xf3, 0xf7, 0xfb, 0x00], + ], + [ + [0xf0, 0xf4, 0xf8, 0xfc], + [0xf1, 0xf5, 0xf9, 0xfd], + [0xf2, 0xf6, 0xfa, 0xfe], + [0xf3, 0xf7, 0xfb, 0x01], + ], + [ + [0xf0, 0xf4, 0xf8, 0xfc], + [0xf1, 0xf5, 0xf9, 0xfd], + [0xf2, 0xf6, 0xfa, 0xfe], + [0xf3, 0xf7, 0xfb, 0x02], + ], + ], + } + ); + }); +}); From 3bdc9cbe56c444278b8396115e483ed4469a97bd Mon Sep 17 00:00:00 2001 From: yash1io Date: Sat, 3 Aug 2024 14:01:40 +0530 Subject: [PATCH 6/8] fix GenerateCounterBlocks tessts --- tests/ctr.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ctr.test.ts b/tests/ctr.test.ts index af0c858..20a671a 100644 --- a/tests/ctr.test.ts +++ b/tests/ctr.test.ts @@ -284,19 +284,19 @@ describe("GenerateCounterBlocks", async () => { [ [0xf0, 0xf4, 0xf8, 0xfc], [0xf1, 0xf5, 0xf9, 0xfd], - [0xf2, 0xf6, 0xfa, 0xfe], + [0xf2, 0xf6, 0xfa, 0xff], [0xf3, 0xf7, 0xfb, 0x00], ], [ [0xf0, 0xf4, 0xf8, 0xfc], [0xf1, 0xf5, 0xf9, 0xfd], - [0xf2, 0xf6, 0xfa, 0xfe], + [0xf2, 0xf6, 0xfa, 0xff], [0xf3, 0xf7, 0xfb, 0x01], ], [ [0xf0, 0xf4, 0xf8, 0xfc], [0xf1, 0xf5, 0xf9, 0xfd], - [0xf2, 0xf6, 0xfa, 0xfe], + [0xf2, 0xf6, 0xfa, 0xff], [0xf3, 0xf7, 0xfb, 0x02], ], ], From 34da47f6c86f40d6aeda8a4595bab2fced372b0d Mon Sep 17 00:00:00 2001 From: yash1io Date: Sat, 3 Aug 2024 15:00:47 +0530 Subject: [PATCH 7/8] remove unrequired signal --- circuits/ctr.circom | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/circuits/ctr.circom b/circuits/ctr.circom index dd1ebc6..e2e1977 100644 --- a/circuits/ctr.circom +++ b/circuits/ctr.circom @@ -24,12 +24,11 @@ template EncryptCTR(l,nk){ component generateCtrBlocks = GenerateCounterBlocks(n); generateCtrBlocks.iv <== iv; - signal counterBlocks[n][4][4] <== generateCtrBlocks.counterBlocks; for(var i = 0 ; i < n; i++){ aes[i] = Cipher(nk); aes[i].key <== key; - aes[i].block <== counterBlocks[i]; + aes[i].block <== generateCtrBlocks.counterBlocks[i]; AddCipher[i] = AddCipher(); AddCipher[i].state <== toBlocks.blocks[i]; From 3de800cb717624b03ae4660904732708572e3686 Mon Sep 17 00:00:00 2001 From: yash1io Date: Sat, 3 Aug 2024 15:18:07 +0530 Subject: [PATCH 8/8] add ctr support for 2^32 blocks --- circuits/ctr.circom | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/circuits/ctr.circom b/circuits/ctr.circom index e2e1977..696d295 100644 --- a/circuits/ctr.circom +++ b/circuits/ctr.circom @@ -117,6 +117,7 @@ template AddCipher(){ // converts iv to counter blocks // iv is 16 bytes template GenerateCounterBlocks(n){ + assert(n < 0xffffffff); signal input iv[16]; signal output counterBlocks[n][4][4]; @@ -131,6 +132,13 @@ template GenerateCounterBlocks(n){ ivr[15] = (ivr[15] + 1)%256; if (ivr[15] == 0){ ivr[14] = (ivr[14] + 1)%256; + if (ivr[14] == 0){ + ivr[13] = (ivr[13] + 1)%256; + if (ivr[13] == 0){ + ivr[12] = (ivr[12] + 1)%256; + } + } } + } } \ No newline at end of file