密码学笔记3——AES实现

AES实现

实验内容

实现128位高级加密标准AES对信息的加密与解密。

具体算法

分组长度128bit,密钥长度128bit
圈数round=10
域GF(2^8)的不可约多项式为x^8+x^4+x^3+x+1

字节替代

对每一个字节本身进行替代
首先是在有限域GF(2^8)上求乘法逆,00映射到自身。求有限域乘法逆调用的是上次实验中的求逆的子程序。使用的是扩展欧几里得算法。
接下来进行如下的仿射变换:乘以矩阵

计算出这个表,迭代的时候直接在表中找映射值。

将字节代换的表使用一个长度为256的数组存储,索引对应的是二进制串的数值。每一个位置存储一个8位的二进制串。对于每一个8位的二进制串,通过上述方法计算出它的字节替换结果之后填入表对应位置中。同时,也可以将逆字节代换表的对应位置也填上,只要将索引同值换一下位置即可。

在程序中,使用全局变量Sbox和Inv_Sbox来分别表示字节代换和逆字节代换。在CreateSbox函数中,计算S盒以及逆S盒,更新这两个全局变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*创建S盒以及逆S盒*/
bitset<8> Sbox[256] ={0};
bitset<8> Inv_Sbox[256] = {0};
for(int i = 0; i < 256; i++){
bitset<8> temp(i);
bitset<8> inv_t = inv(temp);
bitset<8> c_x("01100011");
bitset<8> b;
for(int j = 0; j < 8; j++){
b[j] = inv_t[j]^inv_t[(j+4)%8]^inv_t[(j+5)%8]^inv_t[(j+6)%8]^inv_t[(j+7)%8]^c_x[j];
}
Sbox[i] = b;
Inv_Sbox[b.to_ulong()] = temp;
}

字节移位

分组长度为4的情况下,后三行循环移位字节量如下,循环左移
C1:1,C2:2,C3:3

ByteRotation函数中,接收一个二进制串的vector,以及循环左移移位量,这个vector代表的是一个word,即四个字节。这里进行的是对这四个字节进行循环左移指定位数的操作。

全局变量定义了SHIFT和INV_SHIFT,分别代表加密时每一行循环左移的移位量以及解密时每一行循环左移的移位量。在对应的加解密程序中确定每一行的移位量。

1
2
3
4
5
6
7
8
#define SHIFT {0,1,2,3}
#define INV_SHIFT {0,3,2,1}
void ByteRotation(vector<byte_def> &input,int shift_byte){
for(int i = 0; i < shift_byte; i++){
input.push_back(input[0]);
input.erase(input.begin());
}
}

列混合

加密的时候,相当于乘一个矩阵,矩阵如下

在MixColumn函数中,接收一个使用vector表示的矩阵,对此矩阵进行列混合操作。这里调用的mul函数是进行域乘法的子程序

解密的时候,相当于乘以上面矩阵在有限域下的逆矩阵,即

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
/*列混合加密*/
void MixColumn(vector<vector<byte_def>> &input){
byte_def result[4][4] = {0};
byte_def x("00000010");
byte_def x1("00000011");
for(int col = 0; col < 4; col++){
result[0][col] = mul(x,input[0][col])^mul(x1,input[1][col])^input[2][col]^input[3][col];
result[1][col] = mul(x,input[1][col])^mul(x1,input[2][col])^input[3][col]^input[0][col];
result[2][col] = mul(x,input[2][col])^mul(x1,input[3][col])^input[0][col]^input[1][col];
result[3][col] = mul(x,input[3][col])^mul(x1,input[0][col])^input[1][col]^input[2][col];
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
input[i][j] = result[i][j];
}
}
}
/*列混合解密*/
void Inv_MixColumn(vector<vector<byte_def>> &input){
byte_def result[4][4] = {0};
byte_def x_0e(0x0e);
byte_def x_0b(0x0b);
byte_def x_0d(0x0d);
byte_def x_09(0x09);
for(int col = 0; col < 4; col++){
result[0][col] = mul(x_0e,input[0][col])^mul(x_0b,input[1][col])^mul(x_0d,input[2][col])^mul(x_09,input[3][col]);
result[1][col] = mul(x_0e,input[1][col])^mul(x_0b,input[2][col])^mul(x_0d,input[3][col])^mul(x_09,input[0][col]);
result[2][col] = mul(x_0e,input[2][col])^mul(x_0b,input[3][col])^mul(x_0d,input[0][col])^mul(x_09,input[1][col]);
result[3][col] = mul(x_0e,input[3][col])^mul(x_0b,input[0][col])^mul(x_0d,input[1][col])^mul(x_09,input[2][col]);
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
input[i][j] = result[i][j];
}
}
}

