算法简介

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。(摘自百度百科)

AES属于对称加密算法,加密解密使用的密钥相同,同时也是分组加密算法,明文长度固定为128位,密钥长度分为128位,192位,256位,(也就是常说的AES128,AES192,AES256),密钥每增加64位加密函数增加两轮。

萌新是跟着这位爷这个视频学的。

前置芝士

伽罗华域(Galois Field)上的四则运算

GF(2^8)有限域上的运算问题

看了一天AES数学基础,果然最痛的还是数学😭

个人理解:有限域上的多项式运算主要是把握住加减法运算和异或运算的等效性,理解了这一层,对于有限域GF(2^n)中大于等于n次的多项式,我们对其进行取模运算,即本原多项式 ,就很好理解了。

比如我们要用模乘来计算

左边的结果为

我们先计算,与上式异或以后的结果为,我们再计算,和上面的结果再异或,得到一个低于8次幂的多项式,也就是最后的结果为00110010。

明文填充

假如一段明文长度是192bit,如果按每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit。这时候怎么办呢?就需要对明文块进行填充(Padding)。

填充有六种:NoPadding, PKCS#5, PKCS#7, ISO 10126, ANSI X9.23和ZerosPadding

TIPS:如果加密使用了某种填充方式,解密也需要使用相同的填充方式

NoPadding

顾名思义,就是不填充。缺点就是只能加密长为128bits倍数的信息,一般不会使用。

PKCS#7 & PKCS#5

缺几个字节就填几个缺的字节数。

如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。
比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6}

ZerosPadding

全部填充0x00,无论缺多少全部填充0x00

ISO 10126

最后一个字节是填充的字节数(包括最后一字节),其他全部填随机数。

ANSI X9.23

跟ISO 10126很像,只不过ANSI X9.23其他字节填的都是0而不是随机数。

加密算法大致流程(AES128)

如图:

1658478398330

这里需要注意,10轮循环运算中,前面9轮是有列混合操作的,但是最后一轮是没有的,剩下的操作都是一样的。

输入的明文分组为128位,也就是16字节,我们把它们填入一个4 * 4矩阵,具体方法如下

1658479829666

加密原理和实现

初始变换

1658480044430

初始变换非常简单,就是把4 * 4的明文矩阵和第 0 的子密钥矩阵进行异或即可。

1658480207355

加密函数

由之前的大致流程图可知,AES加密函数分为4步,字节代换、行移位、列混合、轮密钥加,我们分开介绍。

字节代换

这一步就是一个简单的查表操作,和DES加密算法一样,我们把每个2位16进制的高低位分开作为行号和列号,在一个S盒中进行查询,AES定义了一个S盒和一个逆S盒,分别是:

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
const byte AES::SBox[16][16] = 
{
{0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76},
{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0},
{0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15},
{0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75},
{0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84},
{0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf},
{0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8},
{0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2},
{0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73},
{0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb},
{0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79},
{0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08},
{0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a},
{0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e},
{0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf},
{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}
};
const byte AES::invSBox[16][16] =
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};

比如下面这个明文矩阵,我们用第一个数来示范:

1658481003882

第一个数是0x19我们只要找S盒中第1行第9列的数然后进行替换就可以了

1658480964697

这个数是0xd4,对每个数都这样操作,那么在经过一轮字节代换后,原来的矩阵变成了

1658481103159

行移位

1658481143778

这个操作也很简单,当密钥长度为128位的时候,我们把密钥也变成一个4 * 4的矩阵,然后对第2、3、4行分别进行左移1、2、3个字节即可。

列混合

的明文矩阵左乘一个给定的正矩阵

1658482056069

这里需要注意,此处的矩阵乘法并不是我们之前学的 ,具体算法为

这里需要注意,乘法运算使用的是有限域上的乘法运算,这里我们先不深究其原理,只介绍乘法运算的方式。由于只有这两种运算,所以我们也只需要了解这两种运算的方法即可。

变换后得到

1658651301785

轮密钥加

最后是轮密钥加,每一轮都会生成一个对应的密钥矩阵(怎么来的后面会说),把这个矩阵和上一步得到的结果按位异或,完成一轮加密。

假设该轮生成的密钥为

1658651790935

那么最终结果为

1658651808604

密钥扩展

假设初始密钥如下

1658652211918

也就是说每一轮密钥扩展都会在右边扩展出一个新的4 * 4矩阵,具体规则如下:

