AES是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。1998年NIST开始AES第一轮分析、测试和征集,共产生了15个候选算法。1999年3月完成了第二轮AES的分析、测试。2000年10月2日美国政府正式宣布选中比利时密码学家Joan Daemen 和 Vincent Rijmen 提出的一种密码算法RIJNDAEL 作为 AES。高级加密标准由NIST于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。
AES加密数据块分组长度必须为128比特,密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足时,会补齐),分别称为AES-128、AES-192和AES-256。AES加密有很多轮的重复和变换。大致步骤如下:1、密钥扩展(KeyExpansion),2、初始轮(Initial Round),3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,4、最终轮(Final Round),最终轮没有MixColumns。
Crypto++库很好的一点是,不用我们手动的对明文块或者密文块进行分组,而是在实现中自动完成了,这样就减少了我们的工作量。
等等,那AES在分组的时候,有没有什么标准?难道只是将需要加密的信息分成128bit的一块块吗?事实上不是这个样子的。AES作为分组密码的一种,而分组密码从DES时代起就拥有了很多种的工作模式。下面简要介绍各种模式。(部分文字及图片来自维基百科)
(1) ECB模式
最简单的加密模式即为电子密码本(Electronic codebook,ECB)模式。需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密。简单的理解,ECB模式就是将很长的明文,按照128bit分组,不足补零。每组用相同密钥进行加密,最后将各组密文拼在一起即可。就是分割处理的想法,各个不同的明文块和密文块之间没有运算关系。
ECB模式的优点是可并行运算,速度快,易于标准化。缺点是分组加密不能隐蔽数据模式,即相同的明文组蕴含着相同的密文组;不能抵抗组的重放、嵌入、删除等攻击;加密长度只能是分组的倍数。
(2) CBC模式
1976年,IBM发明了密码分组链接(CBC,Cipher-block chaining)模式。在CBC模式中,每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。
(3) CFB
密文反馈(CFB,Cipherfeedback)模式类似于CBC,可以将块密码变为自同步的流密码;工作过程亦非常相似,CFB的解密过程几乎就是颠倒的CBC的加密过程。
(4)OFB
输出反馈模式(Outputfeedback, OFB)可以将块密码变成同步的流密码。它产生密钥流的块,然后将其与明文块进行异或,得到密文。与其它流密码一样,密文中一个位的翻转会使明文中同样位置的位也产生翻转。这种特性使得许多错误校正码,例如奇偶校验位,即使在加密前计算而在加密后进行校验也可以得出正确结果。由于XOR操作的对称性,加密和解密操作是完全相同的。
(5)CTR
与OFB相似,CTR将块密码变为流密码。它通过递增一个加密计数器以产生连续的密钥流,其中,计数器可以是任意保证不产生长时间重复输出的函数,但使用一个普通的计数器是最简单和最常见的做法。CTR模式的特征类似于OFB,但它允许在解密时进行随机存取。由于加密和解密过程均可以进行并行处理,CTR适合运用于多处理器的硬件上。
注意图中的“nonce(随机数)”与其它图中的IV(初始化向量)相同。IV、随机数和计数器均可以通过连接,相加或异或使得相同平文产生不同的密文。
(6)CBC_CTS
即应用了密文窃取(Ciphertextstealing)技术的CBC。
我们在上面的介绍中可以注意到,ECB和CBC两种模式,其输出密文长度永远都是分块大小(128bits)的整数倍,而其他模式都是和输入明文等长。为了解决输出密文偏长的情况,就可以采用密文窃取方式。CBC_CTS具体过程如下:
加密过程:
a. Xn−1 = Pn−1XOR Cn−2.
b. En−1 = Encrypt (K, Xn−1).
c. Cn = Head (En−1,M).
d. P = Pn || 0B−M.
e. Dn = En−1XOR P.
f. Cn−1 = Encrypt (K, Dn).
解密过程:
a. Dn = Decrypt (K, Cn−1).
b. C = Cn || 0B−M.
c. Xn = DnXOR C.
d. Pn = Head (Xn,M).
e. En−1 = Cn|| Tail (Xn, B−M).
f. Xn−1 = Decrypt (K, En−1).
g. Pn−1 = Xn−1XOR Cn−2.
下面是我绘制的示意图。
按照上文所述,对建立的Win32控制台应用程序进行必要的配置之后(在上篇文章中),就可以开始写程序了。下面就是完成的AES程序。该程序可以去我的资源中找到。
[cpp] view plain copy
1. // aestest2.cpp : 定义控制台应用程序的入口点。
2. //
3.
4. #include "stdafx.h"
5. #include <aes.h>
6. #include <cryptopp/Hex.h> // StreamTransformationFilter
7. #include <cryptopp/modes.h> // CFB_Mode
8. #include <iostream> // std:cerr
9. #include <sstream> // std::stringstream
10. #include <string>
11.
12. using namespace std;
13. using namespace CryptoPP;
14. #pragma comment( lib, "cryptlib.lib" )
15.
16.
17.
18. std::string ECB_AESEncryptStr(std::string sKey, const char *plainText)
19. {
20. std::string outstr;
21.
22. //填key
23. SecByteBlock key(AES::MAX_KEYLENGTH);
24. memset(key,0x30,key.size() );
25. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
26.
27.
28. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
29.
30. ECB_Mode_ExternalCipher::Encryption ecbEncryption(aesEncryption);
31. new HexEncoder(new StringSink(outstr)));
32. ecbEncryptor.Put((byte *)plainText, strlen(plainText));
33. ecbEncryptor.MessageEnd();
34.
35. return outstr;
36. }
37.
38.
39. std::string ECB_AESDecryptStr(std::string sKey, const char *cipherText)
40. {
41. std::string outstr;
42.
43. //填key
44. SecByteBlock key(AES::MAX_KEYLENGTH);
45. memset(key,0x30,key.size() );
46. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
47.
48. ECB_Mode<AES >::Decryption ecbDecryption((byte *)key, AES::MAX_KEYLENGTH);
49.
50. new StreamTransformationFilter(ecbDecryption, new StringSink(outstr)));
51. decryptor.Put((byte *)cipherText, strlen(cipherText));
52. decryptor.MessageEnd();
53.
54. return outstr;
55. }
56.
57.
58. std::string CBC_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
59. {
60. std::string outstr;
61.
62. //填key
63. SecByteBlock key(AES::MAX_KEYLENGTH);
64. memset(key,0x30,key.size() );
65. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
66.
67. //填iv
68. byte iv[AES::BLOCKSIZE];
69. memset(iv,0x30,AES::BLOCKSIZE);
70. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
71.
72. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
73.
74. CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
75.
76. new HexEncoder(new StringSink(outstr)));
77. cbcEncryptor.Put((byte *)plainText, strlen(plainText));
78. cbcEncryptor.MessageEnd();
79.
80. return outstr;
81. }
82.
83.
84. std::string CBC_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
85. {
86. std::string outstr;
87.
88. //填key
89. SecByteBlock key(AES::MAX_KEYLENGTH);
90. memset(key,0x30,key.size() );
91. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
92.
93. //填iv
94. byte iv[AES::BLOCKSIZE];
95. memset(iv,0x30,AES::BLOCKSIZE);
96. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
97.
98. CBC_Mode<AES >::Decryption cbcDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
99.
100. new StreamTransformationFilter(cbcDecryption, new StringSink(outstr)));
101. decryptor.Put((byte *)cipherText, strlen(cipherText));
102. decryptor.MessageEnd();
103.
104. return outstr;
105. }
106.
107.
108. std::string CBC_CTS_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
109. {
110. std::string outstr;
111.
112. //填key
113. SecByteBlock key(AES::MAX_KEYLENGTH);
114. memset(key,0x30,key.size() );
115. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
116.
117. //填iv
118. byte iv[AES::BLOCKSIZE];
119. memset(iv,0x30,AES::BLOCKSIZE);
120. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
121.
122. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
123.
124. CBC_CTS_Mode_ExternalCipher::Encryption cbcctsEncryption(aesEncryption, iv);
125.
126. new HexEncoder(new StringSink(outstr)));
127. cbcctsEncryptor.Put((byte *)plainText, strlen(plainText));
128. cbcctsEncryptor.MessageEnd();
129.
130. return outstr;
131. }
132.
133.
134. std::string CBC_CTS_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
135. {
136. std::string outstr;
137.
138. //填key
139. SecByteBlock key(AES::MAX_KEYLENGTH);
140. memset(key,0x30,key.size() );
141. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
142.
143. //填iv
144. byte iv[AES::BLOCKSIZE];
145. memset(iv,0x30,AES::BLOCKSIZE);
146. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
147.
148. CBC_CTS_Mode<AES >::Decryption cbcctsDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
149.
150. new StreamTransformationFilter(cbcctsDecryption, new StringSink(outstr)));
151. decryptor.Put((byte *)cipherText, strlen(cipherText));
152. decryptor.MessageEnd();
153.
154. return outstr;
155. }
156.
157.
158.
159.
160.
161. std::string CFB_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
162. {
163. std::string outstr;
164.
165. //填key
166. SecByteBlock key(AES::MAX_KEYLENGTH);
167. memset(key,0x30,key.size() );
168. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
169.
170. //填iv
171. byte iv[AES::BLOCKSIZE];
172. memset(iv,0x30,AES::BLOCKSIZE);
173. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
174.
175. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
176.
177. CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv);
178.
179. new HexEncoder(new StringSink(outstr)));
180. cfbEncryptor.Put((byte *)plainText, strlen(plainText));
181. cfbEncryptor.MessageEnd();
182.
183. return outstr;
184. }
185.
186.
187. std::string CFB_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
188. {
189. std::string outstr;
190.
191. //填key
192. SecByteBlock key(AES::MAX_KEYLENGTH);
193. memset(key,0x30,key.size() );
194. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
195.
196. //填iv
197. byte iv[AES::BLOCKSIZE];
198. memset(iv,0x30,AES::BLOCKSIZE);
199. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
200.
201. CFB_Mode<AES >::Decryption cfbDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
202.
203. new StreamTransformationFilter(cfbDecryption, new StringSink(outstr)));
204. decryptor.Put((byte *)cipherText, strlen(cipherText));
205. decryptor.MessageEnd();
206.
207. return outstr;
208. }
209.
210.
211. std::string OFB_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
212. {
213. std::string outstr;
214.
215. //填key
216. SecByteBlock key(AES::MAX_KEYLENGTH);
217. memset(key,0x30,key.size() );
218. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
219.
220. //填iv
221. byte iv[AES::BLOCKSIZE];
222. memset(iv,0x30,AES::BLOCKSIZE);
223. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
224.
225. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
226.
227. OFB_Mode_ExternalCipher::Encryption ofbEncryption(aesEncryption, iv);
228.
229. new HexEncoder(new StringSink(outstr)));
230. ofbEncryptor.Put((byte *)plainText, strlen(plainText));
231. ofbEncryptor.MessageEnd();
232.
233. return outstr;
234. }
235.
236.
237. std::string OFB_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
238. {
239. std::string outstr;
240.
241. //填key
242. SecByteBlock key(AES::MAX_KEYLENGTH);
243. memset(key,0x30,key.size() );
244. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
245.
246. //填iv
247. byte iv[AES::BLOCKSIZE];
248. memset(iv,0x30,AES::BLOCKSIZE);
249. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
250.
251. OFB_Mode<AES >::Decryption ofbDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
252.
253. new StreamTransformationFilter(ofbDecryption, new StringSink(outstr)));
254. decryptor.Put((byte *)cipherText, strlen(cipherText));
255. decryptor.MessageEnd();
256.
257. return outstr;
258. }
259.
260. std::string CTR_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
261. {
262. std::string outstr;
263.
264. //填key
265. SecByteBlock key(AES::MAX_KEYLENGTH);
266. memset(key,0x30,key.size() );
267. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
268.
269. //填iv
270. byte iv[AES::BLOCKSIZE];
271. memset(iv,0x30,AES::BLOCKSIZE);
272. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
273.
274. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
275.
276. CTR_Mode_ExternalCipher::Encryption ctrEncryption(aesEncryption, iv);
277.
278. new HexEncoder(new StringSink(outstr)));
279. ctrEncryptor.Put((byte *)plainText, strlen(plainText));
280. ctrEncryptor.MessageEnd();
281.
282. return outstr;
283. }
284.
285.
286. std::string CTR_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
287. {
288. std::string outstr;
289.
290. //填key
291. SecByteBlock key(AES::MAX_KEYLENGTH);
292. memset(key,0x30,key.size() );
293. sKey.size()<=AES::MAX_KEYLENGTH?memcpy(key,sKey.c_str(),sKey.size()):memcpy(key,sKey.c_str(),AES::MAX_KEYLENGTH);
294.
295. //填iv
296. byte iv[AES::BLOCKSIZE];
297. memset(iv,0x30,AES::BLOCKSIZE);
298. sIV.size()<=AES::BLOCKSIZE?memcpy(iv,sIV.c_str(),sIV.size()):memcpy(iv,sIV.c_str(),AES::BLOCKSIZE);
299.
300. CTR_Mode<AES >::Decryption ctrDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
301.
302. new StreamTransformationFilter(ctrDecryption, new StringSink(outstr)));
303. decryptor.Put((byte *)cipherText, strlen(cipherText));
304. decryptor.MessageEnd();
305.
306. return outstr;
307. }
308.
309. int _tmain(int argc, _TCHAR* argv[])
310. {
311. "This Program shows how to use ECB, CBC, CBC_CTS, CFB, OFB and CTR mode of AES in Crypto++.";
312. "0123456789ABCDEF0123456789ABCDEF";//256bits, also can be 128 bits or 192bits
313. "ABCDEF0123456789";//128 bits
314. string ECB_EncryptedText,ECB_DecryptedText,
315. CBC_EncryptedText,CBC_DecryptedText,
316. CBC_CTS_EncryptedText,CBC_CTS_DecryptedText,
317. CFB_EncryptedText,CFB_DecryptedText,
318. OFB_EncryptedText,OFB_DecryptedText,
319. CTR_EncryptedText,CTR_DecryptedText;
320.
321. //ECB
322. //ECB加密
323. //ECB解密
324.
325. //CBC
326. //CBC加密
327. //CBC解密
328.
329. //CBC_CTS
330. //CBC_CTS加密
331. //CBC_CTS解密
332.
333. //CFB
334. //CFB加密
335. //CFB解密
336.
337. //OFB
338. //OFB加密
339. //OFB解密
340.
341. //CTR
342. //CTR加密
343. //CTR解密
344.
345.
346. "Crypto++ AES-256 加密测试"<< endl;
347. "分别使用ECB,CBC, CBC_CTR,CFB,OFB和CTR模式"<< endl;
348. "加密用密钥:" << aesKey << endl;
349. "密钥长度:" << AES::MAX_KEYLENGTH*8 <<"bits" << endl;
350. "IV:" << aesIV << endl;
351. cout << endl;
352.
353. "ECB测试"<< endl;
354. "原文:" << plainText << endl;
355. "密文:" << ECB_EncryptedText << endl;
356. "恢复明文:" << ECB_DecryptedText << endl << endl;
357.
358. "CBC测试"<< endl;
359. "原文:" << plainText << endl;
360. "密文:" << CBC_EncryptedText << endl;
361. "恢复明文:" << CBC_DecryptedText << endl << endl;
362.
363. "CBC_CTS测试"<< endl;
364. "原文:" << plainText << endl;
365. "密文:" << CBC_CTS_EncryptedText << endl;
366. "恢复明文:" << CBC_CTS_DecryptedText << endl << endl;
367.
368. "CFB测试"<< endl;
369. "原文:" << plainText << endl;
370. "密文:" << CFB_EncryptedText << endl;
371. "恢复明文:" << CFB_DecryptedText << endl << endl;
372.
373. "OFB测试"<< endl;
374. "原文:" << plainText << endl;
375. "密文:" << OFB_EncryptedText << endl;
376. "恢复明文:" << OFB_DecryptedText << endl << endl;
377.
378. "CTR测试"<< endl;
379. "原文:" << plainText << endl;
380. "密文:" << CTR_EncryptedText << endl;
381. "恢复明文:" << CTR_DecryptedText << endl << endl;
382.
383.
384. getchar();
385. return 0;
386. }
下面是程序运行结果。可以注意一下各种模式输出的密文长度和具体内容。可以发现ECB和CBC输出模式最长(因要补足128比特块),其他模式输出长度和原文一样。各种模式输出均不相同。