圈密相加

将圈密钥与状态按比特异或,圈密钥长度为分组长度128bit。AddRoundKey函数接收一个矩阵以及轮数作为输入,取相对应轮数的圈密钥,加到矩阵上

1
2
3
4
5
6
7
8
void AddRoundKey(vector<vector<byte_def>> &input, int round){
vector<vector<byte_def>> this_round_key = expand_key[round];
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
input[i][j] ^= this_round_key[i][j];
}
}
}

密钥扩展

密钥总长度=分组长度*(圈数+1)
最开始明文需要异或密钥,以及每一轮最后需要异或密钥
初始密钥K0,K1,K2,K3
SubWord子程序对输入的word的每一个字节进行S盒操作,RotWord子程序对输入的word进行一个字节的移位。

在密钥扩展的子程序KeyExpansion中,接收一个初始的矩阵,即圈密钥0。依据这个初始密钥生成剩下的10个圈密钥。使用一个全局变量expand_key来存储每一轮使用的圈密钥。密钥扩展中需要用到的Rcon使用全局变量来定义。由于这里的一个word使用了四个byte来表示,而Rcon的后面三个byte全为0,因此其实只需要对word的第一个byte进行异或Rcon的第一个byte即可。Rcon的定义只取了它每一个的第一个byte

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
vector<vector<vector<byte_def>>> expand_key;
byte_def Rcon[10] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
void KeyExpansion(vector<vector<byte_def>> initialKey){
vector<vector<byte_def>> w_key;
//处理一下初始的密钥,将它拆分为四个word,并按照密钥扩展的指定顺序存放到w_key里
for(int i = 0; i < ROW_SIZE; i++){
vector<byte_def> helper;
helper.push_back(initialKey[0][i]);
helper.push_back(initialKey[1][i]);
helper.push_back(initialKey[2][i]);
helper.push_back(initialKey[3][i]);
w_key.push_back(helper);
}
//进行密钥扩展,操作单位为word
vector<byte_def> temp;
for(int i = 4; i <44; i++){
temp = w_key[i-1];
if(i % 4 == 0){
RotWord(temp);
SubWord(temp);
temp[0] ^= Rcon[i/4-1];
}
for(int k = 0; k < ROW_SIZE; k++){
temp[k] ^= w_key[i-4][k];
}
w_key.push_back(temp);

}
//取w_key中的word四个一组,存放到全局变量expand_key中
for(int i = 0; i <= ROUND; i++){
vector<vector<byte_def>> round_temp;
vector<byte_def> key_temp;
for(int j = 0; j < 4; j++){
key_temp.clear();
key_temp.push_back(w_key[i*4][j]);
key_temp.push_back(w_key[i*4+1][j]);
key_temp.push_back(w_key[i*4+2][j]);
key_temp.push_back(w_key[i*4+3][j]);
round_temp.push_back(key_temp);
}
expand_key.push_back(round_temp);
}
}

AES加密

函数void AES(vector> &current_group)接收一个矩阵作为输入,对此矩阵进行AES的加密操作:异或圈密钥0,然后进行9轮的字节替换,字节移位,列混合以及密钥加的操作,最后再进行一轮字节替换,字节移位,异或圈密钥10。