对于第i列来说,

  • 如果i不是4的倍数,那么

  • 如果i是4的倍数,那么

不是是4的倍数

这种情况很好办,直接把对应的列向量拿出来按位异或填入第i列即可。

1658652540007

比如当前需要填充白色方框所在的列,那么找到异或后填入得到。

是4的倍数

我们发现多了一个T函数,这个函数由3部分组成:字循环,字节代换和轮常量异或。

字循环

将1个字中的4个字节循环左移1个字节(按照填充规则在矩阵中其实是上移)。

比如变换成,具体的有变为

字节代换

对字循环的结果使⽤S盒进⾏字节代换。

就拿字循环中的结果来说,第一个字节为0xcf,我们查S表的第c行第f列找到对应的值进行代换即可,得到结果

轮常量异或

将前两步的结果同轮常量Rcon[j]进⾏异或,其中j表示轮数 ,轮常量矩阵如下:

1658653471356

比如我们下面要填充这个白色方框中的内容,此时的i是4的倍数,我们已经由前两步(字循环,字节代换)得到了,那么我们计算

1658653551915

密钥扩展最终结果

1658653998859

白嫖的同学的AES代码

声明变量与函数

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
#pragma once

typedef unsigned char byte;
struct word
{
byte wordKey[4];
};

class AES
{
public:
AES() {
initRcon();
};
// ~AES();
void setCipherKey(byte key[]);
void setPlainText(byte plain[]);

//
void keyExpansion(byte key[], word w[]);
word rotWord(word w);
word subWord(word w);
word wordXOR(word w1, word w2);
//functions in encryption and decryption
void encryption();
void addRoundKey(word in[], int round);
void subByte(word in[]);
void shiftRows(word in[]);
void mixColumn(word in[]);
byte GFMultiplyByte(byte L, byte R);
void decryption();
void invShiftRows(word in[]);
void invSubByte(word in[]);
void invMixColumn(word in[]);
void initRcon();
void showWord(word w[], int len);
void showMesage();

//为了实现用指针访问S盒,提供的方法,打印出该S盒
static void print_SBox();
private:
byte cipherKey[16];
word plainText[4];
word cipherText[4];
word deCipherText[4];
static const int Nb = 4, Nk = 4, Nr = 10;
word Rcon[11];
word wordKey[44];
static const byte SBox[16][16];
static const byte invSBox[16][16];
static const byte mixColumnMatrix[4][4];
static const byte invmixColumnMatrix[4][4];
};

加密函数主体

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
#include "aes.h"
#include <iostream>

//使用指针访问S盒
void AES::print_SBox(){
const byte (*sbox_tmp)[16] = SBox;
printf("S盒:\n");
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
printf("0x%02x ", *((*(sbox_tmp+i))+j));
}
printf("\n");
}
}

void AES::showWord(word w[], int len) {
int i, j;
for (i = 0; i < len; i++) {
for (j = 0; j < 4; j++) {
printf("0x%02x ", w[i].wordKey[j]);
}
}
std::cout << std::endl;
}

void AES::showMesage() {
std::cout << "plainText:" << std::endl;
showWord(plainText, 4);
std::cout << "wordKey:" << std::endl;
showWord(wordKey, Nb * (Nr + 1));
std::cout << "cipherText:" << std::endl;
showWord(cipherText, 4);
std::cout << "deCipherText:" << std::endl;
showWord(deCipherText, 4);
}
// initialize the plainText--trans plaintext from vector to state_matrix
void AES::setPlainText(byte plain[]) {
int i;
for (i = 0; i < 16; i++) {
plainText[i / 4].wordKey[i % 4] = plain[i];
}
}

//initialize the key--from vector to state_matrix
void AES::setCipherKey(byte key[]) {
int i;
for (i = 0; i < 16; i++) {
cipherKey[i] = key[i];
}
keyExpansion(cipherKey, wordKey);
}

//initialize the Rcon
void AES::initRcon() {
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++) {
Rcon[i].wordKey[j] = 0x0;
}
Rcon[1].wordKey[0] = 0x01;
Rcon[2].wordKey[0] = 0x02;
Rcon[3].wordKey[0] = 0x04;
Rcon[4].wordKey[0] = 0x08;
Rcon[5].wordKey[0] = 0x10;
Rcon[6].wordKey[0] = 0x20;
Rcon[7].wordKey[0] = 0x40;
Rcon[8].wordKey[0] = 0x80;
Rcon[9].wordKey[0] = 0x1b;
Rcon[10].wordKey[0] = 0x36;
}

