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], + ], + ], + } + ); + }); +});