encode函数接收字符串明文作为输入,循环读入长度为16的字符串,将这16个字符串转化成AES输入的矩阵,先异或一下IV之后放进AES子程序中进行加密,加密完之后,密文作为下一组的IV,更新IV的值,并将密文存入ciphertext变量中。其中,将明文转换为矩阵通过一个名为Padding的函数进行,在此函数中,读入一定长度的字符串,先判断长度是否小于等于16,再计算此字符串的长度比16少多少,将少的长度记为n,将字符串填充为16长度的时候补充0x0n。

AES解密

函数void Inv_AES(vector> & current_group)接收一个矩阵作为输入,对此矩阵进行AES解密的操作:异或圈密钥10,逆行变换,逆字节替代,异或K9,然后进行剩下9轮的逆列变换,逆行变换,逆字节替代,密钥加的操作,其中这里使用的圈密钥是逆序使用的,即先使用圈密钥8,再使用圈密钥7以此类推。

decode函数接收密文,ciphertext。循环读入16个字节,将这16个字节依序放入矩阵中,将此矩阵放到AES解密的子程序里面进行解密,最后再异或一下IV,并更新IV为这一组原来的密文,供下一组解密使用。

运行截图

计算出来的S盒以及逆S盒

w_key计算

圈密钥

加密解密结果

结果分析

S盒的计算以及逆S盒,对比书上给出的S盒以及这里计算出的S盒,结果相同说明S盒计算无误。另外,S盒的索引值以及其对应的值,刚好与逆S盒的值和索引一一相互对应回去。说明逆S盒计算也无误。(比如S盒中索引为00的地方值是63,逆S盒中索引为63的地方值为00)

w_key的计算,根据书上给出的算法实现。手动计算了一下粗略验证了w5和w6,发现计算的结果无误,可以推定w_key的算法实现无误

圈密钥的生成。一个圈密钥是由四个wkey生成的,其中要注意的是从wkey到圈密钥的排放顺序,wkey0对应的是圈密钥的第一列,wkey1是第二列,以此类推。可以看到圈密钥输出的结果正是4个wkey按照给定规则排列成的。

程序加密的结果和网站加密的结果相同,且能够正确解密出密文,说明加密和解密的结果无误。