//static成员的初始化要在实现中完成,或者直接类内初始化
//initialize the const of mixColumn and invMixColumn
const byte AES::mixColumnMatrix[4][4] = {
{0x02, 0x03, 0x01, 0x01},
{0x01, 0x02, 0x03, 0x01},
{0x01, 0x01, 0x02, 0x03},
{0x03, 0x01, 0x01, 0x02}
};
const byte AES::invmixColumnMatrix[4][4] = {
{0x0e, 0x0b, 0x0d, 0x09},
{0x09, 0x0e, 0x0b, 0x0d},
{0x0d, 0x09, 0x0e, 0x0b},
{0x0b, 0x0d, 0x09, 0x0e}
};

//initialize SBox
const byte AES::SBox[16][16] = {
{0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76},
{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0},
{0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15},
{0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75},
{0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84},
{0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf},
{0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8},
{0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2},
{0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73},
{0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb},
{0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79},
{0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08},
{0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a},
{0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e},
{0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf},
{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}
};
const byte AES::invSBox[16][16] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};

//keyExpansion-get the round key
void AES::keyExpansion(byte key[], word w[]) {
int i = 0;
int j;
word temp;
while (i < Nk) {
for (j = 0; j < 4; j++) {
w[j].wordKey[i] = key[j + 4 * i];
}
i++;
}
i = Nk;
while (i < Nb * (Nr + 1)) {
temp = w[i - 1];
if ((i % Nk) == 0) {
temp = rotWord(temp);
temp = subWord(temp);
temp = wordXOR(temp, Rcon[i / Nk]);
}
else if (Nk > 6 && (i % Nk) == 4) {
temp = subWord(temp);
}
w[i] = wordXOR(w[i - Nk], temp);
i++;
}
}

// some sector in keyExpansion
word AES::rotWord(word w) {
int i;
word temp;
for (i = 0; i < 4; i++) {
temp.wordKey[(i + 3) % 4] = w.wordKey[i];
}
return temp;
}

word AES::subWord(word w) {
int i;
byte L, R;
for (i = 0; i < 4; i++) {
L = w.wordKey[i] >> 4;
R = w.wordKey[i] & 0x0f;
w.wordKey[i] = SBox[L][R];
}
return w;
}

word AES::wordXOR(word w1, word w2) {
int i;
word temp;
for (i = 0; i < 4; i++) {
temp.wordKey[i] = w1.wordKey[i] ^ w2.wordKey[i];
}
return temp;
}

//encryption
void AES::encryption() {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
cipherText[i].wordKey[j] = plainText[i].wordKey[j];
}
}
// round function
addRoundKey(cipherText, 0);
for (i = 1; i < 10; i++) {
subByte(cipherText);
shiftRows(cipherText);
mixColumn(cipherText);
addRoundKey(cipherText, i);
}
subByte(cipherText);
shiftRows(cipherText);
addRoundKey(cipherText, 10);
}

void AES::subByte(word in[]) {
int i, j;
byte L, R;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
L = in[i].wordKey[j] >> 4;
R = in[i].wordKey[j] & 0x0f;
in[i].wordKey[j] = SBox[L][R];
}
}
}

void AES::shiftRows(word in[]) {
int i, j;
word temp[4];
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
temp[i].wordKey[j] = in[(i + j) % 4].wordKey[j];
}
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
in[i].wordKey[j] = temp[i].wordKey[j];
}
}
}

void AES::mixColumn(word in[]) {
word result[4];
int i, j, k;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
result[i].wordKey[j] = GFMultiplyByte(mixColumnMatrix[j][0], in[i].wordKey[0]);
for (k = 1; k < 4; k++) {
result[i].wordKey[j] ^= GFMultiplyByte(mixColumnMatrix[j][k], in[i].wordKey[k]);
}
}
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
in[i].wordKey[j] = result[i].wordKey[j];
}
}
}

//forexample: 0xaf * 0x25
byte AES::GFMultiplyByte(byte L, byte R) {
byte temp[8];
byte result = 0x00;
temp[0] = L;
int i;
// temp[0] = L, temp[1] = L*x(modm(x)), temp[2] = L*x^2(mod(m(x))), temp[3] = L*x^3(mod(m(x)))...
//先计算,再存起来,后面根据R的实际情况选用需要的
for (i = 1; i < 8; i++) {
if (temp[i - 1] >= 0x80) {
temp[i] = (temp[i - 1] << 1) ^ 0x1b;
}
else {
temp[i] = temp[i - 1] << 1;
}
}
for (i = 0; i < 8; i++) {
if (int((R >> i) & 0x01) == 1) {
result ^= temp[i];
}
}
return result;
}

