-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathctr.circom
144 lines (114 loc) · 3.66 KB
/
ctr.circom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
pragma circom 2.1.9;
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 = ToBlocks(l);
toBlocks.stream <== plainText;
component aes[n];
signal cipherBlocks[n][4][4];
component AddCipher[n];
component generateCtrBlocks = GenerateCounterBlocks(n);
generateCtrBlocks.iv <== iv;
for(var i = 0 ; i < n; i++){
aes[i] = Cipher(nk);
aes[i].key <== key;
aes[i].block <== generateCtrBlocks.counterBlocks[i];
AddCipher[i] = AddCipher();
AddCipher[i].state <== toBlocks.blocks[i];
AddCipher[i].cipher <== aes[i].cipher;
cipherBlocks[i] <== AddCipher[i].newState;
}
component toStream = ToStream(n,l);
toStream.blocks <== cipherBlocks;
cipher <== toStream.stream;
}
//convert stream of plain text to blocks of 16 bytes
template ToBlocks(l){
signal input stream[l];
var n = l\16;
if(l%16 > 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;
}
}
// convert blocks of 16 bytes to stream of bytes
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;
}
}
}
// 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];
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;
if (ivr[14] == 0){
ivr[13] = (ivr[13] + 1)%256;
if (ivr[13] == 0){
ivr[12] = (ivr[12] + 1)%256;
}
}
}
}
}