网站加密结果

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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
//cipher key "yaojieqian"
//work mode: CBC
//IV: "123"
//PKCS5Padding
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<bitset>
#include<cmath>
#include<vector>
#include<iomanip>
#define GROUP_LEN 128 //分组长度128
#define ROW_LEN 32 //单行长度
#define ROW_SIZE 4 //单行字节数
#define SHIFT {0,1,2,3}
#define INV_SHIFT {0,3,2,1} //仅用在解密处,循环左移的位数
#define ROUND 10
#define SIZE_N 8
#define r_str "11011"//x^4+x^3+x+1
#define poly_str "100011011"
#define debug 1
using namespace std;
typedef bitset<8> byte_def;
typedef bitset<32> word_def;
bitset<8> Sbox[256] ={0};
bitset<8> Inv_Sbox[256] = {0};
vector<vector<vector<byte_def>>> expand_key;
byte_def Rcon[10] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
bitset<SIZE_N> mod(bitset<SIZE_N*2> op1, bitset<SIZE_N> r){
bitset<SIZE_N> res(0);
bitset<SIZE_N*2> helper;
bitset<SIZE_N*2> extend_r(r.to_ulong());
for(int i = SIZE_N*2-1; i >= SIZE_N; i--){
if(op1[i]){
helper = extend_r << (i-SIZE_N);
op1 ^= helper;
op1[i] = 0;
}
}
for(int i = 0; i < SIZE_N; i++)
res[i] = op1[i];
return res;
}
bitset<SIZE_N> mul(bitset<SIZE_N> op1, bitset<SIZE_N> op2){
bitset<SIZE_N*2> raw_res(0);//存储两数相乘的直接结果
bitset<SIZE_N> res(0);//经过模运算之后的结果
bitset<SIZE_N> r(r_str);
bitset<SIZE_N*2> extend_op1(op1.to_string());//需要对其进行左移,故扩展成原长度的两倍
for(int i = 0; i < SIZE_N; i++){
if(op2[i]){
raw_res ^= (extend_op1<<i);
}
}
res = mod(raw_res,r);
return res;
}
int max_exp(bitset<SIZE_N+1> op){
for(int i = SIZE_N; i > -1; i--){
if(op[i])
return i;
}
return 0;
}
bitset<SIZE_N> inv(bitset<SIZE_N> op){
if(!op.any()){
bitset<SIZE_N> res(0);
return res;
}
bitset<SIZE_N+1> poly(poly_str);
bitset<SIZE_N+1> k1(op.to_string());
bitset<SIZE_N+1> k2(poly.to_string());
bitset<SIZE_N+1> ktemp;
bitset<SIZE_N> x1(0);
bitset<SIZE_N> x2(0);
bitset<SIZE_N> temp;
x1[0] = 1;
int diff_exp;
while(max_exp(k1)){
diff_exp = max_exp(k1)-max_exp(k2);
if(diff_exp < 0){
diff_exp = -diff_exp;
ktemp = k1;
k1 = k2;
k2 = ktemp;
temp = x1;
x1 = x2;
x2 = temp;
}
k1 ^= (k2<<diff_exp);
x1 ^= (x2<<diff_exp);
}
return x1;
}
//创建S盒以及逆S盒
void CreateSbox(){
for(int i = 0; i < 256; i++){
bitset<8> temp(i);
bitset<8> inv_t = inv(temp);
bitset<8> c_x("01100011");
bitset<8> b;
for(int j = 0; j < 8; j++){
b[j] = inv_t[j]^inv_t[(j+4)%8]^inv_t[(j+5)%8]^inv_t[(j+6)%8]^inv_t[(j+7)%8]^c_x[j];
}
Sbox[i] = b;
Inv_Sbox[b.to_ulong()] = temp;
}
cout<<"S box calculated:"<<endl;
for(int i = 0; i < 16; i++){
for(int j = 0; j < 16; j++){
cout<<setw(2)<<setfill('0')<<hex<<Sbox[i*16+j].to_ulong()<<" ";
}
cout<<endl;
}
cout<<"Inv S box calculated:"<<endl;
for(int i = 0; i < 16; i++){
for(int j = 0; j < 16; j++){
cout<<setw(2)<<setfill('0')<<hex<<Inv_Sbox[i*16+j].to_ulong()<<" ";
}
cout<<endl;
}
}
byte_def ByteSubsitution(byte_def input){
return Sbox[input.to_ulong()];
}
byte_def Inv_ByteSusitution(byte_def input){
return Inv_Sbox[input.to_ulong()];
}
//对分组进行行移位
//input输入是128bit的
void ByteRotation(vector<byte_def> &input,int shift_byte){
for(int i = 0; i < shift_byte; i++){
input.push_back(input[0]);
input.erase(input.begin());
}
return;
}
void MixColumn(vector<vector<byte_def>> &input){
byte_def result[4][4] = {0};
byte_def x("00000010");
byte_def x1("00000011");
for(int col = 0; col < 4; col++){
result[0][col] = mul(x,input[0][col])^mul(x1,input[1][col])^input[2][col]^input[3][col];
result[1][col] = mul(x,input[1][col])^mul(x1,input[2][col])^input[3][col]^input[0][col];
result[2][col] = mul(x,input[2][col])^mul(x1,input[3][col])^input[0][col]^input[1][col];
result[3][col] = mul(x,input[3][col])^mul(x1,input[0][col])^input[1][col]^input[2][col];
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
input[i][j] = result[i][j];
}
}
return;
}
void Inv_MixColumn(vector<vector<byte_def>> &input){
byte_def result[4][4] = {0};
byte_def x_0e(0x0e);
byte_def x_0b(0x0b);
byte_def x_0d(0x0d);
byte_def x_09(0x09);
for(int col = 0; col < 4; col++){
result[0][col] = mul(x_0e,input[0][col])^mul(x_0b,input[1][col])^mul(x_0d,input[2][col])^mul(x_09,input[3][col]);
result[1][col] = mul(x_0e,input[1][col])^mul(x_0b,input[2][col])^mul(x_0d,input[3][col])^mul(x_09,input[0][col]);
result[2][col] = mul(x_0e,input[2][col])^mul(x_0b,input[3][col])^mul(x_0d,input[0][col])^mul(x_09,input[1][col]);
result[3][col] = mul(x_0e,input[3][col])^mul(x_0b,input[0][col])^mul(x_0d,input[1][col])^mul(x_09,input[2][col]);
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
input[i][j] = result[i][j];
}
}
}
void AddRoundKey(vector<vector<byte_def>> &input, int round){
vector<vector<byte_def>> this_round_key = expand_key[round];
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
input[i][j] ^= this_round_key[i][j];
}
}
}