void AES::addRoundKey(word in[], int round) {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
in[i].wordKey[j] ^= wordKey[i + 4 * round].wordKey[j];
}
}
}

//decryption
void AES::decryption() {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
deCipherText[i].wordKey[j] = cipherText[i].wordKey[j];
}
}
addRoundKey(deCipherText, 10);
for (i = 9; i > 0; i--) {
invShiftRows(deCipherText);
invSubByte(deCipherText);
addRoundKey(deCipherText, i);
invMixColumn(deCipherText);
}
invShiftRows(deCipherText);
invSubByte(deCipherText);
addRoundKey(deCipherText, 0);
}

void AES::invShiftRows(word in[]) {
int i, j;
word temp[4];
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
temp[i].wordKey[j] = in[(i - j + 4) % 4].wordKey[j];
}
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
in[i].wordKey[j] = temp[i].wordKey[j];
}
}
}

void AES::invSubByte(word in[]) {
int i, j;
byte L, R;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
L = in[i].wordKey[j] >> 4;
R = in[i].wordKey[j] & 0x0f;
in[i].wordKey[j] = invSBox[L][R];
}
}
}

void AES::invMixColumn(word in[]) {
word result[4];
int i, j, k;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
result[i].wordKey[j] = GFMultiplyByte(invmixColumnMatrix[j][0], in[i].wordKey[0]);
for (k = 1; k < 4; k++) {
result[i].wordKey[j] ^= GFMultiplyByte(invmixColumnMatrix[j][k], in[i].wordKey[k]);
}
}
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
in[i].wordKey[j] = result[i].wordKey[j];
}
}
}

main调用函数

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
#include "aes.h"
#include <cstdlib>
#include <stdio.h>
#include <iostream>
using namespace std;

//得到不定长输入,传入为输入长度的引用,返回表示存储明文的指针
byte* get_plain(unsigned& sz) {
//plain为指向输入明文的指针,plain_t是重新new时使用的临时指针
byte *plain = NULL, *plain_t;
//i为索引,也是输入明文的长度,len是一共申请的堆的大小
unsigned i = 0, len = 2;
//while(plain == NULL) {
//plain = (byte*)malloc(sizeof(byte) * len);
plain = new byte[sizeof(byte) * len];
//}
while ('\n' != (plain[i] = byte(getchar()))) {
i++;
//假如此时堆已经不满足在接收输入,new重新申请,以2倍速度增长
if (i == len) {
//plain_t = NULL;
//while (NULL == plain_t) {
//plain_t = (byte*)realloc(plain, sizeof(byte) * len * 2);
//len = sizeof(byte) * len * 2;
//}
plain_t = new byte[sizeof(byte) * len * 2];
//将原来的内存拷贝到新new的堆
copy(plain, plain + len, plain_t);
//注意删除原来的堆内存
delete[] plain;
len = sizeof(byte) * len * 2;
plain = plain_t;
}
}
sz = i;
return plain;
}

int main(int argc, char const* argv[])
{
unsigned i;
//设置明文和密钥
byte plain[16], key[16];
for (i = 0; i < 16; i++) {
plain[i] = byte(i);
key[i] = 0x01;
}
AES aes;
aes.setPlainText(plain);
aes.setCipherKey(key);
aes.encryption();
aes.decryption();
aes.showMesage();

unsigned sz, times;
byte* plain2;
cout << "输入明文" << endl;
plain2 = get_plain(sz);

//判断能够正好16位进行加密的轮次
times = sz / 16;
for (i = 0; i < times; i++) {
aes.setPlainText(plain2 + 16 * i);
aes.setCipherKey(key);
aes.encryption();
aes.decryption();
aes.showMesage();
}

//最后不足16位的后面以0补足
for (i = 0; i < 16; i++) {
plain[i] = byte(0);
}
for (i = sz % 16; i > 0; i--) {
plain[i-1] = plain2[times * 16 + i - 1];
}
aes.setPlainText(plain);
aes.setCipherKey(key);
aes.encryption();
aes.decryption();
aes.showMeage();

//释放内存
delete[] plain2;

//使用指针打印S盒
AES::print_SBox();
return 0;
}

或者用这个轮子(emmm

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
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
typedef enum {
AES_CYPHER_128,
AES_CYPHER_192,
AES_CYPHER_256,
} AES_CYPHER_T;
/*
* Encryption Rounds
*/
int g_aes_key_bits[] = {
/* AES_CYPHER_128 */
128,
/* AES_CYPHER_192 */
192,
/* AES_CYPHER_256 */
256,
};
int g_aes_rounds[] = {
/* AES_CYPHER_128 */
10,
/* AES_CYPHER_192 */
12,
/* AES_CYPHER_256 */
14,
};
int g_aes_nk[] = {
/* AES_CYPHER_128 */
4,
/* AES_CYPHER_192 */
6,
/* AES_CYPHER_256 */
8,
};
int g_aes_nb[] = {
/* AES_CYPHER_128 */
4,
/* AES_CYPHER_192 */
4,
/* AES_CYPHER_256 */
4,
};
/*
* aes Rcon:
*
* WARNING: Rcon is designed starting from 1 to 15, not 0 to 14.
* FIPS-197 Page 9: "note that i starts at 1, not 0"
*
* i | 0 1 2 3 4 5 6 7 8 9 10 11
12 13 14
* -----+---------------------------------------------------------------------
---------------------
* | [01] [02] [04] [08] [10] [20] [40] [80] [1b] [36] [6c] [d8] [ab]
[4d] [9a]
* RCON | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
[00] [00]
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
[00] [00]
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
[00] [00]
*/
static const uint32_t g_aes_rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
0x40000000, 0x80000000,
0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0xed000000,
0x9a000000
};
/*
* aes sbox and invert-sbox
*/
static const uint8_t g_aes_sbox[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B
C D E F */
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab,
0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72,
0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31,
0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2,
0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f,
0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58,
0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f,
0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3,
0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b,
0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4,
0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae,
0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b,
0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d,
0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28,
0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb,
0x16
};
static const uint8_t g_inv_sbox[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B
C D E F */
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7,
0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9,
0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3,
0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b,
0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6,
0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d,
0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45,
0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a,
0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf,
0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe,
0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a,
0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec,
0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c,
0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99,
0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21,
0x0c, 0x7d
};
uint8_t aes_sub_sbox(uint8_t val)
{
return g_aes_sbox[val];
}
uint32_t aes_sub_dword(uint32_t val)
{
uint32_t tmp = 0;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 0) & 0xFF))) << 0;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 8) & 0xFF))) << 8;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 16) & 0xFF))) << 16;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 24) & 0xFF))) << 24;
return tmp;
}
uint32_t aes_rot_dword(uint32_t val)
{
uint32_t tmp = val;
return (val >> 8) | ((tmp & 0xFF) << 24);
}
uint32_t aes_swap_dword(uint32_t val)
{
return (((val & 0x000000FF) << 24) |
((val & 0x0000FF00) << 8) |
((val & 0x00FF0000) >> 8) |
((val & 0xFF000000) >> 24));
}
/*
* nr: number of rounds
* nb: number of columns comprising the state, nb = 4 dwords (16 bytes)
* nk: number of 32-bit words comprising cipher key, nk = 4, 6, 8 (KeyLength/(4*8))
*/
void aes_key_expansion(AES_CYPHER_T mode, uint8_t *key, uint8_t *round)
{
uint32_t *w = (uint32_t *)round;
uint32_t t;
int i = 0;
do
{
w[i] = *((uint32_t *)&key[i * 4 + 0]);
}
while (++i < g_aes_nk[mode]);
do
{
if ((i % g_aes_nk[mode]) == 0)
{
t = aes_rot_dword(w[i - 1]);
t = aes_sub_dword(t);
t = t ^ aes_swap_dword(g_aes_rcon[i / g_aes_nk[mode] - 1]);
} else if (g_aes_nk[mode] > 6 && (i % g_aes_nk[mode]) == 4)
{
t = aes_sub_dword(w[i - 1]);
} else
{
t = w[i - 1];
}
w[i] = w[i - g_aes_nk[mode]] ^ t;
}
while (++i < g_aes_nb[mode] * (g_aes_rounds[mode] + 1));
}
void aes_add_round_key(AES_CYPHER_T mode, uint8_t *state,uint8_t *round, int nr)
{
uint32_t *w = (uint32_t *)round;
uint32_t *s = (uint32_t *)state;
int i;
for (i = 0; i < g_aes_nb[mode]; i++)
{
s[i] ^= w[nr * g_aes_nb[mode] + i];
}
}
void aes_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;
for (i = 0; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < 4; j++)
{
state[i * 4 + j] = aes_sub_sbox(state[i * 4 + j]);
}
}
}
void aes_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;
for (i = 1; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < i; j++)
{
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++)
{
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}
uint8_t aes_xtime(uint8_t x)
{
return ((x << 1) ^ (((x >> 7) & 1) * 0x1b));
}
uint8_t aes_xtimes(uint8_t x, int ts)
{
while (ts-- > 0)
{
x = aes_xtime(x);
}
return x;
}
uint8_t aes_mul(uint8_t x, uint8_t y)
{
/*
* encrypt: y has only 2 bits: can be 1, 2 or 3
* decrypt: y could be any value of 9, b, d, or e
*/
return ((((y >> 0) & 1) * aes_xtimes(x, 0)) ^
(((y >> 1) & 1) * aes_xtimes(x, 1)) ^
(((y >> 2) & 1) * aes_xtimes(x, 2)) ^
(((y >> 3) & 1) * aes_xtimes(x, 3)) ^
(((y >> 4) & 1) * aes_xtimes(x, 4)) ^
(((y >> 5) & 1) * aes_xtimes(x, 5)) ^
(((y >> 6) & 1) * aes_xtimes(x, 6)) ^
(((y >> 7) & 1) * aes_xtimes(x, 7)));
}
void aes_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2 };
uint8_t s[4];
int i, j, r;
for (i = 0; i < g_aes_nb[mode]; i++)
{
for (r = 0; r < 4; r++)
{
s[r] = 0;
for (j = 0; j < 4; j++)
{
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++)
{
state[i * 4 + r] = s[r];
}
}
}
int aes_encrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x72, 0x7C, 0x01, 0xC8,
0x46, 0x49, 0x37, 0xFF, 0x7E, 0x70, 0x56, 0x9D, 0x1D, 0x14,
0x33, 0xFB, 0x8A, 0xBF, 0x0E, 0x6C, 0xCC, 0xF6, 0x39, 0x93,
0xB2, 0x86, 0x6F, 0x0E, 0xAF, 0x92, 0x5C, 0xF5, 0xC1, 0xF5,
0xE8, 0x15, 0x0D, 0x03, 0xD1, 0x86, 0xBF, 0x85, 0xBE, 0x88,
0x10, 0x17, 0xE2, 0x7D, 0x39, 0x6D, 0x17, 0xDF, 0x34, 0x6E,
0xC6, 0x59, 0x8B, 0xEB, 0x78, 0xD1, 0x9B, 0xFC, 0x9A, 0xAC,
0x99, 0xD5, 0x86, 0xCB, 0xAD, 0xBB, 0x40, 0x92, 0x26, 0x50,
0x38, 0x43, 0xBD, 0xAC, 0xA2, 0xEF, 0x28, 0xEF, 0x59, 0xB1,
0x85, 0x54, 0x19, 0x23, 0xA3, 0x04, 0x21, 0x60, 0x1E, 0xA8,
0x83, 0x8F, 0xAA, 0x03, 0x2A, 0xC3, 0x2F, 0x57, 0x33, 0xE0,
0x8C, 0x53, 0x12, 0x80, 0x92, 0xFB, 0x91, 0x0F, 0x25, 0x82,
0x5C, 0x8C, 0x0A, 0xD5, 0x6F, 0x6C, 0x86, 0x86, 0x7D, 0xEC,
0x14, 0x7D, 0xEC, 0xE3, 0xEC, 0x4C, 0x4D, 0x76, 0xE6, 0x99,
0x22, 0x1A, 0x60, 0x1F, 0x5F, 0xF6, 0x74, 0x62, 0xB3, 0x15,
0x5D, 0x21, 0x14, 0xE4, 0xBB, 0xB8, 0x36, 0xFE, 0xDB, 0xA7,
0x69, 0x08, 0xAF, 0xC5, 0xDA, 0x1D };
/* round key */
uint8_t s[4 * 4] = { 0 };
/* state */
int nr, i, j;
/* key expansion */
// aes_key_expansion(mode, key, w);
/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode])
{
/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];
/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++)
{
if (nr > 0)
{
/* do SubBytes */
aes_sub_bytes(mode, s);
/* do ShiftRows */
aes_shift_rows(mode, s);
if (nr < g_aes_rounds[mode])
{
/* do MixColumns */
aes_mix_columns(mode, s);
}
}
/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
}
/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = s[j];
}
return 0;
}
int aes_encrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
return aes_encrypt(mode, data, len, key);
}
int aes_encrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv)
{
uint8_t w[4 * 4 * 15] = { 0 };
/* round key */
uint8_t s[4 * 4] = { 0 };
/* state */
uint8_t v[4 * 4] = { 0 };
/* iv */
int nr, i, j;
/* key expansion */
aes_key_expansion(mode, key, w);
memcpy(v, iv, sizeof(v));
/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode])
{
/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j] ^ v[j];
/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++)
{
if (nr > 0)
{
/* do SubBytes */
aes_sub_bytes(mode, s);
/* do ShiftRows */
aes_shift_rows(mode, s);
if (nr < g_aes_rounds[mode])
{
/* do MixColumns */
aes_mix_columns(mode, s);
}
}
/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
}
/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = v[j] = s[j];
}
return 0;
}
void inv_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;
for (i = 1; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < g_aes_nb[mode] - i; j++)
{
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++)
{
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}
uint8_t inv_sub_sbox(uint8_t val)
{
return g_inv_sbox[val];
}
void inv_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;
for (i = 0; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < 4; j++)
{
state[i * 4 + j] = inv_sub_sbox(state[i * 4 + j]);
}
}
}
void inv_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 0x0e, 0x0b, 0x0d, 0x09, 0x09, 0x0e, 0x0b, 0x0d,
0x0d, 0x09, 0x0e, 0x0b, 0x0b, 0x0d, 0x09, 0x0e };
uint8_t s[4];
int i, j, r;
for (i = 0; i < g_aes_nb[mode]; i++)
{
for (r = 0; r < 4; r++)
{
s[r] = 0;
for (j = 0; j < 4; j++)
{
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++)
{
state[i * 4 + r] = s[r];
}
}
}
int aes_decrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x72, 0x7C, 0x01, 0xC8,
0x46, 0x49, 0x37, 0xFF, 0x7E, 0x70, 0x56, 0x9D, 0x1D, 0x14,
0x33, 0xFB, 0x8A, 0xBF, 0x0E, 0x6C, 0xCC, 0xF6, 0x39, 0x93,
0xB2, 0x86, 0x6F, 0x0E, 0xAF, 0x92, 0x5C, 0xF5, 0xC1, 0xF5,
0xE8, 0x15, 0x0D, 0x03, 0xD1, 0x86, 0xBF, 0x85, 0xBE, 0x88,
0x10, 0x17, 0xE2, 0x7D, 0x39, 0x6D, 0x17, 0xDF, 0x34, 0x6E,
0xC6, 0x59, 0x8B, 0xEB, 0x78, 0xD1, 0x9B, 0xFC, 0x9A, 0xAC,
0x99, 0xD5, 0x86, 0xCB, 0xAD, 0xBB, 0x40, 0x92, 0x26, 0x50,
0x38, 0x43, 0xBD, 0xAC, 0xA2, 0xEF, 0x28, 0xEF, 0x59, 0xB1,
0x85, 0x54, 0x19, 0x23, 0xA3, 0x04, 0x21, 0x60, 0x1E, 0xA8,
0x83, 0x8F, 0xAA, 0x03, 0x2A, 0xC3, 0x2F, 0x57, 0x33, 0xE0,
0x8C, 0x53, 0x12, 0x80, 0x92, 0xFB, 0x91, 0x0F, 0x25, 0x82,
0x5C, 0x8C, 0x0A, 0xD5, 0x6F, 0x6C, 0x86, 0x86, 0x7D, 0xEC,
0x14, 0x7D, 0xEC, 0xE3, 0xEC, 0x4C, 0x4D, 0x76, 0xE6, 0x99,
0x22, 0x1A, 0x60, 0x1F, 0x5F, 0xF6, 0x74, 0x62, 0xB3, 0x15,
0x5D, 0x21, 0x14, 0xE4, 0xBB, 0xB8, 0x36, 0xFE, 0xDB, 0xA7,
0x69, 0x08, 0xAF, 0xC5, 0xDA, 0x1D };
/* round key */
uint8_t s[4 * 4] = { 0 };
/* state */
int nr, i, j;
/* key expansion */
// aes_key_expansion(mode, key, w);
/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode])
{
/* init state from user buffer (cyphertext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];
/* start AES cypher loop over all AES rounds */
for (nr = g_aes_rounds[mode]; nr >= 0; nr--)
{
/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
if (nr > 0)
{
if (nr < g_aes_rounds[mode])
{
/* do MixColumns */
inv_mix_columns(mode, s);
}
/* do ShiftRows */
inv_shift_rows(mode, s);
/* do SubBytes */
inv_sub_bytes(mode, s);
}
}
/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = s[j];
}
return 0;
}
int aes_decrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
return aes_decrypt(mode, data, len, key);
}
int aes_decrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv)
{
uint8_t w[4 * 4 * 15] = { 0 };
/* round key */
uint8_t s[4 * 4] = { 0 };
/* state */
uint8_t v[4 * 4] = { 0 };
/* iv */
int nr, i, j;
/* key expansion */
aes_key_expansion(mode, key, w);
memcpy(v, iv, sizeof(v));
/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode])
{
/* init state from user buffer (cyphertext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];
/* start AES cypher loop over all AES rounds */
for (nr = g_aes_rounds[mode]; nr >= 0; nr--)
{
/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
if (nr > 0)
{
if (nr < g_aes_rounds[mode])
{
/* do MixColumns */
inv_mix_columns(mode, s);
}
/* do ShiftRows */
inv_shift_rows(mode, s);
/* do SubBytes */
inv_sub_bytes(mode, s);
}
}
/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
{
uint8_t p = s[j] ^ v[j];
v[j] = data[i + j];
data[i + j] = p;
}
}
return 0;
}
int main()
{
//??
uint8_t buf[] = { 0xD1, 0xF7, 0xB4, 0x67, 0x72, 0x1E, 0x25, 0xBA, 0x44, 0x79,
0x2D, 0xC5, 0xFC, 0x9A, 0xCF, 0x00, 0xA9, 0xA8, 0xF9, 0xED,
0x4D, 0x0E, 0x74, 0x61, 0xB8, 0x17, 0x8D, 0x8F, 0xFD, 0x6D,
0x1E, 0x65 };
//??
uint8_t key[] =
{ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66 };
//??
uint8_t iv[] =
{ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
//?? 1-ECB 0-CBC
bool ecb_or_cbc = 1;
//??? 1-?? 0-??
bool en_or_de = 0;
//ECB ????
if(ecb_or_cbc&&en_or_de)
{
switch (sizeof(key))
{
case 16:aes_encrypt(AES_CYPHER_128, buf, sizeof(buf), key);
break;
case 24:aes_encrypt(AES_CYPHER_192, buf, sizeof(buf), key);
break;
case 32:aes_encrypt(AES_CYPHER_256, buf, sizeof(buf), key);
break;
}
//????
for (int i = 0; i < sizeof(buf); i++)
{
printf("0x%02x,", buf[i] & 0xFF);
}
}
//ECB ???? else if(ecb_or_cbc&&(!en_or_de))
{
switch (sizeof(key))
{
case 16:aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key);
break;
case 24:aes_decrypt(AES_CYPHER_192, buf, sizeof(buf), key);
break;
case 32:aes_decrypt(AES_CYPHER_256, buf, sizeof(buf), key);
break;
}
//????
for (int i = 0; i < sizeof(buf); i++)
{
printf("%c", (buf[i] & 0xFF)^0x66);
}
}
//CBC ???? else if((!ecb_or_cbc)&&en_or_de)
{
switch (sizeof(key))
{
case 16:aes_encrypt_cbc(AES_CYPHER_128, buf, sizeof(buf), key, iv);
break;
case 24:aes_encrypt_cbc(AES_CYPHER_192, buf, sizeof(buf), key, iv);
break;
case 32:aes_encrypt_cbc(AES_CYPHER_256, buf, sizeof(buf), key, iv);
break;
}
//????
for (int i = 0; i < sizeof(buf); i++)
{
printf("0x%02x,", buf[i] & 0xFF);
}
}
//CBC ???? else
{
switch (sizeof(key))
{
case 16:aes_decrypt_cbc(AES_CYPHER_128, buf, sizeof(buf), key, iv);
break;
case 24:aes_decrypt_cbc(AES_CYPHER_192, buf, sizeof(buf), key, iv);
break;
case 32:aes_decrypt_cbc(AES_CYPHER_256, buf, sizeof(buf), key, iv);
break;
}
//????
for (int i = 0; i < sizeof(buf); i++)
{
printf("%c", buf[i] & 0xFF);
}
}
printf("n");
return 0;
}