void SubWord(vector<byte_def> &input){
for(int i = 0; i < 4; i++){
input[i] = Sbox[input[i].to_ulong()];
}
}
void RotWord(vector<byte_def> &input){
input.push_back(input[0]);
input.erase(input.begin());
}
//128 bit AES round = 10, so we should create 10 round key
void KeyExpansion(vector<vector<byte_def>> initialKey){
vector<vector<byte_def>> w_key;
for(int i = 0; i < ROW_SIZE; i++){
vector<byte_def> helper;
helper.push_back(initialKey[0][i]);
helper.push_back(initialKey[1][i]);
helper.push_back(initialKey[2][i]);
helper.push_back(initialKey[3][i]);
w_key.push_back(helper);
}
vector<byte_def> temp;
for(int i = 4; i <44; i++){
temp = w_key[i-1];
if(i % 4 == 0){
RotWord(temp);
SubWord(temp);
temp[0] ^= Rcon[i/4-1];
}
for(int k = 0; k < ROW_SIZE; k++){
temp[k] ^= w_key[i-4][k];
}
w_key.push_back(temp);

}
int count_key = 0;
for(auto it = w_key.begin(); it != w_key.end(); it++){
cout<<"w_key"<<setw(2)<<count_key++<<" = ";
for(auto iter = (*it).begin(); iter != (*it).end(); iter++)
cout<<setw(2)<<setfill('0')<<(*iter).to_ulong()<<" ";
cout<<endl;
}
for(int i = 0; i <= ROUND; i++){
vector<vector<byte_def>> round_temp;
vector<byte_def> key_temp;
for(int j = 0; j < 4; j++){
key_temp.clear();
key_temp.push_back(w_key[i*4][j]);
key_temp.push_back(w_key[i*4+1][j]);
key_temp.push_back(w_key[i*4+2][j]);
key_temp.push_back(w_key[i*4+3][j]);
round_temp.push_back(key_temp);
}
expand_key.push_back(round_temp);
}
cout<<"key after expansion"<<endl;
int count = 0;
for(auto it = expand_key.begin(); it != expand_key.end(); it++){
cout<<"Round key:"<<count++<<endl;
for(auto it1 = (*it).begin(); it1 != (*it).end(); it1++){
for(auto it2 = (*it1).begin(); it2 != (*it1).end(); it2++){
cout<<setw(2)<<setfill('0')<<hex<<(*it2).to_ulong()<<" ";
}
cout<<endl;
}
}

}
void AES(vector<vector<byte_def>> &current_group, ofstream &encode_log){
if(debug){
encode_log<<"AES initial input:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
//和圈密钥0异或一下
AddRoundKey(current_group,0);
if(debug){
encode_log<<"After xor round Key0:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
int shift[4] = SHIFT;
//前面的ROUND-1轮,对于128bit的来说是9轮
for(int round = 1; round < ROUND; round++){
if(debug){
encode_log<<"This is round"<<round<<endl;
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
current_group[i][j] = ByteSubsitution(current_group[i][j]);
}
}
if(debug){
encode_log<<"After Byte subsitution:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
for(int i = 0; i < 4; i++){
ByteRotation(current_group[i],shift[i]);
}
if(debug){
encode_log<<"After ByteRotation:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
MixColumn(current_group);
if(debug){
encode_log<<"After Mixcolumn:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
AddRoundKey(current_group,round);
if(debug){
encode_log<<"After add round key "<<round<<":"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
}
//最后一轮
if(debug){
encode_log<<"This is Round 10"<<endl;
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
current_group[i][j] = ByteSubsitution(current_group[i][j]);
}
}
if(debug){
encode_log<<"After ByteSubsitution:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
for(int i = 0; i < 4; i++){
ByteRotation(current_group[i],shift[i]);
}
if(debug){
encode_log<<"After ByteRotaion:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
AddRoundKey(current_group,ROUND);
if(debug){
encode_log<<"After add round key 10:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
encode_log<<hex<<(*iter).to_ulong()<<" ";
}
encode_log<<endl;
}
}
}
void Inv_AES(vector<vector<byte_def>> &current_group, ofstream &decode_log){
if(debug){
decode_log<<"Inv_AES initial input:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
//和圈密钥10异或一下,最开始的一轮不用列变换
AddRoundKey(current_group,10);
if(debug){
decode_log<<"After add Round key 10:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
int inv_shift[4] = INV_SHIFT;
//逆行变换
for(int i = 0; i < 4; i++){
ByteRotation(current_group[i],inv_shift[i]);
}
if(debug){
decode_log<<"After Inv ByteRotation:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
//逆字节替代
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
current_group[i][j] = Inv_ByteSusitution(current_group[i][j]);
}
}
if(debug){
decode_log<<"After Inv ByteSubsitution:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
//异或一下K9
AddRoundKey(current_group,9);
if(debug){
decode_log<<"After add Round key 9:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
//进行剩下的9轮
for(int round = 8; round >= 0; round--){
Inv_MixColumn(current_group);
if(debug){
decode_log<<"After Inv Mixcolumn:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
for(int i = 0; i < 4; i++){
ByteRotation(current_group[i],inv_shift[i]);
}
if(debug){
decode_log<<"After Inv ByteRotation:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
for(int i = 0; i < 4; i++){
for(int j = 0; j< ROW_SIZE; j++){
current_group[i][j] = Inv_ByteSusitution(current_group[i][j]);
}
}
if(debug){
decode_log<<"After Inv Subsitution:"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
AddRoundKey(current_group,round);
if(debug){
decode_log<<"After add Round key "<<round<<":"<<endl;
for(auto it = current_group.begin(); it != current_group.end(); it++){
for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
}
decode_log<<endl;
}
}
}

}
//将字符串转化为128bit,如长度不够,使用padding补0x0N
vector<vector<byte_def>> Padding(string input){
vector<vector<byte_def>> result(4);
if(input.size() > 16){
cout<<"String exceed size"<<endl;
return result;
}
//calculate n
int n = 16-input.size();
for(int i = 0; i < 16; i++){
if(i < input.size()){
byte_def temp(int(input[i]+0));
result[i%4].push_back(temp);
}
else{
byte_def temp(n);
result[i%4].push_back(temp);
}
}
return result;
}
vector<vector<byte_def>> turnStringIntoBits(string input){
vector<vector<byte_def>> result(4);
if(input.size() > 16){
cout<<"String exceed size"<<endl;
return result;
}
for(int i = 0; i < 16; i++){
if(i < input.size()){
byte_def temp(int(input[i]+0));
result[i%4].push_back(temp);
}
else{
byte_def temp(0);
result[i%4].push_back(temp);
}
}
return result;
}
void encode(string plaintext,vector<byte_def> &ciphertext){
int group_num = ceil((double)plaintext.size()/16);
//IV开始的时候是字符串123
vector<vector<byte_def>> IV = turnStringIntoBits("123");
ofstream encode_log("encode_log.txt");
for(int i = 0; i < group_num; i++){
//每次取16个字符,最后不足十六个字符substr函数读到字符串末尾自己会终止
vector<vector<byte_def>> plain_group = Padding(plaintext.substr(i*16,16));
//明文异或一下IV
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
plain_group[i][j] ^= IV[i][j];
}
}
encode_log<<endl<<"Encoding group "<<i<<": "<<plaintext.substr(i*16,16)<<endl;
//放进AES里面进行运算
AES(plain_group,encode_log);
//将这组的输出存进总输出里面,并且更新IV的值
encode_log<<"group "<<i<<" ciphertext:";
for(int i = 0; i < 4; i++){
for(int j = 0; j < ROW_SIZE; j++){
IV[i][j] = plain_group[i][j];
ciphertext.push_back(plain_group[j][i]);
encode_log<<hex<<plain_group[j][i].to_ulong();
}
}
encode_log<<endl<<endl;
}
encode_log.close();
cout<<"encode result:"<<endl;
for(auto it = ciphertext.begin(); it != ciphertext.end(); it++){
cout<<setw(2)<<setfill('0')<<hex<<(*it).to_ulong();
}
cout<<endl;
}
void decode(vector<byte_def> ciphertext){
//128bits一组,16个字节一组
int group_num = ceil(ciphertext.size()/16);
vector<vector<byte_def>> IV = turnStringIntoBits("123");
vector<byte_def> plaintext;
ofstream decode_log("decode.log.txt");
int index = 0;
for(int i = 0; i < group_num; i++){
vector<vector<byte_def>> cipher_group(4);
//密文丢进去
for(int j = 0; j < 4; j++){
cipher_group[0].push_back(ciphertext[index++]);
cipher_group[1].push_back(ciphertext[index++]);
cipher_group[2].push_back(ciphertext[index++]);
cipher_group[3].push_back(ciphertext[index++]);
}
decode_log<<endl<<"decoding group "<<i<<endl;
Inv_AES(cipher_group,decode_log);
decode_log<<endl;
//异或IV,得到明文,并更新IV的值
for(int j = 0; j < 4; j++){
for(int k = 0; k < 4; k++){
cipher_group[j][k] ^= IV[j][k];
IV[j][k] = ciphertext[i*16+k*4+j];
}
}
for(int j = 0; j < 4; j++){
for(int k = 0; k < 4; k++){
plaintext.push_back(cipher_group[k][j]);
}
}
}
decode_log.close();
cout<<"decode result:"<<endl;
for(auto it = plaintext.begin(); it != plaintext.end(); it++){
cout<<(char)(*it).to_ulong();
}
cout<<endl;
}
int main(){
CreateSbox();
string key = "yaojieqian";//名字作为key
vector<vector<byte_def>> initialKey = turnStringIntoBits(key);
KeyExpansion(initialKey);
string plaintext = "ilearnedhowtocalculatetheamountofpaperneededforaroomwheniwasatschoolyoumultiplythesquarefootageofthewallsbythecubiccontentsofthefloorandceilingcombinedanddoubleityouthenallowhalfthetotalforopeningssuchaswindowsanddoorsthenyouallowtheotherhalfformatchingthepatternthenyoudoublethewholethingagaintogiveamarginoferrorandthenyouorderthepaper";
vector<byte_def> ciphertext;
encode(plaintext,ciphertext);
decode(ciphertext);

}