Browse Source

MD5及其他加密算法示例

Jeff 6 years ago
parent
commit
2164ad6869

+ 1200 - 0
MD5Test/3DES.cpp

@@ -0,0 +1,1200 @@
+#include "StdAfx.h"
+#include "DES.h"
+
+/************************************************************************  
+* DES/3DES原理:  
+*  1-1、变换密钥  
+*  1-1-1、取得64位的密钥,每个第8位作为奇偶校验位。程序上无需任何操作  
+*  
+*  1-2、变换密钥  
+*  1-2-1、舍弃64位密钥中的奇偶校验位,根据下表(PC-1)进行密钥变换(换位)得到56位的密钥,在变换中,奇偶校验位被舍弃  
+*  
+*  Permuted Choice 1 (PC-1),本表表示的数组下标从1开始,因此转换时需要:PC1_Table[i]-1  
+*    57, 49, 41, 33, 25, 17,  9,  
+*    1, 58, 50, 42, 34, 26, 18,  
+*    10,  2, 59, 51, 43, 35, 27,  
+*    19, 11,  3, 60, 52, 44, 36,  
+*    63, 55, 47, 39, 31, 23, 15,  
+*    7, 62, 54, 46, 38, 30, 22,  
+*    14,  6, 61, 53, 45, 37, 29,  
+*    21, 13,  5, 28, 20, 12,  4  
+*  
+*  1-2-2、将变换后的密钥分为两个部分,开始的28位称为C[0],最后的28位称为D[0]  
+*  1-2-3、生成16个子密钥, I = 1。<这里假设I为生成密钥的轮数,它的基数是从1开始,即I取值为 1 – 16 >  
+*  1-2-3-1、同时将C[I]、D[I]左移1位或2位,根据I值决定左移的位数。见下表:  
+*           I: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  
+*           左移位数: 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1  
+*           <每轮移位输出的C[I] D[I]作为下一轮移位时输入的C[I] D[I]  
+*            这里有个关键点,进行解密时这里是向右移,而且在I = 1时无需移位。即:  
+*            右移位数: 0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1  
+*            解密时也只有这里也有区别,其它的地方和加密是一样的,DES算法的很多换位表是互反的,即可能你用  
+*            表1换位完后,用表2再换一遍就又和原始值一样了>  
+*  1-2-3-2、将C[I]D[I]作为一个整体按下表(PC-2)变换,得到48位的K[I]  
+*  
+*  Permuted Choice 2 (PC-2),本表表示的数组下标从1开始,因此转换时需要:PC2_Table[i]-1  
+*    14, 17, 11, 24,  1,  5,  
+*    3, 28, 15,  6, 21, 10,  
+*    23, 19, 12,  4, 26,  8,  
+*    16,  7, 27, 20, 13,  2,  
+*    41, 52, 31, 37, 47, 55,  
+*    30, 40, 51, 45, 33, 48,  
+*    44, 49, 39, 56, 34, 53,  
+*    46, 42, 50, 36, 29, 32  
+*  
+*  1-2-3-3、从1-2-3-1处循环执行,直到K[16]被计算完成  
+*  
+*  2、处理64位的数据  
+*  2-1、取得64位的数据,如果数据长度不足64位,应该将其扩展为64位(例如补零)  
+*       <补什么要看具体数据,只能补数据取值范围外的字符,如果数据取值范围是0x00 – 0XFF而且还不是64位整倍数,那就要另想办法,比如在数据前面加上长度什么的>  
+*  2-2、将64位数据按下表变换(IP)  
+*  
+*  Initial Permutation (IP),本表表示的数组下标从1开始,因此转换时需要:IP_Table[i]-1  
+*    58, 50, 42, 34, 26, 18, 10, 2,  
+*    60, 52, 44, 36, 28, 20, 12, 4,  
+*    62, 54, 46, 38, 30, 22, 14, 6,  
+*    64, 56, 48, 40, 32, 24, 16, 8,  
+*    57, 49, 41, 33, 25, 17,  9, 1,  
+*    59, 51, 43, 35, 27, 19, 11, 3,  
+*    61, 53, 45, 37, 29, 21, 13, 5,  
+*    63, 55, 47, 39, 31, 23, 15, 7  
+*  
+*  2-3、将变换后的数据分为两部分,开始的32位称为L[0],最后的32位称为R[0]  
+*  2-4、用16个子密钥加密数据,初始I=1  
+*  2-4-1、将32位的R[I-1]按下表(E)扩展为48位的E[I-1]  
+*  Expansion (E),本表表示的数组下标从1开始,因此转换时需要:E_Table[i]-1  
+*    32,  1,  2,  3,  4,  5,  
+*    4,  5,  6,  7,  8,  9,  
+*    8,  9, 10, 11, 12, 13,  
+*    12, 13, 14, 15, 16, 17,  
+*    16, 17, 18, 19, 20, 21,  
+*    20, 21, 22, 23, 24, 25,  
+*    24, 25, 26, 27, 28, 29,  
+*    28, 29, 30, 31, 32,  1  
+*  
+*  2-4-2、异或E[I-1]和K[I],即E[I-1] XOR K[I] <上面生成的16组子密钥就是在这里用到的>  
+*  2-4-3、将异或后的结果分为8个6位长的部分,第1位到第6位称为B[1],第7位到第12位称为B[2],依此类推,第43位到第48位称为B[8]  
+*  2-4-4、按S表变换所有的B[J],初始J=1。所有在S表的值都被当作4位长度处理  
+*  2-4-4-1、将B[J]的第1位和第6位组合为一个2位长度的变量M,M作为在S[J]中的行号  
+*  2-4-4-2、将B[J]的第2位到第5位组合,作为一个4位长度的变量N,N作为在S[J]中的列号  
+*  2-4-4-3、用S[J][M][N]来取代B[J]  
+*  
+*  Substitution Box  
+*    S[1]  
+*    14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 7  
+*    0 15 7 4 14 2 13 1 10 6 12 11 9 5 3 8  
+*    4 1 14 8 13 6 2 11 15 12 9 7 3 10 5 0  
+*    15 12 8 2 4 9 1 7 5 11 3 14 10 0 6 13  
+*  
+*    S[2]  
+*    15 1 8 14 6 11 3 4 9 7 2 13 12 0 5 10  
+*    3 13 4 7 15 2 8 14 12 0 1 10 6 9 11 5  
+*    0 14 7 11 10 4 13 1 5 8 12 6 9 3 2 15  
+*    13 8 10 1 3 15 4 2 11 6 7 12 0 5 14 9  
+*  
+*    S[3]  
+*    10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8  
+*    13 7 0 9 3 4 6 10 2 8 5 14 12 11 15 1  
+*    13 6 4 9 8 15 3 0 11 1 2 12 5 10 14 7  
+*    1 10 13 0 6 9 8 7 4 15 14 3 11 5 2 12  
+*  
+*    S[4]  
+*    7 13 14 3 0 6 9 10 1 2 8 5 11 12 4 15  
+*    13 8 11 5 6 15 0 3 4 7 2 12 1 10 14 9  
+*    10 6 9 0 12 11 7 13 15 1 3 14 5 2 8 4  
+*    3 15 0 6 10 1 13 8 9 4 5 11 12 7 2 14  
+*  
+*    S[5]  
+*    2 12 4 1 7 10 11 6 8 5 3 15 13 0 14 9  
+*    14 11 2 12 4 7 13 1 5 0 15 10 3 9 8 6  
+*    4 2 1 11 10 13 7 8 15 9 12 5 6 3 0 14  
+*    11 8 12 7 1 14 2 13 6 15 0 9 10 4 5 3  
+*  
+*    S[6]  
+*    12 1 10 15 9 2 6 8 0 13 3 4 14 7 5 11  
+*    10 15 4 2 7 12 9 5 6 1 13 14 0 11 3 8  
+*    9 14 15 5 2 8 12 3 7 0 4 10 1 13 11 6  
+*    4 3 2 12 9 5 15 10 11 14 1 7 6 0 8 13  
+*  
+*    S[7]  
+*    4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1  
+*    13 0 11 7 4 9 1 10 14 3 5 12 2 15 8 6  
+*    1 4 11 13 12 3 7 14 10 15 6 8 0 5 9 2  
+*    6 11 13 8 1 4 10 7 9 5 0 15 14 2 3 12  
+*  
+*    S[8]  
+*    13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7  
+*    1 15 13 8 10 3 7 4 12 5 6 11 0 14 9 2  
+*    7 11 4 1 9 12 14 2 0 6 10 13 15 3 5 8  
+*    2 1 14 7 4 10 8 13 15 12 9 0 3 5 6 11  
+*  
+*  2-4-4-4、从2-4-4-1处循环执行,直到B[8]被替代完成  
+*  2-4-4-5、将B[1]到B[8]组合,按下表(P)变换,得到P <B[1]到B[8]组成一个32位的数据>  
+*  
+*  Permutation P  
+*    16, 7, 20, 21,  
+*    29, 12, 28, 17,  
+*    1,  15, 23, 26,  
+*    5,  18, 31, 10,  
+*    2,  8, 24, 14,  
+*    32, 27, 3,  9,  
+*    19, 13, 30, 6,  
+*    22, 11, 4,  25  
+*  
+*  2-4-6、异或P和L[I-1]结果放在R[I],即R[I] = P XOR L[I - 1]  
+*  2-4-7、L[I] = R[I - 1]  
+*  2-4-8、从2-4-1处开始循环执行,直到K[16]被变换完成  
+*  2-4-5、组合变换后的R[16]L[16](注意:R作为开始的32位),按下表(IP-1)变换得到最后的结果  
+*         <这里要注意了,是对R[16]L[16],而不是L[16]R[16] 即,需要进行左32位和右32位调换一下位置, 这里下标里的16是指轮数,不是位数>  
+*  
+*  Final Permutation (IP**-1)  
+*    40, 8, 48, 16, 56, 24, 64, 32,  
+*    39, 7, 47, 15, 55, 23, 63, 31,  
+*    38, 6, 46, 14, 54, 22, 62, 30,  
+*    37, 5, 45, 13, 53, 21, 61, 29,  
+*    36, 4, 44, 12, 52, 20, 60, 28,  
+*    35, 3, 43, 11, 51, 19, 59, 27,  
+*    34, 2, 42, 10, 50, 18, 58, 26,  
+*    33, 1, 41,  9, 49, 17, 57, 25  
+*  
+*  3DES计算方法如下:  
+*    3DES(加密) = DES(key1, 加密) DES(key2, 解密)  DES(key3, 加密)  
+*    3DES(解密) = DES(key3, 解密) DES(key2, 加密)  DES(key1, 解密)  
+*    每个KEY为64位,总共可以有192位的KEY, 但一般都只使用128位的key  
+*    如果只用128位密钥,则key3 = key1  
+*  
+*************************************************************************/   
+
+#include "3des.h"   
+#include <stdlib.h>   
+#include <stdio.h>   
+#include <memory.h>   
+#include <string.h>   
+#include <ctype.h>   
+
+const char IP_Table[64] =   
+{   
+	58, 50, 42, 34, 26, 18, 10, 2,   
+	60, 52, 44, 36, 28, 20, 12, 4,   
+	62, 54, 46, 38, 30, 22, 14, 6,   
+	64, 56, 48, 40, 32, 24, 16, 8,   
+	57, 49, 41, 33, 25, 17,  9, 1,   
+	59, 51, 43, 35, 27, 19, 11, 3,   
+	61, 53, 45, 37, 29, 21, 13, 5,   
+	63, 55, 47, 39, 31, 23, 15, 7   
+};   
+
+const char IPR_Table[64] =   
+{   
+	40, 8, 48, 16, 56, 24, 64, 32,   
+	39, 7, 47, 15, 55, 23, 63, 31,   
+	38, 6, 46, 14, 54, 22, 62, 30,   
+	37, 5, 45, 13, 53, 21, 61, 29,   
+	36, 4, 44, 12, 52, 20, 60, 28,   
+	35, 3, 43, 11, 51, 19, 59, 27,   
+	34, 2, 42, 10, 50, 18, 58, 26,   
+	33, 1, 41,  9, 49, 17, 57, 25   
+};   
+
+const char E_Table[48] =   
+{   
+	32,  1,  2,  3,  4,  5,   
+	4,  5,  6,  7,  8,  9,   
+	8,  9, 10, 11, 12, 13,   
+	12, 13, 14, 15, 16, 17,   
+	16, 17, 18, 19, 20, 21,   
+	20, 21, 22, 23, 24, 25,   
+	24, 25, 26, 27, 28, 29,   
+	28, 29, 30, 31, 32,  1   
+};   
+
+const char P_Table[32] =   
+{   
+	16, 7, 20, 21,   
+	29, 12, 28, 17,   
+	1,  15, 23, 26,   
+	5,  18, 31, 10,   
+	2,  8, 24, 14,   
+	32, 27, 3,  9,   
+	19, 13, 30, 6,   
+	22, 11, 4,  25   
+};   
+
+const char PC1_Table[56] =   
+{   
+	57, 49, 41, 33, 25, 17,  9,   
+	1, 58, 50, 42, 34, 26, 18,   
+	10,  2, 59, 51, 43, 35, 27,   
+	19, 11,  3, 60, 52, 44, 36,   
+	63, 55, 47, 39, 31, 23, 15,   
+	7, 62, 54, 46, 38, 30, 22,   
+	14,  6, 61, 53, 45, 37, 29,   
+	21, 13,  5, 28, 20, 12,  4   
+};   
+
+const char PC2_Table[48] =   
+{   
+	14, 17, 11, 24,  1,  5,   
+	3, 28, 15,  6, 21, 10,   
+	23, 19, 12,  4, 26,  8,   
+	16,  7, 27, 20, 13,  2,   
+	41, 52, 31, 37, 47, 55,   
+	30, 40, 51, 45, 33, 48,   
+	44, 49, 39, 56, 34, 53,   
+	46, 42, 50, 36, 29, 32   
+};   
+
+const char LOOP_Table[16] =   
+{   
+	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1   
+};   
+
+const char S_Box[8][4][16] =   
+{   
+	{   
+		{14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7},   
+		{ 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8},   
+		{ 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0},   
+		{15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13}   
+	},   
+
+	{   
+		{15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10},   
+		{ 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5},   
+		{ 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15},   
+		{13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9}   
+	},   
+
+	{   
+		{10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8},   
+		{13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1},   
+		{13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7},   
+		{ 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12}   
+	},   
+
+	{   
+		{ 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15},   
+		{13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9},   
+		{10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4},   
+		{ 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14}   
+	},   
+
+	{   
+		{ 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9},   
+		{14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6},   
+		{ 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14},   
+		{11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3}   
+	},   
+
+	{   
+		{12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11},   
+		{10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8},   
+		{ 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6},   
+		{ 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13}   
+	},   
+
+	{   
+		{ 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1},   
+		{13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6},   
+		{ 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2},   
+		{ 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12}   
+	},   
+
+	{   
+		{13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7},   
+		{ 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2},   
+		{ 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8},   
+		{ 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11}   
+	}   
+};   
+
+char*  ch64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";   
+
+
+
+static void ByteToBit(char *Out, const char *In, int bits);   
+static void BitToByte(char *Out, const char *In, int bits);   
+static void RotateL(char *In, int len, int loop);   
+static void Xor(char *InA, const char *InB, int len);   
+static void Transform(char *Out, const char *In, const char *Table, int len);   
+static void S_func(char Out[32], const char In[48]);   
+static void F_func(char In[32], const char Ki[48]);   
+static void SetSubKey(PSubKey pSubKey, const char Key[8]);   
+static void DES(char Out[8], const char In[8], const PSubKey pSubKey, int Type);   
+
+
+
+/*******************************************************************  
+函 数 名 称:  ByteToBit  
+功 能 描 述:  把BYTE转化为Bit流  
+参 数 说 明:  Out:    输出的Bit流[in][out]  
+In:     输入的BYTE流[in]  
+bits:   Bit流的长度[in]  
+
+返回值 说明:   void  
+*******************************************************************/   
+static void ByteToBit(char *Out, const char *In, int bits)   
+{   
+	int i;   
+	for (i=0; i<bits; ++i)   
+		Out[i] = (In[i>>3]>>(7 - i&7)) & 1;   
+}   
+
+/*******************************************************************  
+函 数 名 称:  BitToByte  
+功 能 描 述:  把Bit转化为Byte流  
+参 数 说 明:  Out:    输出的BYTE流[in][out]  
+In:     输入的Bit流[in]  
+bits:   Bit流的长度[in]  
+
+返回值 说明:   void  
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+static void BitToByte(char *Out, const char *In, int bits)   
+{   
+	int i;   
+	memset(Out, 0, bits>>3);   
+	for (i=0; i<bits; ++i) Out[i>>3] |= In[i]<<(7 - i&7);   
+}   
+
+/*******************************************************************  
+函 数 名 称:  RotateL  
+功 能 描 述:  把BIT流按位向左迭代  
+参 数 说 明:  In:     输入的Bit流[in][out]  
+len:    Bit流的长度[in]  
+loop:   向左迭代的长度  
+
+返回值 说明:   void  
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+static void RotateL(char *In, int len, int loop)   
+{   
+	char szTmp[256] = {0};   
+
+	if (len >= 256) return;   
+	if (loop==0 || loop>=256) return;   
+
+	memset(szTmp, 0x00, sizeof(szTmp));   
+
+	memcpy(szTmp, In, loop);   
+	memmove(In, In+loop, len-loop);   
+	memcpy(In+len-loop, szTmp, loop);   
+}   
+
+/*******************************************************************  
+函 数 名 称:  Xor  
+功 能 描 述:  把两个Bit流进行异或  
+参 数 说 明:  InA:    输入的Bit流[in][out]  
+InB:    输入的Bit流[in]  
+loop:   Bit流的长度  
+
+返回值 说明:   void  
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+static void Xor(char *InA, const char *InB, int len)   
+{   
+	int i;   
+	for (i=0; i<len; ++i) InA[i] ^= InB[i];   
+}   
+
+/*******************************************************************  
+函 数 名 称:  Transform  
+功 能 描 述:  把两个Bit流按表进行位转化  
+参 数 说 明:  Out:    输出的Bit流[out]  
+In:     输入的Bit流[in]  
+Table:  转化需要的表指针  
+len:    转化表的长度  
+
+返回值 说明:   void  
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+static void Transform(char *Out, const char *In, const char *Table, int len)   
+{   
+	char szTmp[256] = {0};   
+	int i;   
+
+	if (!Out || !In || !Table) return;   
+	if (len >= 256) return;   
+
+	memset(szTmp, 0x00, sizeof(szTmp));   
+	for (i=0; i<len; ++i) szTmp[i] = In[Table[i]-1];   
+
+	memcpy(Out, szTmp, len);   
+}   
+
+/*******************************************************************  
+函 数 名 称:  S_func  
+功 能 描 述:  实现数据加密S BOX模块  
+参 数 说 明:  Out:    输出的32Bit[out]  
+In:     输入的48Bit[in]  
+
+返回值 说明:   void  
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+static void S_func(char Out[32], const char In[48])   
+{   
+	int i,j,k,l;   
+	for (i=0,j=0,k=0; i<8; ++i,In+=6,Out+=4)   
+	{   
+		j = (In[0]<<1) + In[5];   
+		k = (In[1]<<3) + (In[2]<<2) + (In[3]<<1) + In[4];   
+
+		for ( l=0; l<4; ++l)   
+			Out[l] = (S_Box[i][j][k]>>(3 - l)) & 1;   
+	}   
+}   
+
+/*******************************************************************  
+函 数 名 称:  F_func  
+功 能 描 述:  实现数据加密到输出P  
+参 数 说 明:  Out:    输出的32Bit[out]  
+In:     输入的48Bit[in]  
+
+返回值 说明:   void  
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+static void F_func(char In[32], const char Ki[48])   
+{   
+	char MR[48] = {0};   
+	memset(MR, 0x00, sizeof(MR));   
+
+	Transform(MR, In, E_Table, 48);   
+	Xor(MR, Ki, 48);   
+	S_func(In, MR);   
+	Transform(In, In, P_Table, 32);   
+}   
+
+/*******************************************************************  
+函 数 名 称:  SetSubKey  
+功 能 描 述:  变换(换位)8字节密钥,生成16个子密钥  
+参 数 说 明:  pSubKey:    转换生成的16个子密钥[out]  
+Key:        输入的8字节64Bit密钥[in]  
+
+返回值 说明:   void  
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+static void SetSubKey(PSubKey pSubKey, const char Key[8])   
+{   
+	int i;   
+	char K[64] = {0}, *KL=&K[0], *KR=&K[28];   
+
+	ByteToBit(K, Key, 64);   
+
+	Transform(K, K, PC1_Table, 56);   
+
+	for ( i=0; i<16; ++i)   
+	{   
+		RotateL(KL, 28, LOOP_Table[i]);   
+		RotateL(KR, 28, LOOP_Table[i]);   
+		Transform((*pSubKey)[i], K, PC2_Table, 48);   
+	}   
+}   
+
+/*******************************************************************  
+函 数 名 称:    DES  
+功 能 描 述:    处理8字节64位的数据  
+参 数 说 明:    Out:        输出的8字节[out]  
+In:         输入的8字节待加密[in]  
+pSubKey:    转换后的16个48位子密钥  
+Type:       类型:加密ENCRYPT,解密DECRYPT  
+
+返回值 说明: void  
+作       者:  huangjf  
+更 新 日 期:    2009.6.17  
+*******************************************************************/   
+static void DES(char Out[8], const char In[8], const PSubKey pSubKey, int Type)   
+{   
+	int i;   
+	char M[64] = {0}, *ML=&M[0], *MR=&M[32], szTmp[32] = {0};   
+
+	ByteToBit(M, In, 64);   
+	Transform(M, M, IP_Table, 64);   
+
+	if (Type == ENCRYPT)   
+	{   
+		for (i=0; i<16; ++i)   
+		{   
+			memcpy(szTmp, MR, 32);   
+			F_func(MR, (*pSubKey)[i]);   
+			Xor(MR, ML, 32);   
+			memcpy(ML, szTmp, 32);   
+		}   
+	}   
+	else   
+	{   
+		for (i=15; i>=0; --i)   
+		{   
+			memcpy(szTmp, MR, 32);   
+			F_func(MR, (*pSubKey)[i]);   
+			Xor(MR, ML, 32);   
+			memcpy(ML, szTmp, 32);   
+		}   
+	}   
+	RotateL(M, 64, 32);   
+	Transform(M, M, IPR_Table, 64);   
+	BitToByte(Out, M, 64);   
+}   
+
+/************************************************************************************************************************************************/   
+/************************************************************************************************************************************************/   
+
+/*******************************************************************  
+函 数 名 称:    Run1Des  
+功 能 描 述:    执行单DES算法对文本加解密  
+参 数 说 明:    bType   :类型:加密ENCRYPT,解密DECRYPT  
+bMode   :模式:ECB,CBC  
+In      :待加密串指针  
+in_len  :待加密串的长度,同时Out的缓冲区大小应大于或者等于in_len  
+Key     :密钥(可为8位,16位,24位)支持3密钥  
+key_len :密钥长度,多出24位部分将被自动裁减  
+Out     :待输出串指针  
+out_len :输出缓存大小  
+cvecstr :8字节随即字符串  
+
+作       者:  huangjf  
+更 新 日 期:    2009.6.17  
+
+返回值 说明: int     :是否加密成功,1:成功,0:失败  
+*******************************************************************/   
+int Run1Des(int bType, int bMode, const char *In, unsigned int in_len, const char *Key, unsigned int key_len, char* Out, unsigned int out_len, const char cvecstr[8])   
+{   
+	int i,j,k;   
+	char m_SubKey[16][48] = {0};   
+
+	/*参数不合法*/   
+	if (!In || !Key || !Out) return 0;   
+
+	/*密钥长度,单DES只支持8字节(64位的密钥,每个第8位作为奇偶校验位),多于8字节的自动裁剪*/   
+	if (key_len & 0x00000007) return 0;   
+
+	/*被加密数据长度,必需为8字节的倍数,如果非8的倍数,调用RunPad()函数补位*/   
+	if (in_len & 0x00000007) return 0;   
+
+	/*输出缓存大小判断*/   
+	if (out_len < in_len) return 0;   
+
+	/*生成16个子密钥*/   
+	memset(m_SubKey, 0x00, sizeof(m_SubKey));   
+	SetSubKey(&m_SubKey, Key);   
+
+	if (bMode == ECB)   
+	{   
+		/*每8字节加密*/   
+		for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+		{   
+			DES(Out, In, &m_SubKey, bType);   
+		}   
+	}   
+	else if (bMode == CBC)   
+	{   
+		if (cvecstr == NULL) return 0;   
+
+		char cvec[8] = {0};   
+		char cvin[8] = {0};   
+
+		memcpy(cvec, cvecstr, 8);   
+
+		for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+		{   
+			if (bType == ENCRYPT)   
+			{   
+				for ( k=0; k<8; ++k)   
+				{   
+					cvin[k] = In[k] ^ cvec[k];   
+				}   
+			}   
+			else   
+			{   
+				memcpy(cvin, In, 8);   
+			}   
+
+			DES(Out, cvin, &m_SubKey, bType);   
+
+			if (bType == ENCRYPT)   
+			{   
+				memcpy(cvec, Out, 8);   
+			}   
+			else   
+			{   
+				for (k=0; k<8; ++k)   
+				{   
+					Out[k] = Out[k] ^ cvec[k];   
+				}   
+				memcpy(cvec, cvin, 8);   
+			}   
+		}   
+	}   
+	else   
+	{   
+		return 0;   
+	}   
+
+	return 1;   
+}   
+
+/*******************************************************************  
+函 数 名 称:  Run3Des  
+功 能 描 述:  执行3DES算法对文本加解密  
+参 数 说 明:  bType   :类型:加密ENCRYPT,解密DECRYPT  
+bMode   :模式:ECB,CBC  
+In      :待加密串指针  
+in_len  :待加密串的长度,同时Out的缓冲区大小应大于或者等于in_len  
+Key     :密钥(可为8位,16位,24位)支持3密钥  
+key_len :密钥长度,多出24位部分将被自动裁减  
+Out     :待输出串指针  
+out_len :输出缓存大小  
+cvecstr :8字节随即字符串  
+
+返回值 说明:   int     :是否加密成功,1:成功,0:失败  
+
+作       者:    huangjf  
+更 新 日 期:  2009.6.17  
+
+3DES(加密) = DES(key1, 加密) DES(key2, 解密) DES(key3, 加密)  
+3DES(解密) = DES(key3, 解密) DES(key2, 加密) DES(key1, 解密)  
+每个KEY为64位,总共可以有192位的KEY, 但一般都只使用128位的key  
+如果只用128位密钥,则key3 = key1  
+
+*******************************************************************/   
+int Run3Des(int bType, int bMode, const char *In, unsigned int in_len, const char *Key, unsigned int key_len, char* Out, unsigned int out_len, const char cvecstr[8])   
+{   
+	int i,j,k;   
+	char m_SubKey[3][16][48] = {0};   
+	unsigned char nKey;   
+
+	/*参数不合法*/   
+	if (!In || !Key || !Out) return 0;   
+
+	/*被加密数据长度,必需为8字节的倍数,如果非8的倍数,调用RunPad()函数补位*/   
+	if (in_len & 0x00000007) return 0;   
+
+	/*密钥长度,3DES只支持8、16、24字节(192位的密钥,实际使用128位,每个第8位作为奇偶校验位),多于24字节的自动裁剪*/   
+	if (key_len & 0x00000007) return 0;   
+
+	/*输出缓存大小判断*/   
+	if (out_len < in_len) return 0;   
+
+	/*生成16个子密钥*/   
+	nKey = (key_len>>3)>3 ? 3 : (key_len>>3);   
+	memset(m_SubKey, 0x00, sizeof(m_SubKey));   
+	for ( i=0; i<nKey; i++)   
+	{   
+		SetSubKey(&m_SubKey[i], &Key[i<<3]);   
+	}   
+
+	if (bMode == ECB)   
+	{   
+		if (nKey == 1)   
+		{   
+			/*每8字节加密*/   
+			for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+			{   
+				DES(Out, In, &m_SubKey[0], bType);   
+			}   
+		}   
+		else if (nKey == 2)   
+		{   
+			for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+			{   
+				DES(Out, In,  &m_SubKey[0], bType);   
+				DES(Out, Out, &m_SubKey[1], bType==ENCRYPT?DECRYPT:ENCRYPT);   
+				DES(Out, Out, &m_SubKey[0], bType);   
+			}   
+		}   
+		else if (nKey == 3)   
+		{   
+			for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+			{   
+				DES(Out, In,  &m_SubKey[bType?2:0], bType);   
+				DES(Out, Out, &m_SubKey[1],         bType==ENCRYPT?DECRYPT:ENCRYPT);   
+				DES(Out, Out, &m_SubKey[bType?0:2], bType);   
+			}   
+		}   
+		else   
+		{   
+			/*密钥长度不对*/   
+			return 0;   
+		}   
+	}   
+	else if (bMode == CBC)   
+	{   
+		if (cvecstr == NULL) return 0;   
+
+		char cvec[8] = {0};   
+		char cvin[8] = {0};   
+
+		memcpy(cvec, cvecstr, 8);   
+
+		if (nKey == 1)   
+		{   
+			for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+			{   
+				if (bType == ENCRYPT)   
+				{   
+					for (k=0; k<8; ++k)   
+					{   
+						cvin[k] = In[k] ^ cvec[k];   
+					}   
+				}   
+				else   
+				{   
+					memcpy(cvin, In, 8);   
+				}   
+
+				DES(Out, cvin, &m_SubKey[0], bType);   
+
+				if (bType == ENCRYPT)   
+				{   
+					memcpy(cvec, Out, 8);   
+				}   
+				else   
+				{   
+					for (k=0; k<8; ++k)   
+					{   
+						Out[k] = Out[k] ^ cvec[k];   
+					}   
+					memcpy(cvec, cvin, 8);   
+				}   
+			}   
+		}   
+		else if (nKey == 2)   
+		{   
+			for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+			{   
+				if (bType == ENCRYPT)   
+				{   
+					for ( k=0; k<8; ++k)   
+					{   
+						cvin[k] = In[k] ^ cvec[k];   
+					}   
+				}   
+				else   
+				{   
+					memcpy(cvin, In, 8);   
+				}   
+
+				DES(Out, cvin, &m_SubKey[0], bType);   
+				DES(Out, Out,  &m_SubKey[1], bType==ENCRYPT?DECRYPT:ENCRYPT);   
+				DES(Out, Out,  &m_SubKey[0], bType);   
+
+				if (bType == ENCRYPT)   
+				{   
+					memcpy(cvec, Out, 8);   
+				}   
+				else   
+				{   
+					for (k=0; k<8; ++k)   
+					{   
+						Out[k] = Out[k] ^ cvec[k];   
+					}   
+					memcpy(cvec, cvin, 8);   
+				}   
+			}   
+		}   
+		else if (nKey == 3)   
+		{   
+
+			for (i=0,j=in_len>>3; i<j; ++i,Out+=8,In+=8)   
+			{   
+				if (bType == ENCRYPT)   
+				{   
+					for (k=0; k<8; ++k)   
+					{   
+						cvin[k] = In[k] ^ cvec[k];   
+					}   
+				}   
+				else   
+				{   
+					memcpy(cvin, In, 8);   
+				}   
+
+				DES(Out, cvin, &m_SubKey[bType?2:0], bType);   
+				DES(Out, Out,  &m_SubKey[1],         bType==ENCRYPT?DECRYPT:ENCRYPT);   
+				DES(Out, Out,  &m_SubKey[bType?0:2], bType);   
+
+				if (bType == ENCRYPT)   
+				{   
+					memcpy(cvec, Out, 8);   
+				}   
+				else   
+				{   
+					for (k=0; k<8; ++k)   
+					{   
+						Out[k] = Out[k] ^ cvec[k];   
+					}   
+					memcpy(cvec, cvin, 8);   
+				}   
+			}   
+		}   
+		else   
+		{   
+			/*密钥长度不对*/   
+			return 0;   
+		}   
+	}   
+	else   
+	{   
+		return 0;   
+	}   
+
+	return 1;   
+}   
+
+/*******************************************************************  
+函 数 名 称:  RunPad  
+功 能 描 述:  根据协议对加密前的数据进行填充  
+参 数 说 明:  bType   :类型:PAD类型  
+In      :数据串指针  
+Out     :填充输出串指针  
+in_len  :数据的长度  
+padlen  :(in,out)输出buffer的长度,填充后的长度  
+
+返回值 说明:   char    :是否填充成功  
+作       者:    huangjf  
+修 改 历 史:  
+
+更 新 日 期:  2009.6.17  
+*******************************************************************/   
+int RunPad(int nType,const char* In,unsigned in_len,char* Out,int* padlen)   
+{   
+	int res = (in_len & 0x00000007);   
+
+	/*  
+	if(*padlen< ((int)in_len+8-res))  
+	{  
+	return 0;  
+	}  
+	else  
+	{  
+	*padlen =   ((int)in_len+8-res);  
+	memcpy(Out,In,in_len);  
+	}  
+	*/   
+	*padlen =   ((int)in_len+8-res);   
+	memcpy(Out,In,in_len);   
+
+	if (nType   ==  PAD_ISO_1)   
+	{   
+		memset(Out+in_len,0x00,8-res);   
+	}   
+	else if (nType  ==  PAD_ISO_2)   
+	{   
+		memset(Out+in_len,0x80,1);   
+		memset(Out+in_len,0x00,7-res);   
+	}   
+	else if (nType  ==  PAD_PKCS_7)   
+	{   
+		memset(Out+in_len,8-res,8-res);   
+	}   
+	else   
+	{   
+		return 0;   
+	}   
+
+	return 1;   
+}   
+
+/*解密后,将填充的字符去掉*/   
+void RunRsm(char *Text)   
+{   
+	int len,tmpint;   
+
+	len=strlen(Text);   
+	tmpint=*(Text+len-1);   
+	*(Text+len-tmpint)=0x00;   
+}   
+
+/*将48位的明文密钥转换成24的字符串密钥*/   
+int CovertKey(char *iKey, char *oKey)   
+{   
+	char in[64],out[64];   
+	int  inlen,i,j;   
+	unsigned char p,q,t,m,n;   
+
+	memset(in,0,sizeof(in));   
+	memset(out,0,sizeof(out));   
+
+	inlen=strlen(iKey);   
+	/*检查长度合法性*/   
+	if (inlen!=48)   
+		return 0;   
+	strcpy(in,iKey);   
+	/*检查字符合法性*/   
+	for (i=0; i<inlen; i++)   
+	{   
+		if (!isxdigit(in[i]))   
+			return 0;   
+	}   
+	for (i=0,j=0; i<inlen; i+=2,j++)   
+	{   
+		p=toupper(in[i]);   
+		q=toupper(in[i+1]);   
+
+		if (isdigit(p))   
+			m=p-48;   
+		else   
+			m=p-55;   
+
+		if (isdigit(q))   
+			n=q-48;   
+		else   
+			n=q-55;   
+
+		p=(char)((m<<4)&0xf0);   
+		q=n&0x0f;   
+		t=p|q;   
+		out[j]=t;   
+	}   
+	memcpy(oKey,out,j+1);   
+
+	return 1;   
+}   
+
+char *Base64Encode(char *src,int srclen)   
+{   
+	int n,buflen,i,j;   
+	int pading=0;   
+	char *buf;   
+	static char *dst;   
+
+	buf=src;   
+	buflen=n=srclen;   
+	if (n%3!=0) /* pad with 0x00 by using a temp buffer */   
+	{   
+		pading=1;   
+		buflen=n+3-n%3;   
+		buf=(char*)malloc(buflen+1);   
+		memset(buf,0,buflen+1);   
+		memcpy(buf,src,n);   
+		for (i=0; i<3-n%3; i++)   
+			buf[n+i]=0x00;   
+	}   
+
+	dst=(char*)malloc(buflen*4/3+1);   
+	memset(dst,0,buflen*4/3+1);   
+	for (i=0,j=0; i<buflen; i+=3,j+=4)   
+	{   
+		dst[j]=(buf[i]&0xFC)>>2;   
+		dst[j+1]=((buf[i]&0x03)<<4) + ((buf[i+1]&0xF0)>>4);   
+		dst[j+2]=((buf[i+1]&0x0F)<<2) + ((buf[i+2]&0xC0)>>6);   
+		dst[j+3]=buf[i+2]&0x3F;   
+	}   
+
+	for (i=0; i<buflen*4/3; i++) /* map 6 bit value to base64 ASCII character */   
+	{   
+		dst[i]=ch64[dst[i]];   
+	}   
+	for (i=0; i<3-n%3; i++)/*补'='*/   
+		dst[j-i-1]='=';   
+
+	if (pading)   
+		free(buf);   
+	return dst;   
+}   
+
+char *Base64Decode(char *src)   
+{   
+	int m,n,i,j,len;   
+	char *p;   
+	static char *dst;   
+	char strbuf[256];   
+
+	if (src == 0 || src[0] == 0)   
+		return NULL;   
+	len = strlen(src);   
+	if (len % 4)   
+		return NULL;   
+
+	for (i = 0; i < len-2; i++)   
+		if (src[i] == '=')   
+			return NULL;   
+
+	memset(strbuf,0,sizeof(strbuf));   
+	strcpy(strbuf,src);   
+	n=strlen(src);   
+	for (i=0; i<n; i++) /* map base64 ASCII character to 6 bit value */   
+	{   
+		p=strchr(ch64,src[i]);   
+		if (!p)   
+			break;   
+		src[i]=p-ch64;   
+	}   
+	dst=(char*)malloc(n*3/4+1);   
+	memset(dst,0,n*3/4+1);   
+	for (i=0,j=0; i<n; i+=4,j+=3)   
+	{   
+		dst[j]=(src[i]<<2) + ((src[i+1]&0x30)>>4);   
+		dst[j+1]=((src[i+1]&0x0F)<<4) + ((src[i+2]&0x3C)>>2);   
+		dst[j+2]=((src[i+2]&0x03)<<6) + src[i+3];   
+	}   
+	m=strcspn(strbuf,"=");   
+	for (i=0; i<n-m; i++)   
+		dst[j-i-1]=0x00;   
+
+	return dst;   
+}   
+
+void MyDesInit(int* cryptmode,int* padmode,char* cvec)   
+{   
+	char buf[10];   
+
+	memset(buf,0,sizeof(buf));   
+	*cryptmode=CBC;   
+	*padmode=PAD_PKCS_7;   
+	buf[0]=0x01;   
+	buf[1]=0x02;   
+	buf[2]=0x03;   
+	buf[3]=0x04;   
+	buf[4]=0x05;   
+	buf[5]=0x06;   
+	buf[6]=0x07;   
+	buf[7]=0x08;   
+	memcpy(cvec,buf,8);   
+}   
+
+/*******************************************************************  
+函 数 名 称:  Crypt3Des  
+功 能 描 述:  实现3DES的加解密  
+参 数 说 明:  type    :类型:加密ENCRYPT,解密DECRYPT  
+in      :待加密串指针或者待解密的密码字符串指针  
+Out     :加密后的密码或者解密后的明文  
+Key     :密钥(48位的ASCII字符串)  
+
+返回值 说明:  
+0:成功  
+-1:非法的密钥长度  
+-2:密钥含有非16进制字符  
+-3:明文填充失败  
+-4:加解密失败  
+-5:非法的操作类型  
+
+*******************************************************************/   
+int Crypt3Des(int type,char* in,char* key,char* out)   
+{   
+
+	int cryptmode,padmode,inlen,outlength,keylen,i;   
+	char cvec[10],instr[256],keystr[256],outstr[256],tmpstr[256];   
+	char* p,*q;   
+
+	memset(cvec,0,sizeof(cvec));   
+	memset(instr,0,sizeof(instr));   
+	memset(outstr,0,sizeof(outstr));   
+	memset(keystr,0,sizeof(keystr));   
+	memset(tmpstr,0,sizeof(tmpstr));   
+
+	MyDesInit(&cryptmode,&padmode,cvec);/*设置环境变量*/   
+	inlen=strlen(in);   
+
+	if (in == 0 || in[0] == 0)   
+		return -7;   
+
+	inlen = strlen(in);   
+
+
+	if (inlen % 8)   
+		return -8;   
+
+	if (key == 0) return -9;   
+
+	keylen=strlen(key);   
+	if (keylen!=48)   
+		return -1;   
+	for (i = 0; i < keylen; i++)   
+	{   
+		if ((key[i] >= '0' && key[i] <= '9') || (key[i] >= 'a' && key[i] <= 'f') || (key[i] >= 'A' && key[i] <= 'F'))   
+			continue;   
+		else   
+			return -10;   
+	}   
+	if (inlen>256)   
+		return 0;   
+	if (!CovertKey(key,keystr))   
+		return -2;   
+
+	keylen=strlen(keystr);   
+
+	if (type==ENCRYPT)   
+	{   
+
+		if (!RunPad(padmode,in,strlen(in),instr,&inlen))   
+			return -3;   
+		if (!Run3Des(0,cryptmode,instr,inlen,keystr,(unsigned char)keylen,outstr,sizeof(outstr),cvec))   
+			return -4;   
+		outlength=strlen(outstr);   
+
+		p=Base64Encode(outstr,outlength);   
+		if (p==NULL)   
+			return -6;   
+		strcpy(out,p);   
+		free(p);   
+		return 1;   
+	}   
+	else if (type==DECRYPT)   
+	{   
+		strcpy(tmpstr,in);   
+		q=Base64Decode(tmpstr);   
+		if (q==NULL)   
+			return -6;   
+		strcpy(instr,q);   
+		inlen=strlen(q);   
+		free(q);   
+
+		if (!Run3Des(1,cryptmode,instr,inlen,keystr,(unsigned char)keylen,outstr,sizeof(outstr),cvec))   
+			return -4;   
+		RunRsm(outstr);   
+		strcpy(out,outstr);   
+	}   
+	else   
+		return -5;   
+
+	return 1;   
+}   
+
+unsigned char GetByte(char *s)   
+{   
+	int                v1;   
+	int                v2;   
+
+	if (s[0] >= '0' && s[0] <= '9')   
+		v1 = s[0] - '0';   
+	else if (s[0] >= 'a' && s[0] <= 'f')   
+		v1 = s[0] - 'a' + 10;   
+	else   
+		v1 = s[0] - 'A' + 10;   
+
+	if (s[1] >= '0' && s[1] <= '9')   
+		v2 = s[1] - '0';   
+	else if (s[1] >= 'a' && s[1] <= 'f')   
+		v2 = s[1] - 'a' + 10;   
+	else   
+		v2 = s[1] - 'A' + 10;   
+
+	return (v1*16+v2);   
+}   
+
+/************************************************************************  
+//3DES  
+char FVin[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};  
+char FVout[16] = {0};  
+char FCvec[8] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};  
+unsigned char * p;  
+size_t iLen;  
+
+//ECB加密  
+if (Run3Des(ENCRYPT, ECB, FVin, 16, Km[0], KEY_LEN_16, FVout, sizeof(FVout), NULL) == 1) {  
+RunRsm(FVout);  
+}  
+
+//DES  
+if (Run1Des(ENCRYPT, ECB, FVin, 16, Km[0], KEY_LEN_8, FVout, sizeof(FVout), NULL) == 1) {  
+RunRsm(FVout);  
+}  
+************************************************************************/  
+
+

+ 115 - 0
MD5Test/3DES.h

@@ -0,0 +1,115 @@
+#pragma once
+
+#ifndef _3DES__H_   
+#define _3DES__H_   
+
+#ifdef __cplusplus   
+extern "C"   
+{   
+#endif   
+
+#define ENCRYPT 0   
+#define DECRYPT 1   
+
+#define ECB 0   
+#define CBC 1   
+
+#define KEY_LEN_8 8   
+#define KEY_LEN_16 16   
+#define KEY_LEN_24 24   
+
+#define PAD_ISO_1   0   
+#define PAD_ISO_2   1   
+#define PAD_PKCS_7  2   
+
+	typedef char (*PSubKey)[16][48];   
+
+	/*解密后,将填充的字符去掉*/   
+	void RunRsm(char* Text);   
+
+	/*将48位的明文密钥转换成24的字符串密钥*/   
+	int CovertKey(char* iKey, char *oKey);   
+
+	/*******************************************************************  
+	函 数 名 称:  RunPad  
+	功 能 描 述:  根据协议对加密前的数据进行填充  
+	参 数 说 明:  bType   :类型:PAD类型  
+	In      :数据串指针  
+	Out     :填充输出串指针  
+	in_len  :数据的长度  
+	padlen  :(in,out)输出buffer的长度,填充后的长度  
+
+	返回值 说明:   char    :是否填充成功  
+	*******************************************************************/   
+	int RunPad(int nType,const char* In,unsigned in_len,char* Out,int* padlen);   
+
+	/*******************************************************************  
+	函 数 名 称:    Run1Des  
+	功 能 描 述:    执行单DES算法对文本加解密  
+	参 数 说 明:    bType   :类型:加密ENCRYPT,解密DECRYPT  
+	bMode   :模式:ECB,CBC  
+	In      :待加密串指针  
+	in_len  :待加密串的长度,同时Out的缓冲区大小应大于或者等于in_len  
+	Key     :密钥(可为8位,16位,24位)支持3密钥  
+	key_len :密钥长度,多出24位部分将被自动裁减  
+	Out     :待输出串指针  
+	out_len :输出缓存大小  
+	cvecstr :8字节随即字符串  
+
+	返回值 说明: int     :是否加密成功,1:成功,0:失败  
+	*******************************************************************/   
+	int Run1Des(int bType, int bMode, const char *In, unsigned int in_len, const char *Key, unsigned int key_len, char* Out, unsigned int out_len, const char cvecstr[8]);   
+
+	/*******************************************************************  
+	函 数 名 称:  Run3Des  
+	功 能 描 述:  执行3DES算法对文本加解密  
+	参 数 说 明:  bType   :类型:加密ENCRYPT,解密DECRYPT  
+	bMode   :模式:ECB,CBC  
+	In      :待加密串指针  
+	in_len  :待加密串的长度,同时Out的缓冲区大小应大于或者等于in_len  
+	Key     :密钥(可为8位,16位,24位)支持3密钥  
+	key_len :密钥长度,多出24位部分将被自动裁减  
+	Out     :待输出串指针  
+	out_len :输出缓存大小  
+	cvecstr :8字节随即字符串  
+
+	返回值 说明:   int     :是否加密成功,1:成功,0:失败  
+
+	作       者:    huangjf  
+	更 新 日 期:  2009.6.17  
+
+	3DES(加密) = DES(key1, 加密) DES(key2, 解密)  DES(key3, 加密)  
+	3DES(解密) = DES(key3, 解密) DES(key2, 加密)  DES(key1, 解密)  
+	每个KEY为64位,总共可以有192位的KEY, 但一般都只使用128位的key  
+	如果只用128位密钥,则key3 = key1  
+
+	*******************************************************************/   
+	int Run3Des(int bType, int bMode, const char *In, unsigned int in_len, const char *Key, unsigned int key_len, char* Out, unsigned int out_len, const char cvecstr[8]);   
+
+	/*******************************************************************  
+	函 数 名 称:    Crypt3Des  
+	功 能 描 述:    实现3DES的加解密  
+	参 数 说 明:    type    :类型:加密ENCRYPT,解密DECRYPT  
+	in      :待加密串指针或者待解密的密码字符串指针  
+	Out     :加密后的密码或者解密后的明文  
+	Key     :密钥(48位的ASCII字符串)  
+
+	返回值 说明:  
+	0:成功  
+	-1:非法的密钥长度  
+	-2:密钥含有非16进制字符  
+	-3:明文填充失败  
+	-4:加解密失败  
+	-5:非法的操作类型  
+	*******************************************************************/   
+	int Crypt3Des(int type,char* in,char* key,char* out);   
+
+	char *Base64Encode(char *src, int srclen);   
+	char *Base64Decode(char *src);   
+	unsigned char GetByte(char *s);   
+
+#ifdef __cplusplus   
+}   
+#endif   
+
+#endif  

+ 1132 - 0
MD5Test/AesCipher.cpp

@@ -0,0 +1,1132 @@
+#include "stdafx.h"
+#include <cstring>
+#include <cassert>
+#include "AesCipher.h"
+
+// Round Constant Array
+const AesCipher::u8_t AesCipher::sm_rcon[52] = {
+	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 
+	0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 
+	0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 
+	0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 
+	0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 
+	0x8d, 0x01, 
+};
+
+// Substitute Bytes Transformation Array, S-Box
+const AesCipher::u8_t AesCipher::sm_sbox[256] = {
+	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, 
+};
+
+// Inverse Substitute Bytes Transformation Array, Inverse S-Box
+// 逆置换表,解密时使用;
+const AesCipher::u8_t AesCipher::sm_isbox[256] = {
+	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, 
+};
+
+// Encryption Transform Array 1
+const AesCipher::u32_t AesCipher::sm_te1[256] = {
+	0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 
+	0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 
+	0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 
+	0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 
+	0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 
+	0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 
+	0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 
+	0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 
+	0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 
+	0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 
+	0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 
+	0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 
+	0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 
+	0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 
+	0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 
+	0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 
+	0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 
+	0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 
+	0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 
+	0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 
+	0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 
+	0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 
+	0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 
+	0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 
+	0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 
+	0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 
+	0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 
+	0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 
+	0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 
+	0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 
+	0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 
+	0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, 
+};
+
+// Encryption Transform Array 2
+const AesCipher::u32_t AesCipher::sm_te2[256] = {
+	0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 
+	0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 
+	0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 
+	0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 
+	0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 
+	0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 
+	0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 
+	0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 
+	0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 
+	0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 
+	0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 
+	0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 
+	0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 
+	0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 
+	0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 
+	0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 
+	0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 
+	0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 
+	0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 
+	0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 
+	0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 
+	0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 
+	0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 
+	0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 
+	0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 
+	0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 
+	0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 
+	0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 
+	0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 
+	0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 
+	0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 
+	0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, 
+};
+
+// Encryption Transform Array 3
+const AesCipher::u32_t AesCipher::sm_te3[256] = {
+	0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 
+	0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 
+	0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 
+	0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 
+	0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 
+	0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 
+	0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 
+	0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 
+	0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 
+	0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 
+	0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 
+	0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 
+	0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 
+	0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 
+	0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 
+	0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 
+	0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 
+	0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 
+	0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 
+	0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 
+	0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 
+	0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 
+	0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 
+	0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 
+	0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 
+	0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 
+	0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 
+	0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 
+	0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 
+	0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 
+	0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 
+	0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, 
+};
+
+// Encryption Transform Array 4
+const AesCipher::u32_t AesCipher::sm_te4[256] = {
+	0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 
+	0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 
+	0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 
+	0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 
+	0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 
+	0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 
+	0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 
+	0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 
+	0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 
+	0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 
+	0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 
+	0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 
+	0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 
+	0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 
+	0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 
+	0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 
+	0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 
+	0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 
+	0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 
+	0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 
+	0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 
+	0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 
+	0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 
+	0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 
+	0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 
+	0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 
+	0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 
+	0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 
+	0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 
+	0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 
+	0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 
+	0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, 
+};
+
+// Decryption Transform Array 1
+const AesCipher::u32_t AesCipher::sm_td1[256] = {
+	0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 
+	0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 
+	0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 
+	0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 
+	0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 
+	0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 
+	0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 
+	0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 
+	0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 
+	0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 
+	0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 
+	0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 
+	0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 
+	0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 
+	0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 
+	0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 
+	0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 
+	0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 
+	0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 
+	0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 
+	0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 
+	0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 
+	0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 
+	0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 
+	0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 
+	0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 
+	0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 
+	0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 
+	0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 
+	0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 
+	0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 
+	0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, 
+};
+
+// Decryption Transform Array 2
+const AesCipher::u32_t AesCipher::sm_td2[256] = {
+	0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 
+	0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 
+	0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 
+	0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 
+	0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 
+	0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 
+	0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 
+	0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 
+	0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 
+	0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 
+	0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 
+	0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 
+	0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 
+	0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 
+	0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 
+	0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 
+	0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 
+	0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 
+	0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 
+	0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 
+	0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 
+	0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 
+	0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 
+	0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 
+	0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 
+	0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 
+	0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 
+	0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 
+	0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 
+	0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 
+	0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 
+	0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, 
+};
+
+// Decryption Transform Array 3
+const AesCipher::u32_t AesCipher::sm_td3[256] = {
+	0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 
+	0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 
+	0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 
+	0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 
+	0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 
+	0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 
+	0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 
+	0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 
+	0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 
+	0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 
+	0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 
+	0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 
+	0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 
+	0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 
+	0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 
+	0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 
+	0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 
+	0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 
+	0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 
+	0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 
+	0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 
+	0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 
+	0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 
+	0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 
+	0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 
+	0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 
+	0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 
+	0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 
+	0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 
+	0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 
+	0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 
+	0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, 
+};
+
+// Decryption Transform Array 4
+const AesCipher::u32_t AesCipher::sm_td4[256] = {
+	0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 
+	0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 
+	0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 
+	0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 
+	0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 
+	0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 
+	0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 
+	0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 
+	0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 
+	0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 
+	0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 
+	0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 
+	0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 
+	0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 
+	0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 
+	0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 
+	0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 
+	0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 
+	0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 
+	0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 
+	0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 
+	0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 
+	0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 
+	0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 
+	0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 
+	0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 
+	0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 
+	0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 
+	0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 
+	0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 
+	0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 
+	0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0, 
+};
+
+#ifdef __AES_IMC_SPEEDUP__
+
+// Inverse MixColumns Transformation Array 1
+const AesCipher::u32_t AesCipher::sm_imc1[256] = {
+	0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 
+	0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 
+	0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 
+	0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 
+	0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 
+	0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 
+	0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 
+	0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 
+	0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 
+	0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 
+	0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 
+	0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 
+	0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 
+	0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 
+	0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 
+	0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 
+	0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 
+	0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 
+	0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 
+	0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 
+	0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 
+	0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 
+	0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 
+	0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 
+	0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 
+	0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 
+	0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 
+	0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 
+	0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 
+	0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 
+	0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 
+	0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3, 
+};
+
+// Inverse MixColumns Transformation Array 2
+const AesCipher::u32_t AesCipher::sm_imc2[256] = {
+	0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 
+	0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 
+	0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 
+	0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 
+	0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 
+	0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 
+	0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 
+	0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 
+	0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 
+	0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 
+	0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 
+	0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 
+	0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 
+	0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 
+	0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 
+	0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 
+	0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 
+	0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 
+	0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 
+	0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 
+	0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 
+	0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 
+	0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 
+	0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 
+	0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 
+	0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 
+	0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 
+	0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 
+	0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 
+	0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 
+	0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 
+	0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697, 
+};
+
+// Inverse MixColumns Transformation Array 3
+const AesCipher::u32_t AesCipher::sm_imc3[256] = {
+	0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 
+	0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 
+	0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 
+	0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 
+	0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 
+	0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 
+	0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 
+	0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 
+	0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 
+	0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 
+	0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 
+	0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 
+	0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 
+	0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 
+	0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 
+	0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 
+	0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 
+	0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 
+	0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 
+	0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 
+	0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 
+	0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 
+	0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 
+	0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 
+	0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 
+	0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 
+	0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 
+	0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 
+	0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 
+	0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 
+	0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 
+	0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46, 
+};
+
+// Inverse MixColumns Transformation Array 4
+const AesCipher::u32_t AesCipher::sm_imc4[256] = {
+	0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 
+	0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 
+	0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 
+	0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 
+	0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 
+	0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 
+	0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 
+	0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 
+	0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 
+	0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 
+	0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 
+	0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 
+	0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 
+	0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 
+	0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 
+	0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 
+	0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 
+	0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 
+	0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 
+	0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 
+	0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 
+	0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 
+	0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 
+	0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 
+	0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 
+	0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 
+	0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 
+	0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 
+	0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 
+	0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 
+	0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 
+	0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d, 
+};
+
+#else  // #ifdef __AES_IMC_SPEEDUP__
+
+/************************************************************************/
+/*  函数:[6/3/2016 IT];
+/*  描述:有限域GF(2^8,2的8次幂)上的乘法,标准算法应该是循环8次(b与a的每一位相乘,结果相加);
+/*  参数:;
+/*  	[IN] a:要运算的a参数;
+/*  	[IN] b:要运算的b参数;
+/*  返回:返回a,b的运算结果;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+unsigned char AesCipher::mul(unsigned char a, unsigned char b)
+{
+	unsigned char ret = 0;
+
+	for (int i = 0; i < 8; ++i) {
+		if (b & 0x01)
+			ret ^= a;
+		if (a & 0x80) {
+			a <<= 1;
+			a ^= 0x1B;
+		} else
+			a <<= 1;
+		b >>= 1;
+	}
+
+	return ret;
+}
+
+/************************************************************************/
+/*  函数:invMixColumn[6/3/2016 IT];
+/*  描述:逆列混淆转换;
+/*  参数:;
+/*  	[IN] w:要逆转换的机器字节(int32);
+/*  返回:返回由逆列混淆转换生成的机器字节;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+AesCipher::u32_t AesCipher::invMixColumn(u32_t w)
+{
+	unsigned char byte0 = (w >> 24) & 0xFF;
+	unsigned char byte1 = (w >> 16) & 0xFF;
+	unsigned char byte2 = (w >> 8) & 0xFF;
+	unsigned char byte3 = w & 0xFF;
+	unsigned char b0 = mul(byte0, 0x0E) ^ mul(byte1, 0x0B) ^ mul(byte2, 0x0D) ^ mul(byte3, 0x09);
+	unsigned char b1 = mul(byte0, 0x09) ^ mul(byte1, 0x0E) ^ mul(byte2, 0x0B) ^ mul(byte3, 0x0D);
+	unsigned char b2 = mul(byte0, 0x0D) ^ mul(byte1, 0x09) ^ mul(byte2, 0x0E) ^ mul(byte3, 0x0B);
+	unsigned char b3 = mul(byte0, 0x0B) ^ mul(byte1, 0x0D) ^ mul(byte2, 0x09) ^ mul(byte3, 0x0E);
+	return (u32_t(b0) << 24) | (u32_t(b1) << 16) | (u32_t(b2) << 8) | u32_t(b3);
+}
+
+#endif // #ifdef __AES_IMC_SPEEDUP__
+
+/************************************************************************/
+/*  函数:makeRoundKey[6/3/2016 IT];
+/*  描述:将用户输入的密钥扩展成轮密钥(轮计算时用到的密钥);
+/*  参数:;
+/*  	[IN] key:用户输入的密钥;
+/*  	[IN] keyLength:用户输入的密钥长度,只能是16字节、24字节、32字节长度;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void AesCipher::makeRoundKey(IN const char *key, IN int keyLength /* = DEFAULT_KEY_LENGTH */)
+{
+	assert(key != 0);
+	assert(keyLength == 16 || keyLength == 24 || keyLength == 32);
+
+	if (key == 0)  // null pointer
+		return ;
+	if (keyLength != 16 && keyLength != 24 && keyLength != 32)
+		return ;
+
+	m_keyLength = keyLength;
+	m_bKey = true;
+
+	// Calculate number of rounds
+	if (m_keyLength == 16)
+		m_rounds = 10;
+	else if (m_keyLength == 24)
+		m_rounds = 12;
+	else // m_keyLength == 32
+		m_rounds = 14;
+
+	int i, j;
+	int totalWords = (m_rounds + 1) * BWC;  // round key's total number of words
+	int kwc = m_keyLength / 4;              // key's number of word
+
+	// Copy user key into temporary ints
+	u32_t tk[MAX_KWC];
+	for ( i = 0, j = 0; i < kwc; ++i) {
+		tk[i] = (u32_t)(unsigned char)key[j++] << 24;
+		tk[i] |= (u32_t)(unsigned char)key[j++] << 16;
+		tk[i] |= (u32_t)(unsigned char)key[j++] << 8;
+		tk[i] |= (u32_t)(unsigned char)key[j++];
+	}
+
+	// Copy values into round key arrays
+	int k = 0;
+	for (i = 0; i < kwc; ++i, ++k) {
+		m_ke[k / BWC][k % BWC] = tk[i];
+		m_kd[m_rounds - k / BWC][k % BWC] = tk[i];
+	}
+
+	int rconIndex = 0;
+	while (k < totalWords) {
+		u32_t tmp = tk[kwc - 1];
+		// tk[0] ^= SubWord(RotWord(tmp)) ^ rcon[ i / kwc]
+		// first loop shift-left one byte, then substitute bytes using S-Box, then xor with Rcon
+		tk[0] ^= (u32_t(sm_sbox[(tmp >> 16) & 0xFF]) << 24 | u32_t(sm_sbox[(tmp >> 8) & 0xFF]) << 16 |
+			u32_t(sm_sbox[tmp & 0xFF]) << 8 | u32_t(sm_sbox[tmp >> 24])
+			) ^ (u32_t(sm_rcon[rconIndex++]) << 24);
+
+		if (kwc != MAX_KWC) {
+			for (i = 1; i < kwc; ++i)
+				tk[i] ^= tk[i - 1];
+		} else {
+			for (i = 1; i < kwc / 2; ++i)
+				tk[i] ^= tk[i - 1];
+			tmp = tk[kwc / 2 - 1];
+			// substitute bytes using S-Box
+			tk[kwc / 2] ^= u32_t(sm_sbox[tmp & 0xFF]) | u32_t(sm_sbox[(tmp >> 8) & 0xFF]) << 8 |
+				u32_t(sm_sbox[(tmp >> 16) & 0xFF]) << 16 | u32_t(sm_sbox[tmp >> 24]) << 24;
+			for (i = kwc / 2 + 1; i < kwc; ++i)
+				tk[i] ^= tk[i - 1];
+		}
+		// Copy values into round key arrays
+		for (i = 0; (i < kwc) && (k < totalWords); ++i, ++k) {
+			m_ke[k / BWC][k % BWC] = tk[i];
+			m_kd[m_rounds - k / BWC][k % BWC] = tk[i];
+		}
+	}
+
+	// Inverse MixColumns Transformation
+	for (i = 1; i < m_rounds; ++i) {
+		for (j = 0; j < BWC; ++j) {
+#ifdef __AES_IMC_SPEEDUP__
+			u32_t tmp = m_kd[i][j];
+			m_kd[i][j] = sm_imc1[tmp >> 24] ^
+				sm_imc2[(tmp >> 16) & 0xFF] ^
+				sm_imc3[(tmp >>  8) & 0xFF] ^
+				sm_imc4[tmp & 0xFF];
+#else 
+			m_kd[i][j] = invMixColumn(m_kd[i][j]);
+#endif
+		}
+	}
+}
+
+/************************************************************************/
+/*  函数:encryptBlock[6/3/2016 IT];
+/*  描述:加密一个块大小的明文,这个块假定是AES的块大小(128bits);
+/*  参数:;
+/*  	[IN] in:要加密的明文(这个明文必须是一个块的大小);
+/*  	[OUT] result:输出明文加密后的密文;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void AesCipher::encryptBlock(IN const char *in, OUT char *result)
+{
+	// first, convert chars into words (32bit per word)
+	u32_t w1 = (u32_t)(unsigned char)*(in++) << 24;
+	w1 |= (u32_t)(unsigned char)*(in++) << 16;
+	w1 |= (u32_t)(unsigned char)*(in++) << 8;
+	w1 |= (u32_t)(unsigned char)*(in++);
+
+	u32_t w2 = (u32_t)(unsigned char)*(in++) << 24;
+	w2 |= (u32_t)(unsigned char)*(in++) << 16;
+	w2 |= (u32_t)(unsigned char)*(in++) << 8;
+	w2 |= (u32_t)(unsigned char)*(in++);
+
+	u32_t w3 = (u32_t)(unsigned char)*(in++) << 24;
+	w3 |= (u32_t)(unsigned char)*(in++) << 16;
+	w3 |= (u32_t)(unsigned char)*(in++) << 8;
+	w3 |= (u32_t)(unsigned char)*(in++);
+
+	u32_t w4 = (u32_t)(unsigned char)*(in++) << 24;
+	w4 |= (u32_t)(unsigned char)*(in++) << 16;
+	w4 |= (u32_t)(unsigned char)*(in++) << 8;
+	w4 |= (u32_t)(unsigned char)*(in++);
+
+	// AddRoundKey transformation for plaintext
+	w1 ^= m_ke[0][0];
+	w2 ^= m_ke[0][1];
+	w3 ^= m_ke[0][2];
+	w4 ^= m_ke[0][3];
+
+	// round transforms
+	for (int i = 1; i < m_rounds; ++i) {
+		u32_t t1, t2, t3, t4;
+
+		// substitute byte, ShiftRows, MixColumns and AddRoundKey transformation
+		// sm_te transformation includes substitute byte and MixColumns transformation
+		t1 = (sm_te1[w1 >> 24] ^ sm_te2[(w2 >> 16) & 0xFF] ^
+			sm_te3[(w3 >> 8) & 0xFF] ^ sm_te4[w4 & 0xFF]
+		) ^ m_ke[i][0];
+		t2 = (sm_te1[w2 >> 24] ^ sm_te2[(w3 >> 16) & 0xFF] ^
+			sm_te3[(w4 >> 8) & 0xFF] ^ sm_te4[w1 & 0xFF]
+		) ^ m_ke[i][1];
+		t3 = (sm_te1[w3 >> 24] ^ sm_te2[(w4 >> 16) & 0xFF] ^
+			sm_te3[(w1 >> 8) & 0xFF] ^ sm_te4[w2 & 0xFF]
+		) ^ m_ke[i][2];
+		t4 = (sm_te1[w4 >> 24] ^ sm_te2[(w1 >> 16) & 0xFF] ^
+			sm_te3[(w2 >> 8) & 0xFF] ^ sm_te4[w3 & 0xFF]
+		) ^ m_ke[i][3];
+
+		w1 = t1;
+		w2 = t2;
+		w3 = t3;
+		w4 = t4;
+	}
+
+	// last round is special
+	int tmp = m_ke[m_rounds][0];
+	// Substitute Bytes, ShiftRows and AddRoundKey transformation
+	result[0] = sm_sbox[w1 >> 24] ^ (tmp >> 24);
+	result[1] = sm_sbox[(w2 >> 16) & 0xFF] ^ (tmp >> 16);
+	result[2] = sm_sbox[(w3 >>  8) & 0xFF] ^ (tmp >>  8);
+	result[3] = sm_sbox[w4 & 0xFF] ^ tmp;
+
+	tmp = m_ke[m_rounds][1];
+	result[4] = sm_sbox[w2 >> 24] ^ (tmp >> 24);
+	result[5] = sm_sbox[(w3 >> 16) & 0xFF] ^ (tmp >> 16);
+	result[6] = sm_sbox[(w4 >>  8) & 0xFF] ^ (tmp >>  8);
+	result[7] = sm_sbox[w1 & 0xFF] ^ tmp;
+
+	tmp = m_ke[m_rounds][2];
+	result[8] = sm_sbox[w3 >> 24] ^ (tmp >> 24);
+	result[9] = sm_sbox[(w4 >> 16) & 0xFF] ^ (tmp >> 16);
+	result[10] = sm_sbox[(w1 >> 8) & 0xFF] ^ (tmp >>  8);
+	result[11] = sm_sbox[w2 & 0xFF] ^ tmp;
+
+	tmp = m_ke[m_rounds][3];
+	result[12] = sm_sbox[w4 >> 24] ^ (tmp >> 24);
+	result[13] = sm_sbox[(w1 >> 16) & 0xFF] ^ (tmp >> 16);
+	result[14] = sm_sbox[(w2 >>  8) & 0xFF] ^ (tmp >>  8);
+	result[15] = sm_sbox[w3 & 0xFF] ^ tmp;
+}
+
+/************************************************************************/
+/*  函数:decryptBlock[6/3/2016 IT];
+/*  描述:解密一个块大小的密文,这个块假定是AES的块大小(128bits);
+/*  参数:;
+/*  	[IN] in:要解密的密文(这个密文大小必须是一个块的大小);
+/*  	[OUT] result:输出使用密钥解密后的明文;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void AesCipher::decryptBlock(IN const char *in, OUT char *result)
+{
+	// first, convert chars into words (32bit per word)
+	u32_t w1 = (u32_t)(unsigned char)*(in++) << 24;
+	w1 |= (u32_t)(unsigned char)*(in++) << 16;
+	w1 |= (u32_t)(unsigned char)*(in++) << 8;
+	w1 |= (u32_t)(unsigned char)*(in++);
+
+	u32_t w2 = (u32_t)(unsigned char)*(in++) << 24;
+	w2 |= (u32_t)(unsigned char)*(in++) << 16;
+	w2 |= (u32_t)(unsigned char)*(in++) << 8;
+	w2 |= (u32_t)(unsigned char)*(in++);
+
+	u32_t w3 = (u32_t)(unsigned char)*(in++) << 24;
+	w3 |= (u32_t)(unsigned char)*(in++) << 16;
+	w3 |= (u32_t)(unsigned char)*(in++) << 8;
+	w3 |= (u32_t)(unsigned char)*(in++);
+
+	u32_t w4 = (u32_t)(unsigned char)*(in++) << 24;
+	w4 |= (u32_t)(unsigned char)*(in++) << 16;
+	w4 |= (u32_t)(unsigned char)*(in++) << 8;
+	w4 |= (u32_t)(unsigned char)*(in++);
+
+	// AddRoundKey transformation for plaintext
+	w1 ^= m_kd[0][0];
+	w2 ^= m_kd[0][1];
+	w3 ^= m_kd[0][2];
+	w4 ^= m_kd[0][3];
+
+	// round transforms
+	for (int i = 1; i < m_rounds; ++i) {
+		u32_t t1, t2, t3, t4;
+
+		// substitute byte, ShiftRows, MixColumns and AddRoundKey transformation
+		// sm_te transformation includes substitute byte and MixColumns transformation
+		t1 = (sm_td1[w1 >> 24] ^ sm_td2[(w4 >> 16) & 0xFF] ^
+			sm_td3[(w3 >>  8) & 0xFF] ^ sm_td4[w2 & 0xFF]
+		) ^ m_kd[i][0];
+		t2 = (sm_td1[w2 >> 24] ^ sm_td2[(w1 >> 16) & 0xFF] ^
+			sm_td3[(w4 >>  8) & 0xFF] ^ sm_td4[w3 & 0xFF]
+		) ^ m_kd[i][1];
+		t3 = (sm_td1[w3 >> 24] ^ sm_td2[(w2 >> 16) & 0xFF] ^
+			sm_td3[(w1 >>  8) & 0xFF] ^ sm_td4[w4 & 0xFF]
+		) ^ m_kd[i][2];
+		t4 = (sm_td1[w4 >> 24] ^ sm_td2[(w3 >> 16) & 0xFF] ^
+			sm_td3[(w2 >>  8) & 0xFF] ^ sm_td4[w1 & 0xFF]
+		) ^ m_kd[i][3];
+
+		w1 = t1;
+		w2 = t2;
+		w3 = t3;
+		w4 = t4;
+	}
+
+	// last round is special
+	u32_t tmp = m_kd[m_rounds][0];
+	// substitute byte, ShiftRows and AddRoundKey transformation
+	result[0] = sm_isbox[w1 >> 24] ^ (tmp >> 24 & 0xFF);
+	result[1] = sm_isbox[(w4 >> 16) & 0xFF] ^ (tmp >> 16 & 0xFF);
+	result[2] = sm_isbox[(w3 >>  8) & 0xFF] ^ (tmp >>  8 & 0xFF);
+	result[3] = sm_isbox[w2 & 0xFF] ^ tmp & 0xFF;
+
+	tmp = m_kd[m_rounds][1];
+	result[4] = sm_isbox[w2 >> 24] ^ (tmp >> 24 & 0xFF);
+	result[5] = sm_isbox[(w1 >> 16) & 0xFF] ^ (tmp >> 16 & 0xFF);
+	result[6] = sm_isbox[(w4 >>  8) & 0xFF] ^ (tmp >>  8 & 0xFF);
+	result[7] = sm_isbox[w3 & 0xFF] ^ tmp & 0xFF;
+
+	tmp = m_kd[m_rounds][2];
+	result[8] = sm_isbox[w3 >> 24] ^ (tmp >> 24 & 0xFF);
+	result[9] = sm_isbox[(w2 >> 16) & 0xFF] ^ (tmp >> 16 & 0xFF);
+	result[10] = sm_isbox[(w1 >> 8) & 0xFF] ^ (tmp >>  8 & 0xFF);
+	result[11] = sm_isbox[w4 & 0xFF] ^ tmp & 0xFF;
+
+	tmp = m_kd[m_rounds][3];
+	result[12] = sm_isbox[w4 >> 24] ^ (tmp >> 24 & 0xFF);
+	result[13] = sm_isbox[(w3 >> 16) & 0xFF] ^ (tmp >> 16 & 0xFF);
+	result[14] = sm_isbox[(w2 >>  8) & 0xFF] ^ (tmp >>  8 & 0xFF);
+	result[15] = sm_isbox[w1 & 0xFF] ^ (tmp & 0xFF);
+}
+
+/************************************************************************/
+/*  函数:incrCounter[6/3/2016 IT];
+/*  描述:计数器增加(Increase)1;
+/*  参数:;
+/*  	[IN] counter:CTR的计数器,块运算时使用的块大小假定为AES的块大小(128bits);
+/*  返回:如果溢出,返回false,否则返回true;
+/*  注意:低地址字节对应计数器的低位;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool AesCipher::incrCounter(char *counter)
+{
+	unsigned char *bytes = reinterpret_cast<unsigned char*>(counter);
+	int i;
+	for (i = 0; i < BLOCK_SIZE && bytes[i] == UCHAR_MAX; ++i)
+		bytes[i] = 0;  // carry
+	if (i < BLOCK_SIZE) {
+		bytes[i]++;
+		return true;
+	} else // overflow
+		return false;
+}
+
+/************************************************************************/
+/*  函数:encrypt[6/3/2016 IT];
+/*  描述:加密多个明文块;
+/*  参数:;
+/*  	[IN] in:要加密的明文(明文必须是块的整数倍);
+/*  	[OUT] result:输出明文加密后的密文;
+/*  	[IN] num:要加密的明文长度,必须是块大小的整数倍;
+/*  	[IN] mode:加密的工作模式,默认CBC;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void AesCipher::encrypt(IN const char *in, OUT char *result, IN size_t num, IN int mode /* = CBC */)
+{
+	assert(in != 0 && result != 0 && m_bKey);
+	assert(num > 0 && num % BLOCK_SIZE == 0);
+
+	// in and result arenot null pointers and round key was made
+	if (in == 0 || result == 0 || !m_bKey)
+		return ;
+	//n should be > 0 and multiple of BLOCK_SIZE
+	if (num == 0 || num % BLOCK_SIZE != 0)
+		return ;
+
+	// chain working mode
+	if (mode == CBC || mode == CFB || mode == OFB) {
+		assert(m_bIv);
+		if (!m_bIv)
+			return ;
+	}
+
+	char iv[BLOCK_SIZE];
+	memcpy(iv, m_iv, BLOCK_SIZE);
+	char counter[BLOCK_SIZE];
+	memcpy(counter, m_counter, BLOCK_SIZE);
+	size_t n;
+	char tmpBuf[BLOCK_SIZE];
+	switch (mode)
+	{
+	case ECB:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			encryptBlock(in, result);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;
+		}
+
+		break;
+
+	case CBC:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			xorBlock(iv, in);
+			encryptBlock(iv, result);
+			memcpy(iv, result, BLOCK_SIZE);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;
+		}
+
+		break;
+
+	case CFB:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			memcpy(tmpBuf, in, BLOCK_SIZE);   // processing the case when in == result
+			encryptBlock(iv, result);
+			xorBlock(result, tmpBuf);
+			memcpy(iv, result, BLOCK_SIZE);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;
+		}
+
+		break;
+
+	case OFB:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			memcpy(tmpBuf, in, BLOCK_SIZE);   // processing the case when in == result
+			encryptBlock(iv, result);
+			memcpy(iv, result, BLOCK_SIZE);
+			xorBlock(result, tmpBuf);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;
+		}
+
+		break;
+
+	case CTR:
+		assert(m_bCounter);
+		if (!m_bCounter)
+			return;
+		for (n = num / BLOCK_SIZE; n > 0; --n) {
+			memcpy(tmpBuf, in, BLOCK_SIZE);   // processing the case when in == result
+			encryptBlock(counter, result);
+			xorBlock(result, tmpBuf);
+			incrCounter(counter);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;   
+		}
+
+		break;
+	}
+}
+
+/************************************************************************/
+/*  函数:decrypt[6/3/2016 IT];
+/*  描述:解密多个密文块;
+/*  参数:;
+/*  	[IN] in:要解密的密文(密文必须是块大小的整数倍);
+/*  	[OUT] result:输出解密后的明文;
+/*  	[IN] num:要解密的密文大小,密文大小必须是块的整数倍;
+/*  	[IN] mode:解密使用的工作模式,默认使用CBC;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void AesCipher::decrypt(IN const char *in, OUT char *result, IN size_t num, IN int mode /* = CBC */)
+{
+	assert(in != 0 && result != 0 && m_bKey);
+	assert(num > 0 && num % BLOCK_SIZE == 0);
+
+	// in and result arenot null pointers and round key was made
+	if (in == 0 || result == 0 || !m_bKey)
+		return ;
+	//n should be > 0 and multiple of BLOCK_SIZE
+	if (num == 0 || num % BLOCK_SIZE != 0)
+		return ;
+
+	// chain working mode
+	if (mode == CBC || mode == CFB || mode == OFB) {
+		assert(m_bIv);
+		if (!m_bIv)
+			return ;
+	}
+
+	char iv[BLOCK_SIZE];
+	memcpy(iv, m_iv, BLOCK_SIZE);
+	char counter[BLOCK_SIZE];
+	size_t n;
+	char tmpBuf[BLOCK_SIZE];
+	switch (mode)
+	{
+	case ECB:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			decryptBlock(in, result);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;
+		}
+
+		break;
+
+	case CBC:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			memcpy(tmpBuf, in, BLOCK_SIZE);   // processing the case when in == result
+			decryptBlock(in, result);
+			xorBlock(result, iv);
+			memcpy(iv, tmpBuf, BLOCK_SIZE);               
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;
+		}
+
+		break;
+
+	case CFB:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			memcpy(tmpBuf, in, BLOCK_SIZE);   // processing the case when in == result
+			encryptBlock(iv, result);  // encryption function!
+			xorBlock(result, tmpBuf);
+			memcpy(iv, tmpBuf, BLOCK_SIZE);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;
+		}
+
+		break;
+
+	case OFB:
+		for (n = num / BLOCK_SIZE; n > 0; --n)  {
+			memcpy(tmpBuf, in, BLOCK_SIZE);   // processing the case when in == result
+			encryptBlock(iv, result);   // encryption function!
+			memcpy(iv, result, BLOCK_SIZE);
+			xorBlock(result, tmpBuf);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;            
+		}
+
+		break;
+
+	case CTR:
+		assert(m_bCounter);
+		if (!m_bCounter)
+			return;
+		memcpy(counter, m_counter, BLOCK_SIZE);
+		for (n = num / BLOCK_SIZE; n > 0; --n) {
+			memcpy(tmpBuf, in, BLOCK_SIZE);   // processing the case when in == result
+			encryptBlock(counter, result);  // encryption function!
+			xorBlock(result, tmpBuf);
+			incrCounter(counter);
+			in += BLOCK_SIZE;
+			result += BLOCK_SIZE;   
+		}
+
+		break;
+	}
+}
+
+/************************************************************************/
+/*  函数:[6/3/2016 IT];
+/*  描述:加密任意长度的明文;
+/*  参数:;
+/*  	[IN] in:要加密的明文;
+/*  	[OUT] result:输出加密后的密文;
+/*  	[IN] num:要加密的明文长度,任意字节数;
+/*  	[IN] mode:加密模式,默认为CBC;
+/*  返回:void;
+/*  注意:如果需要,空字节将附加到明文中,以使明文长度符合块整数倍大小;
+/*		  加密前,应该先调用calculateCipherLen来获取密文长度;
+/*		  如果密文堆创建失败将抛出运行时异常.
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void AesCipher::encryptString(IN const char *in, OUT char *result, IN size_t num, IN int mode /* = CBC */)
+{
+	size_t len = calculateCipherLen(num);
+	char *buf = new char[len];
+	if (buf == 0) 
+		throw std::runtime_error("Allocating memory failed.");       
+	// filling with zero
+	memset(buf, 0, len);
+	memcpy(buf, in, num);
+	// The last block holds valid number of bytes in last plaintext block.
+	buf[len - BLOCK_SIZE] = num % BLOCK_SIZE ? num % BLOCK_SIZE : BLOCK_SIZE;        
+	encrypt(buf, result, len, mode);
+
+	delete [] buf;
+}
+
+/************************************************************************/
+/*  函数:decryptString[6/3/2016 IT];
+/*  描述:解密密文;
+/*  参数:;
+/*  	[IN] in:要解密的密文;
+/*  	[OUT] result:输出解密后的明文;
+/*  	[IN] num:要解密的密文长度,必须是块大小的整数倍;
+/*  	[IN] mode:解密模式,默认为CBC;
+/*  返回:返回解密后的明文字节数;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int AesCipher::decryptString(IN const char *in, OUT char *result, IN size_t num, IN int mode /* = CBC */)
+{
+	decrypt(in, result, num, mode);
+	return num - 2 * BLOCK_SIZE + result[num - BLOCK_SIZE];
+}

+ 165 - 0
MD5Test/AesCipher.h

@@ -0,0 +1,165 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:AES算法加解密工具类;
+/*  描    述:AES又称Rijndael,是高级加密标准的数据加密解密算法;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[6/3/2016];
+/*
+/*
+/*  注    意:使用宏__AES_IMC_SPEEDUP__能加快生成轮密钥(AesCipher::makeRoundKey),但意味着更多4K内存被使用。
+/*			  默认情况下,禁用此加速,如果确实使用加速,开启宏定义即可;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __AES_CIPHER_H__
+#define __AES_CIPHER_H__
+
+#include <cstring>
+#include <climits>
+#include <stdexcept>
+
+//#define __AES_IMC_SPEEDUP__	// 加密生成轮密钥的宏;
+
+class AesCipher
+{
+public: 
+	// AES的工作模式(同样是其他分组(块)加密算法的工作模式)
+	// ECB:电子密码本模式(Electronic Codebook mode);
+	// CBC:密码块链接模式(Cipher Block Chaining mode);
+	// CFB:密码反馈模式(Cipher Feedback mode);
+	// OFB:输出反馈模式(Output Feedback mode);
+	// CTR:计数器模式(Counter mode);
+	enum { ECB = 0, CBC = 1, CFB = 2, OFB = 3, CTR = 4 };
+	enum { DEFAULT_KEY_LENGTH = 16 };      // 默认密钥长度16字节;
+	enum { BLOCK_SIZE = 16 };              // 分组(块)大小;
+
+public:
+	AesCipher() : m_bKey(false), m_bIv(false), m_bCounter(false) { }
+
+	// 将用户输入的密钥扩展成轮密钥(轮计算时用到的密钥);
+	void makeRoundKey(IN const char *key, IN int keyLength = DEFAULT_KEY_LENGTH);
+
+	// 为链工作模式(CBC,CFB和OFB)设置初始向量(IV);
+	void setIV(const char *iv) {
+		if (iv != 0) {
+			m_bIv = true;
+			memcpy(m_iv, iv, BLOCK_SIZE);
+		} else
+			m_bIv = false;
+	}
+
+	// 为CTR工作模式设置初始计数器;
+	// 参数:counter,为CTR(只适应128bits或16Bytes)而设置的初始计数器;
+	// 注意:低地址字节对应计数器的低位;
+	void setCounter(const char *counter) {
+		if (counter != 0) {
+			m_bCounter = true;
+			memcpy(m_counter, counter, BLOCK_SIZE);
+		} else
+			m_bCounter = false;
+	}
+
+	// 加密多个明文块;
+	void encrypt(IN const char *in, OUT char *result, IN size_t num, IN int mode = CBC);
+	// 解密多个密文块;
+	void decrypt(IN const char *in, OUT char *result, IN size_t num, IN int mode = CBC);
+	// 用明文长度获取对应的密文长度(返回密文字节数);
+	static int calculateCipherLen(size_t plaintextlen) {
+		return (plaintextlen / BLOCK_SIZE + (plaintextlen % BLOCK_SIZE ? 1 : 0) + 1) * 16;
+	}
+
+	// 加密任意长度的明文;
+	void encryptString(IN const char *in, OUT char *result, IN size_t num, IN int mode = CBC);
+
+	// 解密密文;
+	int decryptString(IN const char *in, OUT char *result, IN size_t num, IN int mode = CBC);
+	
+	// 获取密钥长度;
+	int getKeyLength() {
+		if (!m_bKey)
+			return 0;
+		return m_keyLength;
+	}
+
+	// 获取轮次数;
+	int getRounds() {
+		if (!m_bKey)
+			return 0;
+		return m_rounds;
+	}
+
+	// private types and functions
+private:
+	typedef unsigned __int32 u32_t;
+	typedef unsigned char    u8_t;
+
+	// 加密一个块大小的明文,这个块假定是AES的块大小(128bits);
+	void encryptBlock(IN const char *in, OUT char *result);
+
+	// 解密一个块大小的密文,这个块假定是AES的块大小(128bits);
+	void decryptBlock(IN const char *in, OUT char *result);
+
+	// 块的异或(XOR)运行;
+	static void xorBlock(char *block1, const char *block2) {
+		for (int i = 0; i < BLOCK_SIZE; ++i)
+			block1[i] ^= block2[i]; 
+	}
+
+	// 计数器增加(Increase)1;
+	bool incrCounter(char *counter);
+
+private:
+	enum { MAX_ROUNDS = 14 };        // maximum number of round
+	enum { MAX_KWC = 8 };            // key's maximum number of word
+	enum { BWC = 4 };                // block's number of word (BLOCK_SIZE / 4)
+
+	// Substitute Bytes Transformation Array, S-Box
+	static const u8_t sm_sbox[256];
+	// Inverse Substitute Bytes Transformation Array, Inverse S-Box
+	static const u8_t sm_isbox[256];
+	// Two-in-one Transform Array: substitute byte & MixColumns transformation
+	static const u32_t  sm_te1[256];
+	static const u32_t  sm_te2[256];
+	static const u32_t  sm_te3[256];
+	static const u32_t  sm_te4[256];
+	// Two-in-one Transform Array: inverse substitute byte & inverse MixColumns transformation
+	static const u32_t  sm_td1[256];
+	static const u32_t  sm_td2[256];
+	static const u32_t  sm_td3[256];
+	static const u32_t  sm_td4[256];
+
+#ifdef __AES_IMC_SPEEDUP__
+	// Inverse MixColumns Transformation Array
+	static const u32_t  sm_imc1[256];          
+	static const u32_t  sm_imc2[256];
+	static const u32_t  sm_imc3[256];
+	static const u32_t  sm_imc4[256];
+#else
+	// Inverse MixColumns Transformation Function
+	unsigned char mul(unsigned char a, unsigned char b);
+	u32_t invMixColumn(u32_t w);   
+#endif 
+
+	// Round Constant Array
+	static const u8_t sm_rcon[52];           
+
+	bool m_bKey;                        // key initialization flag
+	u32_t m_ke[MAX_ROUNDS + 1][BWC];    // encryption round key
+	u32_t m_kd[MAX_ROUNDS + 1][BWC];    // decryption round key
+	int m_keyLength;                    // length of key
+	int m_rounds;                       // number of rounds
+	// initial vector (IV) block, for chain mode
+	bool m_bIv;                         // IV initialization flag
+	char m_iv[BLOCK_SIZE];
+	// initial counter for CTR mode.
+	bool m_bCounter;                    // counter initialization flag
+	char m_counter[BLOCK_SIZE];
+};
+
+#endif  //__AES_CIPHER_H__
+

+ 130 - 0
MD5Test/Base64.cpp

@@ -0,0 +1,130 @@
+#include "StdAfx.h"
+#include "Base64.h"
+
+CBase64::CBase64(void)
+{
+}
+
+CBase64::~CBase64(void)
+{
+}
+
+const char CBase64::sm_base64digits[65] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+const char CBase64::sm_base64val[128] = {
+	BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+	BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+	BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
+	52, 53, 54, 55,  56, 57, 58, 59,  60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
+	BAD,  0,  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,BAD, BAD,BAD,BAD,BAD,
+	BAD, 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,BAD, BAD,BAD,BAD,BAD
+};
+
+/************************************************************************/
+/*  函数:[6/2/2016 IT];
+/*  描述:将字节转换为Base64字符;
+/*  参数:;
+/*  	[IN] pbinary:			要转换成Base64字符的二进制字节数组;
+/*  	[IN] nbinaryLen:		pbinary所指向的缓存大小;
+/*  	[OUT] pOutBase64:		返回转换后的Base64字符,以'\0'结束;
+/*  返回:返回转换成功后的Base64字符数;
+/*  注意:注意参数1是字节BYTE,返回的pOutBase64是人为加上'\0'结束符;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void CBase64::binToBase64(IN const unsigned char *pbinary, IN size_t nbinaryLen, OUT char *pOutBase64)
+{
+	for ( ; nbinaryLen >= 3; nbinaryLen -= 3, pbinary += 3) 
+	{
+		*pOutBase64++ = sm_base64digits[pbinary[0] >> 2];
+		*pOutBase64++ = sm_base64digits[((pbinary[0] << 4) & 0x30) | (pbinary[1] >> 4)];
+		*pOutBase64++ = sm_base64digits[((pbinary[1] << 2) & 0x3c) | (pbinary[2] >> 6)];
+		*pOutBase64++ = sm_base64digits[pbinary[2] & 0x3f];
+	}
+
+	if (nbinaryLen > 0) 
+	{
+		unsigned char fragment;
+		*pOutBase64++ = sm_base64digits[pbinary[0] >> 2];
+		fragment = (pbinary[0] << 4) & 0x30;
+
+		if (nbinaryLen > 1)
+			fragment |= pbinary[1] >> 4;
+
+		*pOutBase64++ = sm_base64digits[fragment];
+		*pOutBase64++ = (nbinaryLen < 2) ? '=' : sm_base64digits[(pbinary[1] << 2) & 0x3c];
+		*pOutBase64++ = '=';
+	}
+	*pOutBase64 = '\0';
+}
+
+/************************************************************************/
+/*  函数:[6/2/2016 IT];
+/*  描述:将Base64字符串转为化二进制字节字符串;
+/*  参数:;
+/*  	[IN] pBase64:		要转化成二进制字节字符串的Base64字符;
+/*  	[OUT] pbinary:		返回转化成二进制字节的字符串;
+/*  	[IN] maxLen:		pbinary指向的缓存大小;
+/*  返回:返回转化成二进制字节字符数;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int CBase64::base64ToBin(IN const char *pBase64, OUT unsigned char *pbinary, IN size_t maxLen)
+{
+	size_t len = 0;
+	unsigned char digit1, digit2, digit3, digit4;
+
+	if (pBase64[0] == '+' && pBase64[1] == ' ')
+		pBase64 += 2;
+	if (pBase64[0] == '\r')
+		return 0;
+
+	while (*pBase64 && *pBase64 != '\r' /*&& digit4 != '='*/) 
+	{
+		digit1 = pBase64[0];
+		if (decode64(digit1) == BAD)
+			return -1;
+		digit2 = pBase64[1];
+		if (decode64(digit2) == BAD)
+			return -1;
+		digit3 = pBase64[2];
+		if (digit3 != '=' && decode64(digit3) == BAD)
+			return -1; 
+		digit4 = pBase64[3];
+		if (digit4 != '=' && decode64(digit4) == BAD)
+			return -1;
+		pBase64 += 4;
+
+		++len;
+		if (maxLen && len > maxLen)
+			return -1;
+
+		*(pbinary++) = (decode64(digit1) << 2) | (decode64(digit2) >> 4);
+		if (digit3 != '=') 
+		{
+			++len;
+			if (maxLen && len > maxLen)
+				return -1;
+			*(pbinary++) = ((decode64(digit2) << 4) & 0xf0) | (decode64(digit3) >> 2);
+			if (digit4 != '=') 
+			{
+				++len;
+				if (maxLen && len > maxLen)
+					return -1;
+				*(pbinary++) = ((decode64(digit3) << 6) & 0xc0) | decode64(digit4);
+			} // if
+		} // if
+	} // while
+
+	return len;
+}

+ 70 - 0
MD5Test/Base64.h

@@ -0,0 +1,70 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[5/24/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __BASE64_CODE__
+#define __BASE64_CODE__
+
+#pragma once
+
+class CBase64
+{
+public:
+	CBase64(void);
+	~CBase64(void);
+
+	/************************************************************************/
+	/*  函数:[5/24/2016 IT];
+	/*  描述:获取指定字符串长度对应的Base64字符长度;
+	/*  参数:;
+	/*  	[IN] len:要计算的字符长度;
+	/*  返回:返回指定长度len的字符串转换为编码Base64对应的长度,并多加一个'\0'结束符;
+	/*  注意:;
+	/************************************************************************/
+	static int CalcBase64Len(IN const size_t& len) {
+		return (len / 3 + (len % 3 ? 1 : 0)) * 4 + 1; // one more byte for '\0'
+	}
+
+	static void binToBase64(IN const unsigned char *pbinary, IN size_t nbinaryLen, OUT char *pOutBase64);
+
+	/************************************************************************/
+	/*  函数:[5/24/2016 IT];
+	/*  描述:获取指定Base64字符串长度对应的字节长度;
+	/*  参数:;
+	/*  	[IN] len:要计算的Base64字符长度;
+	/*  返回:返回指定长度len的Base64字符串转换为字节对应的长度;
+	/*  注意:;
+	/************************************************************************/
+	static int CalcBinLen(size_t len) {
+		return len / 4 * 3; 
+	}
+
+	static int base64ToBin(IN const char *pBase64, OUT unsigned char *pbinary, IN size_t maxLen);
+
+private:
+	static char decode64(unsigned char ch) {
+		return ch < 128 ? sm_base64val[ch] : BAD;
+	}
+
+private:
+	enum {BAD = -1};
+	// 必须是ASCII字符;
+	static const char sm_base64digits[65];
+	// 必须是ASCII字符;
+	static const char sm_base64val[128];
+};
+
+#endif // __BASE64_CODE__

+ 63 - 0
MD5Test/MD5/MD5.cpp

@@ -0,0 +1,63 @@
+// MD5.cpp : 定义 DLL 的初始化例程。
+//
+
+#include "stdafx.h"
+#include "MD5.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+//
+//TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的,
+//		则从此 DLL 导出的任何调入
+//		MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到
+//		该函数的最前面。
+//
+//		例如:
+//
+//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
+//		{
+//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
+//			// 此处为普通函数体
+//		}
+//
+//		此宏先于任何 MFC 调用
+//		出现在每个函数中十分重要。这意味着
+//		它必须作为函数中的第一个语句
+//		出现,甚至先于所有对象变量声明,
+//		这是因为它们的构造函数可能生成 MFC
+//		DLL 调用。
+//
+//		有关其他详细信息,
+//		请参阅 MFC 技术说明 33 和 58。
+//
+
+// CMD5App
+
+BEGIN_MESSAGE_MAP(CMD5App, CWinApp)
+END_MESSAGE_MAP()
+
+
+// CMD5App 构造
+
+CMD5App::CMD5App()
+{
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CMD5App 对象
+
+CMD5App theApp;
+
+
+// CMD5App 初始化
+
+BOOL CMD5App::InitInstance()
+{
+	CWinApp::InitInstance();
+
+	return TRUE;
+}

+ 6 - 0
MD5Test/MD5/MD5.def

@@ -0,0 +1,6 @@
+; MD5.def : 声明 DLL 的模块参数。
+
+LIBRARY      "MD5"
+
+EXPORTS
+    ; 此处可以是显式导出

+ 27 - 0
MD5Test/MD5/MD5.h

@@ -0,0 +1,27 @@
+// MD5.h : MD5 DLL 的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+
+
+// CMD5App
+// 有关此类实现的信息,请参阅 MD5.cpp
+//
+
+class CMD5App : public CWinApp
+{
+public:
+	CMD5App();
+
+// 重写
+public:
+	virtual BOOL InitInstance();
+
+	DECLARE_MESSAGE_MAP()
+};

+ 125 - 0
MD5Test/MD5/MD5.rc

@@ -0,0 +1,125 @@
+// Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+	"#ifndef APSTUDIO_INVOKED\r\n"
+    "#include ""targetver.h""\r\n"
+    "#endif\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+	"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
+	"LANGUAGE 4, 2\r\n"
+	"#pragma code_page(936)\r\n"
+    "#include ""res\\MD5.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
+#ifndef _AFXDLL
+    "#include ""l.CHS\\afxres.rc""  	// 标准组件\r\n"
+#endif
+    "#endif\r\n"
+    "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // APSTUDIO_INVOKED
+
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 版本
+//
+
+VS_VERSION_INFO     VERSIONINFO
+  FILEVERSION       1,0,0,1
+  PRODUCTVERSION    1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+	BLOCK "StringFileInfo"
+	BEGIN
+        BLOCK "080403a8"
+		BEGIN
+            VALUE "CompanyName", "TODO: <公司名>"
+            VALUE "FileDescription", "TODO: <文件说明>"
+			VALUE "FileVersion",     "1.0.0.1"
+			VALUE "InternalName",    "MD5.dll"
+            VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
+			VALUE "OriginalFilename","MD5.dll"
+            VALUE "ProductName", "TODO: <产品名>"
+			VALUE "ProductVersion",  "1.0.0.1"
+		END
+	END
+	BLOCK "VarFileInfo"
+	BEGIN
+		VALUE "Translation", 0x0804, 936
+    END
+END
+
+#endif
+#ifndef APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+#include "res\\MD5.rc2"  // 非 Microsoft Visual C++ 编辑的资源
+#ifndef _AFXDLL
+#include "l.CHS\\afxres.rc"  	// 标准组件
+#endif
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED
+

+ 259 - 0
MD5Test/MD5/MD5.vcproj

@@ -0,0 +1,259 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="MD5"
+	ProjectGUID="{8FB1F8F1-68D7-445D-8041-0CFE9BB86331}"
+	RootNamespace="MD5"
+	Keyword="MFCDLLProj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				ModuleDefinitionFile=".\MD5.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				ModuleDefinitionFile=".\MD5.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\MD5.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MD5.def"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\MD5.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\MD5.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\MD5.rc2"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 44 - 0
MD5Test/MD5/ReadMe.txt

@@ -0,0 +1,44 @@
+========================================================================
+    MICROSOFT 基础类库 : MD5 项目概述
+========================================================================
+
+
+应用程序向导已为您创建了此 MD5 DLL。此 DLL 不仅演示 Microsoft 基础类的基本使用方法,还可作为您编写 DLL 的起点。
+
+本文件概要介绍组成 MD5 DLL 的每个文件的内容。
+
+MD5.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+MD5.h
+    这是 DLL 的主头文件。它声明了 CMD5App 类。
+
+MD5.cpp
+    这是主 DLL 源文件。它包含 CMD5App 类。
+
+MD5.rc
+    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+res\MD5.rc2
+    此文件包含不在 Microsoft Visual C++ 中进行编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
+
+MD5.def
+    此文件包含在 Microsoft Windows 中运行所必需的 DLL 的有关信息。它定义了 DLL 的名称和说明等参数,而且还从 DLL 导出函数。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 MD5.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 16 - 0
MD5Test/MD5/Resource.h

@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MD5.rc
+//
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE	1000
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		1000
+#define _APS_NEXT_COMMAND_VALUE		32771
+#endif
+#endif

+ 13 - 0
MD5Test/MD5/res/MD5.rc2

@@ -0,0 +1,13 @@
+//
+// MD5.RC2 - Microsoft Visual C++ 不会直接编辑的资源
+//
+
+#ifdef APSTUDIO_INVOKED
+#error 此文件不能用 Microsoft Visual C++ 编辑
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// 在此处添加手动编辑的资源...
+
+/////////////////////////////////////////////////////////////////////////////

+ 7 - 0
MD5Test/MD5/stdafx.cpp

@@ -0,0 +1,7 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// MD5.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+

+ 39 - 0
MD5Test/MD5/stdafx.h

@@ -0,0 +1,39 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxole.h>         // MFC OLE 类
+#include <afxodlgs.h>       // MFC OLE 对话框类
+#include <afxdisp.h>        // MFC 自动化类
+#endif // _AFX_NO_OLE_SUPPORT
+
+#ifndef _AFX_NO_DB_SUPPORT
+#include <afxdb.h>                      // MFC ODBC 数据库类
+#endif // _AFX_NO_DB_SUPPORT
+
+#ifndef _AFX_NO_DAO_SUPPORT
+#include <afxdao.h>                     // MFC DAO 数据库类
+#endif // _AFX_NO_DAO_SUPPORT
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                     // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+

+ 26 - 0
MD5Test/MD5/targetver.h

@@ -0,0 +1,26 @@
+
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif
+

+ 478 - 0
MD5Test/MD5Checksum.cpp

@@ -0,0 +1,478 @@
+#include "stdafx.h"
+#include "MD5Checksum.h"
+#include "MD5ChecksumDefines.h"
+
+extern HANDLE g_EventCheckMd5;
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+
+/*****************************************************************************************
+
+*****************************************************************************************/
+BYTE CMD5Checksum::GetMD5(LPCTSTR sFilePath, CString &sMd5)
+{
+	
+	try
+	{ 
+		CFile file;
+		if(file.Open(sFilePath,CFile::modeRead)==0)
+			return 1;
+
+		CMD5Checksum MD5Checksum;   //checksum object 
+		int nLength = 0;       //number of bytes read from the file
+		const int nBufferSize = 500*1024; //checksum the file in blocks of 1024 bytes
+		BYTE Buffer[nBufferSize];   //buffer for data read from the file
+
+		BYTE btRet = 0;
+		//checksum the file in blocks of 1024 bytes
+		while ((nLength = file.Read( Buffer, nBufferSize )) > 0 )
+		{
+			if(WaitForSingleObject(g_EventCheckMd5,0) == WAIT_OBJECT_0)
+			{
+				btRet = 2;
+				break;
+			}
+			MD5Checksum.Update( Buffer, nLength );
+		}
+
+		file.Close();
+
+		//finalise the checksum and return it
+		sMd5 = MD5Checksum.Final();
+		return btRet;
+	}
+
+	//report any file exceptions in debug mode only
+	catch (CFileException* e )
+	{ 
+		TRACE0("CMD5Checksum::GetMD5: CFileException caught"); 
+		throw e;
+	}
+	return 1;
+}
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::RotateLeft
+DETAILS:  private
+DESCRIPTION: Rotates the bits in a 32 bit DWORD left by a specified amount
+RETURNS:  The rotated DWORD 
+ARGUMENTS:  DWORD x : the value to be rotated
+int n   : the number of bits to rotate by
+*****************************************************************************************/
+DWORD CMD5Checksum::RotateLeft(DWORD x, int n)
+{ 
+	//check that DWORD is 4 bytes long - true in Visual C++ 6 and 32 bit Windows
+	ASSERT( sizeof(x) == 4 );
+
+	//rotate and return x
+	return (x << n) | (x >> (32-n));
+}
+
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::FF
+DETAILS:  protected
+DESCRIPTION: Implementation of basic MD5 transformation algorithm
+RETURNS:  none
+ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
+DWORD X           : Input data
+DWORD S     : MD5_SXX Transformation constant
+DWORD T     : MD5_TXX Transformation constant
+NOTES:   None
+*****************************************************************************************/
+void CMD5Checksum::FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
+{ 
+	DWORD F = (B & C) | (~B & D);
+	A += F + X + T;
+	A = RotateLeft(A, S);
+	A += B;
+}
+
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::GG
+DETAILS:  protected
+DESCRIPTION: Implementation of basic MD5 transformation algorithm
+RETURNS:  none
+ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
+DWORD X           : Input data
+DWORD S      : MD5_SXX Transformation constant
+DWORD T      : MD5_TXX Transformation constant
+NOTES:   None
+*****************************************************************************************/
+void CMD5Checksum::GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
+{ 
+	DWORD G = (B & D) | (C & ~D);
+	A += G + X + T;
+	A = RotateLeft(A, S);
+	A += B;
+}
+
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::HH
+DETAILS:  protected
+DESCRIPTION: Implementation of basic MD5 transformation algorithm
+RETURNS:  none
+ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
+DWORD X           : Input data
+DWORD S      : MD5_SXX Transformation constant
+DWORD T      : MD5_TXX Transformation constant
+NOTES:   None
+*****************************************************************************************/
+void CMD5Checksum::HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
+{ 
+	DWORD H = (B ^ C ^ D);
+	A += H + X + T;
+	A = RotateLeft(A, S);
+	A += B;
+}
+
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::II
+DETAILS:  protected
+DESCRIPTION: Implementation of basic MD5 transformation algorithm
+RETURNS:  none
+ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
+DWORD X           : Input data
+DWORD S      : MD5_SXX Transformation constant
+DWORD T      : MD5_TXX Transformation constant
+NOTES:   None
+*****************************************************************************************/
+void CMD5Checksum::II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
+{ 
+	DWORD I = (C ^ (B | ~D));
+	A += I + X + T;
+	A = RotateLeft(A, S);
+	A += B;
+}
+
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::ByteToDWord
+DETAILS:  private
+DESCRIPTION: Transfers the data in an 8 bit array to a 32 bit array
+RETURNS:  void
+ARGUMENTS:  DWORD* Output : the 32 bit (unsigned long) destination array 
+BYTE* Input   : the 8 bit (unsigned char) source array
+UINT nLength  : the number of 8 bit data items in the source array
+NOTES:   Four BYTES from the input array are transferred to each DWORD entry
+of the output array. The first BYTE is transferred to the bits (0-7) 
+of the output DWORD, the second BYTE to bits 8-15 etc. 
+The algorithm assumes that the input array is a multiple of 4 bytes long
+so that there is a perfect fit into the array of 32 bit words.
+*****************************************************************************************/
+void CMD5Checksum::ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength)
+{ 
+	//entry invariants
+	ASSERT( nLength % 4 == 0 );
+	ASSERT( AfxIsValidAddress(Output, nLength/4, TRUE) );
+	ASSERT( AfxIsValidAddress(Input, nLength, FALSE) );
+
+	//initialisations
+	UINT i=0; //index to Output array
+	UINT j=0; //index to Input array
+
+	//transfer the data by shifting and copying
+	for ( ; j < nLength; i++, j += 4)
+	{ 
+		Output[i] = (ULONG)Input[j]   | 
+			(ULONG)Input[j+1] << 8 | 
+			(ULONG)Input[j+2] << 16 | 
+			(ULONG)Input[j+3] << 24;
+	}
+}
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::Transform
+DETAILS:  protected
+DESCRIPTION: MD5 basic transformation algorithm;  transforms 'm_lMD5'
+RETURNS:  void
+ARGUMENTS:  BYTE Block[64]
+NOTES:   An MD5 checksum is calculated by four rounds of 'Transformation'.
+The MD5 checksum currently held in m_lMD5 is merged by the 
+transformation process with data passed in 'Block'.  
+*****************************************************************************************/
+void CMD5Checksum::Transform(BYTE Block[64])
+{ 
+	//initialise local data with current checksum
+	ULONG a = m_lMD5[0];
+	ULONG b = m_lMD5[1];
+	ULONG c = m_lMD5[2];
+	ULONG d = m_lMD5[3];
+
+	//copy BYTES from input 'Block' to an array of ULONGS 'X'
+	ULONG X[16];
+	ByteToDWord( X, Block, 64 );
+
+	//Perform Round 1 of the transformation
+	FF (a, b, c, d, X[ 0], MD5_S11, MD5_T01); 
+	FF (d, a, b, c, X[ 1], MD5_S12, MD5_T02); 
+	FF (c, d, a, b, X[ 2], MD5_S13, MD5_T03); 
+	FF (b, c, d, a, X[ 3], MD5_S14, MD5_T04); 
+	FF (a, b, c, d, X[ 4], MD5_S11, MD5_T05); 
+	FF (d, a, b, c, X[ 5], MD5_S12, MD5_T06); 
+	FF (c, d, a, b, X[ 6], MD5_S13, MD5_T07); 
+	FF (b, c, d, a, X[ 7], MD5_S14, MD5_T08); 
+	FF (a, b, c, d, X[ 8], MD5_S11, MD5_T09); 
+	FF (d, a, b, c, X[ 9], MD5_S12, MD5_T10); 
+	FF (c, d, a, b, X[10], MD5_S13, MD5_T11); 
+	FF (b, c, d, a, X[11], MD5_S14, MD5_T12); 
+	FF (a, b, c, d, X[12], MD5_S11, MD5_T13); 
+	FF (d, a, b, c, X[13], MD5_S12, MD5_T14); 
+	FF (c, d, a, b, X[14], MD5_S13, MD5_T15); 
+	FF (b, c, d, a, X[15], MD5_S14, MD5_T16);
+
+	//Perform Round 2 of the transformation
+	GG (a, b, c, d, X[ 1], MD5_S21, MD5_T17); 
+	GG (d, a, b, c, X[ 6], MD5_S22, MD5_T18); 
+	GG (c, d, a, b, X[11], MD5_S23, MD5_T19); 
+	GG (b, c, d, a, X[ 0], MD5_S24, MD5_T20); 
+	GG (a, b, c, d, X[ 5], MD5_S21, MD5_T21); 
+	GG (d, a, b, c, X[10], MD5_S22, MD5_T22); 
+	GG (c, d, a, b, X[15], MD5_S23, MD5_T23); 
+	GG (b, c, d, a, X[ 4], MD5_S24, MD5_T24); 
+	GG (a, b, c, d, X[ 9], MD5_S21, MD5_T25); 
+	GG (d, a, b, c, X[14], MD5_S22, MD5_T26); 
+	GG (c, d, a, b, X[ 3], MD5_S23, MD5_T27); 
+	GG (b, c, d, a, X[ 8], MD5_S24, MD5_T28); 
+	GG (a, b, c, d, X[13], MD5_S21, MD5_T29); 
+	GG (d, a, b, c, X[ 2], MD5_S22, MD5_T30); 
+	GG (c, d, a, b, X[ 7], MD5_S23, MD5_T31); 
+	GG (b, c, d, a, X[12], MD5_S24, MD5_T32);
+
+	//Perform Round 3 of the transformation
+	HH (a, b, c, d, X[ 5], MD5_S31, MD5_T33); 
+	HH (d, a, b, c, X[ 8], MD5_S32, MD5_T34); 
+	HH (c, d, a, b, X[11], MD5_S33, MD5_T35); 
+	HH (b, c, d, a, X[14], MD5_S34, MD5_T36); 
+	HH (a, b, c, d, X[ 1], MD5_S31, MD5_T37); 
+	HH (d, a, b, c, X[ 4], MD5_S32, MD5_T38); 
+	HH (c, d, a, b, X[ 7], MD5_S33, MD5_T39); 
+	HH (b, c, d, a, X[10], MD5_S34, MD5_T40); 
+	HH (a, b, c, d, X[13], MD5_S31, MD5_T41); 
+	HH (d, a, b, c, X[ 0], MD5_S32, MD5_T42); 
+	HH (c, d, a, b, X[ 3], MD5_S33, MD5_T43); 
+	HH (b, c, d, a, X[ 6], MD5_S34, MD5_T44); 
+	HH (a, b, c, d, X[ 9], MD5_S31, MD5_T45); 
+	HH (d, a, b, c, X[12], MD5_S32, MD5_T46); 
+	HH (c, d, a, b, X[15], MD5_S33, MD5_T47); 
+	HH (b, c, d, a, X[ 2], MD5_S34, MD5_T48);
+
+	//Perform Round 4 of the transformation
+	II (a, b, c, d, X[ 0], MD5_S41, MD5_T49); 
+	II (d, a, b, c, X[ 7], MD5_S42, MD5_T50); 
+	II (c, d, a, b, X[14], MD5_S43, MD5_T51); 
+	II (b, c, d, a, X[ 5], MD5_S44, MD5_T52); 
+	II (a, b, c, d, X[12], MD5_S41, MD5_T53); 
+	II (d, a, b, c, X[ 3], MD5_S42, MD5_T54); 
+	II (c, d, a, b, X[10], MD5_S43, MD5_T55); 
+	II (b, c, d, a, X[ 1], MD5_S44, MD5_T56); 
+	II (a, b, c, d, X[ 8], MD5_S41, MD5_T57); 
+	II (d, a, b, c, X[15], MD5_S42, MD5_T58); 
+	II (c, d, a, b, X[ 6], MD5_S43, MD5_T59); 
+	II (b, c, d, a, X[13], MD5_S44, MD5_T60); 
+	II (a, b, c, d, X[ 4], MD5_S41, MD5_T61); 
+	II (d, a, b, c, X[11], MD5_S42, MD5_T62); 
+	II (c, d, a, b, X[ 2], MD5_S43, MD5_T63); 
+	II (b, c, d, a, X[ 9], MD5_S44, MD5_T64);
+
+	//add the transformed values to the current checksum
+	m_lMD5[0] += a;
+	m_lMD5[1] += b;
+	m_lMD5[2] += c;
+	m_lMD5[3] += d;
+}
+
+
+/*****************************************************************************************
+CONSTRUCTOR: CMD5Checksum
+DESCRIPTION: Initialises member data
+ARGUMENTS:  None
+NOTES:   None
+*****************************************************************************************/
+CMD5Checksum::CMD5Checksum()
+{ 
+	// zero members
+	memset( m_lpszBuffer, 0, 64 );
+	m_nCount[0] = m_nCount[1] = 0;
+
+	// Load magic state initialization constants
+	m_lMD5[0] = MD5_INIT_STATE_0;
+	m_lMD5[1] = MD5_INIT_STATE_1;
+	m_lMD5[2] = MD5_INIT_STATE_2;
+	m_lMD5[3] = MD5_INIT_STATE_3;
+}
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::DWordToByte
+DETAILS:  private
+DESCRIPTION: Transfers the data in an 32 bit array to a 8 bit array
+RETURNS:  void
+ARGUMENTS:  BYTE* Output  : the 8 bit destination array 
+DWORD* Input  : the 32 bit source array
+UINT nLength  : the number of 8 bit data items in the source array
+NOTES:   One DWORD from the input array is transferred into four BYTES 
+in the output array. The first (0-7) bits of the first DWORD are 
+transferred to the first output BYTE, bits bits 8-15 are transferred from
+the second BYTE etc. 
+
+The algorithm assumes that the output array is a multiple of 4 bytes long
+so that there is a perfect fit of 8 bit BYTES into the 32 bit DWORDs.
+*****************************************************************************************/
+void CMD5Checksum::DWordToByte(BYTE* Output, DWORD* Input, UINT nLength )
+{ 
+	//entry invariants
+	ASSERT( nLength % 4 == 0 );
+	ASSERT( AfxIsValidAddress(Output, nLength, TRUE) );
+	ASSERT( AfxIsValidAddress(Input, nLength/4, FALSE) );
+
+	//transfer the data by shifting and copying
+	UINT i = 0;
+	UINT j = 0;
+	for ( ; j < nLength; i++, j += 4) 
+	{ 
+		Output[j]  = (UCHAR)(Input[i] & 0xff    );
+		Output[j+1] = (UCHAR)((Input[i] >> 8) & 0xff);
+		Output[j+2] = (UCHAR)((Input[i] >> 16) & 0xff);
+		Output[j+3] = (UCHAR)((Input[i] >> 24) & 0xff);
+	}
+}
+
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::Final
+DETAILS:  protected
+DESCRIPTION: Implementation of main MD5 checksum algorithm; ends the checksum calculation.
+RETURNS:  CString : the final hexadecimal MD5 checksum result 
+ARGUMENTS:  None
+NOTES:   Performs the final MD5 checksum calculation ('Update' does most of the work,
+this function just finishes the calculation.) 
+*****************************************************************************************/
+CString CMD5Checksum::Final()
+{ 
+	//Save number of bits
+	BYTE Bits[8];
+	DWordToByte( Bits, m_nCount, 8 );
+
+	//Pad out to 56 mod 64.
+	UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3f);
+	UINT nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
+	Update( PADDING, nPadLen );
+
+	//Append length (before padding)
+	Update( Bits, 8 );
+
+	//Store final state in 'lpszMD5'
+	const int nMD5Size = 16;
+	unsigned char lpszMD5[ nMD5Size ];
+	DWordToByte( lpszMD5, m_lMD5, nMD5Size );
+
+	//Convert the hexadecimal checksum to a CString
+	CString strMD5;
+	for ( int i=0; i < nMD5Size; i++) 
+	{ 
+		CString Str;
+		if (lpszMD5[i] == 0) 
+		{ 
+			Str = CString("00");
+		}
+		else if (lpszMD5[i] <= 15)  
+		{ 
+			Str.Format(_T("0%X"),lpszMD5[i]);
+		}
+		else
+		{ 
+			Str.Format(_T("%X"),lpszMD5[i]);
+		}
+
+		ASSERT( Str.GetLength() == 2 );
+		strMD5 += Str;
+	}
+	ASSERT( strMD5.GetLength() == 32 );
+	/*
+	char szMd5[MAX_DESC] = {0};
+	sprintf_s(szMd5, sizeof(szMd5), "%s", strMD5.GetBuffer());
+	strMD5.ReleaseBuffer();
+	return szMd5;
+	*/
+	return strMD5;
+}
+
+
+/*****************************************************************************************
+FUNCTION:  CMD5Checksum::Update
+DETAILS:  protected
+DESCRIPTION: Implementation of main MD5 checksum algorithm
+RETURNS:  void
+ARGUMENTS:  BYTE* Input    : input block
+UINT nInputLen : length of input block
+NOTES:   Computes the partial MD5 checksum for 'nInputLen' bytes of data in 'Input'
+*****************************************************************************************/
+void CMD5Checksum::Update( BYTE* Input, ULONG nInputLen )
+{ 
+	//Compute number of bytes mod 64
+	UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3F);
+
+	//Update number of bits
+	if ( ( m_nCount[0] += nInputLen << 3 )  <  ( nInputLen << 3) )
+	{ 
+		m_nCount[1]++;
+	}
+	m_nCount[1] += (nInputLen >> 29);
+
+	//Transform as many times as possible.
+	UINT i=0;  
+	UINT nPartLen = 64 - nIndex;
+	if (nInputLen >= nPartLen)  
+	{ 
+		memcpy( &m_lpszBuffer[nIndex], Input, nPartLen );
+		Transform( m_lpszBuffer );
+		for (i = nPartLen; i + 63 < nInputLen; i += 64) 
+		{ 
+			Transform( &Input[i] );
+		}
+		nIndex = 0;
+	} 
+	else 
+	{
+		i = 0;
+	}
+
+	// Buffer remaining input
+	memcpy( &m_lpszBuffer[nIndex], &Input[i], nInputLen-i);
+}
+
+
+
+CString CMD5Checksum::GetMD5OfString(CString strString)
+{
+	try
+	{ 
+		CMD5Checksum MD5Checksum;   //checksum object 
+		int nLength = strString.GetLength();       //number of bytes read from the file
+		//const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes
+		BYTE *Buffer;   //buffer for data read from the file
+		Buffer=(BYTE*)(strString.GetBuffer(nLength));
+		//checksum the file in blocks of 1024 bytes
+		//while ((nLength = File.Read( Buffer, nBufferSize )) > 0 )
+		//{ 
+		MD5Checksum.Update( Buffer, nLength );
+		//}
+		//finalise the checksum and return it
+		return MD5Checksum.Final();
+	}
+
+	//report any file exceptions in debug mode only
+	catch (CFileException* e )
+	{ 
+		TRACE0("CMD5Checksum::GetMD5: CFileException caught"); 
+		throw e;
+	}
+}

+ 43 - 0
MD5Test/MD5Checksum.h

@@ -0,0 +1,43 @@
+#if !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_)
+#define AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+/*****************************************************************************************
+
+  
+*****************************************************************************************/
+class CMD5Checksum  
+{
+public:
+ static CString GetMD5OfString(CString strString);
+ //interface functions for the RSA MD5 calculation
+ static BYTE GetMD5(LPCTSTR sFilePath, CString &sMd5);
+
+protected:
+ //constructor/destructor
+ CMD5Checksum();
+ virtual ~CMD5Checksum() {};
+
+ //RSA MD5 implementation
+ void Transform(BYTE Block[64]);
+ void Update(BYTE* Input, ULONG nInputLen);
+ CString Final();
+ inline DWORD RotateLeft(DWORD x, int n);
+ inline void FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);
+ inline void GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);
+ inline void HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);
+ inline void II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);
+
+ //utility functions
+ inline void DWordToByte(BYTE* Output, DWORD* Input, UINT nLength);
+ inline void ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength);
+
+private:
+ BYTE  m_lpszBuffer[64];  //input buffer
+ ULONG m_nCount[2];   //number of bits, modulo 2^64 (lsb first)
+ ULONG m_lMD5[4];   //MD5 checksum
+};
+
+#endif // !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_)

+ 103 - 0
MD5Test/MD5ChecksumDefines.h

@@ -0,0 +1,103 @@
+//Magic initialization constants
+#define MD5_INIT_STATE_0 0x67452301
+#define MD5_INIT_STATE_1 0xefcdab89
+#define MD5_INIT_STATE_2 0x98badcfe
+#define MD5_INIT_STATE_3 0x10325476
+
+//Constants for Transform routine.
+#define MD5_S11  7
+#define MD5_S12 12
+#define MD5_S13 17
+#define MD5_S14 22
+#define MD5_S21  5
+#define MD5_S22  9
+#define MD5_S23 14
+#define MD5_S24 20
+#define MD5_S31  4
+#define MD5_S32 11
+#define MD5_S33 16
+#define MD5_S34 23
+#define MD5_S41  6
+#define MD5_S42 10
+#define MD5_S43 15
+#define MD5_S44 21
+
+//Transformation Constants - Round 1
+#define MD5_T01  0xd76aa478 //Transformation Constant 1 
+#define MD5_T02  0xe8c7b756 //Transformation Constant 2
+#define MD5_T03  0x242070db //Transformation Constant 3
+#define MD5_T04  0xc1bdceee //Transformation Constant 4
+#define MD5_T05  0xf57c0faf //Transformation Constant 5
+#define MD5_T06  0x4787c62a //Transformation Constant 6
+#define MD5_T07  0xa8304613 //Transformation Constant 7
+#define MD5_T08  0xfd469501 //Transformation Constant 8
+#define MD5_T09  0x698098d8 //Transformation Constant 9
+#define MD5_T10  0x8b44f7af //Transformation Constant 10
+#define MD5_T11  0xffff5bb1 //Transformation Constant 11
+#define MD5_T12  0x895cd7be //Transformation Constant 12
+#define MD5_T13  0x6b901122 //Transformation Constant 13
+#define MD5_T14  0xfd987193 //Transformation Constant 14
+#define MD5_T15  0xa679438e //Transformation Constant 15
+#define MD5_T16  0x49b40821 //Transformation Constant 16
+
+//Transformation Constants - Round 2
+#define MD5_T17  0xf61e2562 //Transformation Constant 17
+#define MD5_T18  0xc040b340 //Transformation Constant 18
+#define MD5_T19  0x265e5a51 //Transformation Constant 19
+#define MD5_T20  0xe9b6c7aa //Transformation Constant 20
+#define MD5_T21  0xd62f105d //Transformation Constant 21
+#define MD5_T22  0x02441453 //Transformation Constant 22
+#define MD5_T23  0xd8a1e681 //Transformation Constant 23
+#define MD5_T24  0xe7d3fbc8 //Transformation Constant 24
+#define MD5_T25  0x21e1cde6 //Transformation Constant 25
+#define MD5_T26  0xc33707d6 //Transformation Constant 26
+#define MD5_T27  0xf4d50d87 //Transformation Constant 27
+#define MD5_T28  0x455a14ed //Transformation Constant 28
+#define MD5_T29  0xa9e3e905 //Transformation Constant 29
+#define MD5_T30  0xfcefa3f8 //Transformation Constant 30
+#define MD5_T31  0x676f02d9 //Transformation Constant 31
+#define MD5_T32  0x8d2a4c8a //Transformation Constant 32
+
+//Transformation Constants - Round 3
+#define MD5_T33  0xfffa3942 //Transformation Constant 33
+#define MD5_T34  0x8771f681 //Transformation Constant 34
+#define MD5_T35  0x6d9d6122 //Transformation Constant 35
+#define MD5_T36  0xfde5380c //Transformation Constant 36
+#define MD5_T37  0xa4beea44 //Transformation Constant 37
+#define MD5_T38  0x4bdecfa9 //Transformation Constant 38
+#define MD5_T39  0xf6bb4b60 //Transformation Constant 39
+#define MD5_T40  0xbebfbc70 //Transformation Constant 40
+#define MD5_T41  0x289b7ec6 //Transformation Constant 41
+#define MD5_T42  0xeaa127fa //Transformation Constant 42
+#define MD5_T43  0xd4ef3085 //Transformation Constant 43
+#define MD5_T44  0x04881d05 //Transformation Constant 44
+#define MD5_T45  0xd9d4d039 //Transformation Constant 45
+#define MD5_T46  0xe6db99e5 //Transformation Constant 46
+#define MD5_T47  0x1fa27cf8 //Transformation Constant 47
+#define MD5_T48  0xc4ac5665 //Transformation Constant 48
+
+//Transformation Constants - Round 4
+#define MD5_T49  0xf4292244 //Transformation Constant 49
+#define MD5_T50  0x432aff97 //Transformation Constant 50
+#define MD5_T51  0xab9423a7 //Transformation Constant 51
+#define MD5_T52  0xfc93a039 //Transformation Constant 52
+#define MD5_T53  0x655b59c3 //Transformation Constant 53
+#define MD5_T54  0x8f0ccc92 //Transformation Constant 54
+#define MD5_T55  0xffeff47d //Transformation Constant 55
+#define MD5_T56  0x85845dd1 //Transformation Constant 56
+#define MD5_T57  0x6fa87e4f //Transformation Constant 57
+#define MD5_T58  0xfe2ce6e0 //Transformation Constant 58
+#define MD5_T59  0xa3014314 //Transformation Constant 59
+#define MD5_T60  0x4e0811a1 //Transformation Constant 60
+#define MD5_T61  0xf7537e82 //Transformation Constant 61
+#define MD5_T62  0xbd3af235 //Transformation Constant 62
+#define MD5_T63  0x2ad7d2bb //Transformation Constant 63
+#define MD5_T64  0xeb86d391 //Transformation Constant 64
+
+
+//Null data (except for first BYTE) used to finalise the checksum calculation
+static unsigned char PADDING[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};

+ 914 - 0
MD5Test/MD5Test.cpp

@@ -0,0 +1,914 @@
+// MD5Test.cpp : 定义控制台应用程序的入口点。
+//
+
+#include "stdafx.h"
+#include "MD5Test.h"
+
+#include "md5.h"
+#include "Base64.h"
+#include "StringProcess.h"
+#include "AesCipher.h"
+#include "lzari.h"
+#include "des.h"
+#include <stdio.h>
+
+
+// ----stat头文件;
+#include <sys/types.h>
+#include <sys/stat.h>
+// ----stat头文件;
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 唯一的应用程序对象;
+
+INT Test_Bin2Base64_WChar(IN WCHAR* pWString, IN INT nWStrLen, OUT CHAR** pBase64)
+{
+	// 1.计算出Base64的长度,CalcBase64Len的参数必须是字节长度,而非字符数;
+	INT nBaseLen = CBase64::CalcBase64Len(nWStrLen*sizeof(WCHAR));
+
+	// 2.创建Base64缓存;
+	*pBase64 = new CHAR[nBaseLen + 1];
+	memset(*pBase64, 0, nBaseLen + 1);
+
+	// 3.转化出Base64字符;
+	CBase64::binToBase64((const unsigned char*)pWString, nWStrLen, *pBase64);
+
+	return nBaseLen;
+}
+
+INT Test_Bin2Base64_ASCII(IN CHAR* pString, IN INT nStrLen, OUT CHAR** pBase64)
+{
+	// 1.计算出Base64的长度,CalcBase64Len的参数必须是字节长度,而非字符数;
+	INT nBaseLen = CBase64::CalcBase64Len(nStrLen);
+
+	// 2.创建Base64缓存;
+	*pBase64 = new CHAR[nBaseLen + 1];
+	memset(*pBase64, 0, nBaseLen + 1);
+
+	// 3.转化出Base64字符;
+	CBase64::binToBase64((const unsigned char*)pString, nStrLen, *pBase64);
+
+	return nBaseLen;
+}
+
+void Test_Base642Bin_WChar(IN CHAR* pBase64, IN INT nBase64Len, OUT WCHAR* pOutBin, IN INT nOutLen )
+{
+	// 1.计算出字节长度;
+	INT nByteLen = CBase64::CalcBinLen(nBase64Len);
+
+	// 2.创建Byte缓存区;
+	BYTE *pBin = new BYTE[nByteLen];
+	memset(pBin, 0, nByteLen);
+
+	// 3.转化成字节;
+	CBase64::base64ToBin(pBase64, pBin, nByteLen);
+
+	if ( pOutBin == NULL )
+	{
+		if ( pBin )
+			delete []pBin;
+		pBin = NULL;
+	}
+	else 
+	{
+		memcpy(pOutBin, pBin, nByteLen);
+		if ( pBin )
+			delete []pBin;
+		pBin = NULL;
+	}
+}
+
+INT Test_Base642Bin_ASCII(IN CHAR* pBase64, IN INT nBase64Len, OUT CHAR* pOutBin, IN INT nOutLen )
+{
+	// 1.计算出字节长度;
+	INT nByteLen = CBase64::CalcBinLen(nBase64Len);
+
+	// 2.创建Byte缓存区;
+	BYTE *pBin = new BYTE[nByteLen];
+	memset(pBin, 0, nByteLen);
+
+	// 3.转化成字节;
+	CBase64::base64ToBin(pBase64, pBin, nByteLen);
+
+	if ( pOutBin == NULL )
+	{
+		if ( pBin )
+			delete []pBin;
+		pBin = NULL;
+	}
+	else 
+	{
+		memcpy(pOutBin, pBin, nByteLen);
+		if ( pBin )
+			delete []pBin;
+		pBin = NULL;
+	}
+
+	return nByteLen;
+}
+
+// 从指定的文件读取数据,并生成出Base64对应的文本文件;
+void Test_CreateBase64File(IN LPCTSTR lpBinFile, IN LPCTSTR lpBase64File)
+{
+	CFile cf;
+	if ( cf.Open(lpBinFile, CFile::modeRead) )
+	{
+		ULONGLONG uLen = cf.GetLength();
+		BYTE *pData = new BYTE[uLen];
+		memset(pData, 0, uLen);
+
+		cf.Read(pData, uLen);
+
+		// 1.计算出base 64的长度;
+		ULONGLONG uBaseLen = CBase64::CalcBase64Len(uLen);
+
+		// 创建Base64缓存;
+		CHAR *pBase64 = new CHAR[uBaseLen + 1];
+		memset(pBase64, 0, uBaseLen + 1);
+
+		CBase64::binToBase64(pData, uLen, pBase64);
+
+		CFile cf64;
+		if ( cf64.Open(lpBase64File, CFile::modeCreate|CFile::modeWrite) )
+		{
+			cf64.Write(pBase64, uBaseLen + 1);
+
+			if ( pBase64 )
+				delete []pBase64;
+			pBase64 = NULL;
+
+			cf64.Close();
+		}
+
+		if ( pData )
+			delete []pData;
+		pData = NULL;
+
+		cf.Close();
+	}
+}
+
+// 将Base64内容的文本文件恢复回正常的文件;
+void Test_CreateBindFile(IN LPCTSTR lpBase64File, IN LPCTSTR lpBinFile )
+{
+	CFile cf64;
+	if ( cf64.Open(lpBase64File, CFile::modeRead) )
+	{
+		ULONGLONG uLen = cf64.GetLength();
+		BYTE *pBase64Data = new BYTE[uLen];
+		memset(pBase64Data, 0, uLen);
+
+		cf64.Read(pBase64Data, uLen);
+
+		// 1.计算出二进制字节的长度;
+		ULONGLONG uBinLen = CBase64::CalcBinLen(uLen);
+
+		// 创建binary缓存;
+		BYTE *pByte = new BYTE[uBinLen];
+		memset(pByte, 0, uBinLen);
+
+		uBinLen = CBase64::base64ToBin((CHAR*)pBase64Data, pByte, uBinLen);
+		pByte[uBinLen] = '\0'; // 必须操作这一步,否则数据末尾不会正常截断;
+
+		CFile cfbin;
+		if ( cfbin.Open(lpBinFile, CFile::modeCreate|CFile::modeWrite) )
+		{
+			cfbin.Write(pByte, uBinLen);
+
+			if ( pByte )
+				delete []pByte;
+			pByte = NULL;
+
+			cfbin.Close();
+		}
+
+		if ( pBase64Data )
+			delete []pBase64Data;
+		pBase64Data = NULL;
+
+		cf64.Close();
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////
+// 将文件使用Aes计算器模式加密,并生成加密文件;
+void Test_Aes_Encryptfile_CTR(IN LPCTSTR lpFile, IN LPCCH lpKey, IN LPCTSTR lpAesFile)
+{
+	// 1.定义数据;
+	BYTE *pFileBuff = NULL;				// 文件缓存指针;
+	ULONGLONG uFileLen = 0;				// 文件长度;
+	BYTE *pOutBuff = NULL;				// 加密后的文件数据;
+	ULONGLONG uOutLen = 0;				// 文件数据加密后的长度;
+	CHAR szKey[MAX_PATH] = {0};			// 加密使用的密钥;
+	CHAR szCounter[16] = {0};			// 计算器模式下的计算值;
+
+	// 设置计算器计算值;
+	szCounter[5] = -113;
+	// 获取文件数据;
+	CFile cf;
+	if ( cf.Open(lpFile, CFile::modeRead) )
+	{
+		uFileLen = cf.GetLength();
+		pFileBuff = new BYTE[uFileLen];
+		memset(pFileBuff, 0, uFileLen);
+		cf.Read(pFileBuff, uFileLen);
+
+		cf.Close();
+	}
+
+	// 3.开始加密;
+	AesCipher AesCrypto;
+	AesCrypto.makeRoundKey(lpKey, strlen(lpKey));
+	AesCrypto.setCounter(szCounter);
+
+	// 计算出文件加密后的长度;
+	uOutLen = AesCrypto.calculateCipherLen(uFileLen);
+	pOutBuff = new BYTE[uOutLen];
+	memset(pOutBuff, 0, uOutLen);
+
+	// 加密文件数据成字符串;
+	AesCrypto.encryptString((CHAR*)pFileBuff, (CHAR*)pOutBuff, uFileLen, AesCipher::CTR);
+
+	// 释放文件数据资源;
+	if ( pFileBuff )
+		delete []pFileBuff;
+	pFileBuff = NULL;
+
+	// 将加密后的数据保存到文件中;
+	CFile cfAes;
+	if ( cfAes.Open(lpAesFile, CFile::modeCreate|CFile::modeWrite) )
+	{
+		cfAes.Write(pOutBuff, uOutLen);
+		cfAes.Close();
+	}
+
+	// 释放加密后的文件数据;
+	if ( pOutBuff )
+		delete []pOutBuff;
+	pOutBuff = NULL;
+}
+
+void Test_Aes_Decryptfile_CTR(IN LPCTSTR lpFile, IN LPCCH lpKey, IN LPCTSTR lpAesFile)
+{
+	// 1.定义数据;
+	BYTE *pFileBuff = NULL;				// 文件缓存指针;
+	ULONGLONG uFileLen = 0;				// 文件长度;
+	BYTE *pOutBuff = NULL;				// 解密后的文件数据;
+	ULONGLONG uOutLen = 0;				// 文件数据解密后的长度;
+	CHAR szKey[MAX_PATH] = {0};			// 加密使用的密钥;
+	CHAR szCounter[16] = {0};			// 计算器模式下的计算值;
+
+	// 设置计算器计算值;
+	szCounter[5] = -113;
+	// 获取文件数据;
+	CFile cf;
+	if ( cf.Open(lpFile, CFile::modeRead) )
+	{
+		uFileLen = cf.GetLength();
+		pFileBuff = new BYTE[uFileLen];
+		memset(pFileBuff, 0, uFileLen);
+		cf.Read(pFileBuff, uFileLen);
+
+		cf.Close();
+	}
+
+	// 3.开始解密;
+	AesCipher AesCrypto;
+	AesCrypto.makeRoundKey(lpKey, strlen(lpKey));
+	AesCrypto.setCounter(szCounter);
+
+	// 初始化输出数据;
+	pOutBuff = new BYTE[uFileLen + 1];
+	memset(pOutBuff, 0, uFileLen + 1);
+
+	// 解密文件数据成字符串,并返回解密后的数据长度;
+	uOutLen =  AesCrypto.decryptString((CHAR*)pFileBuff, (CHAR*)pOutBuff, uFileLen, AesCipher::CTR);
+	pOutBuff[uOutLen] = '\0'; // 必须操作这一步,否则数据末尾不会正常截断;
+
+	// 释放文件数据资源;
+	if ( pFileBuff )
+		delete []pFileBuff;
+	pFileBuff = NULL;
+
+	// 将加密后的数据保存到文件中;
+	CFile cfAes;
+	if ( cfAes.Open(lpAesFile, CFile::modeCreate|CFile::modeWrite) )
+	{
+		cfAes.Write(pOutBuff, uOutLen);
+		cfAes.Close();
+	}
+
+	// 释放加密后的文件数据;
+	if ( pOutBuff )
+		delete []pOutBuff;
+	pOutBuff = NULL;
+}
+
+// ECB, CBC, CFB, OFB工作模式(明文比密文长度要短很多);
+void Test_Aes_Decryptfile_Others(IN LPCCH lpPlainText, IN LPCCH lpKey, IN LPCCH lpCounter)
+{
+	// 参数有效性判断;
+	if ( lpPlainText == NULL || lpKey == NULL )
+		return;
+
+	// 密钥是否符合长度要求;
+	INT nKeyLen = strlen(lpKey);
+	if ( nKeyLen != 16 && nKeyLen != 24 && nKeyLen != 32 )
+		return;
+
+	// 明文长度;
+	INT nPlainTextLen = strlen(lpPlainText);
+
+	AesCipher AesCrypt;
+	AesCrypt.makeRoundKey(lpKey);
+	if ( lpCounter )
+		AesCrypt.setCounter(lpCounter);
+	// 输出的密文;
+	CHAR* pOutCipherText = NULL;
+	// 计算密文长度;
+	INT nCipherTextLen = AesCrypt.calculateCipherLen(strlen(lpPlainText));
+	// 创建密文堆;
+	pOutCipherText = new CHAR[nCipherTextLen+1];
+	memset(pOutCipherText, 0, nCipherTextLen + 1);
+
+	// 解密后的明文;
+	CHAR* pPlainText = NULL;
+	pPlainText = new CHAR[nCipherTextLen+1];
+	memset(pPlainText, 0 ,nCipherTextLen+1);
+
+	// ECB mode;
+	printf("\n\nECB*****************************************************\n");
+	AesCrypt.encryptString(lpPlainText, pOutCipherText, nPlainTextLen, AesCipher::ECB);
+	//pOutCipherText[nCipherTextLen] = '\0';
+	printf("ECB Encrypt mode \n %s \n %s \n\n", lpPlainText, pOutCipherText);
+	nPlainTextLen = AesCrypt.decryptString(pOutCipherText, pPlainText, nCipherTextLen, AesCipher::ECB);
+	pPlainText[nPlainTextLen] = '\0';
+	printf("ECB Decrypt mode \n %s \n %s \n\n", pOutCipherText, pPlainText);
+
+	// CBC mode;
+	printf("\n\nCBC*****************************************************\n");
+	memset(pOutCipherText, 0, nCipherTextLen + 1);
+	memset(pPlainText, 0 ,nCipherTextLen+1);
+
+	// 为CBC、CFB、OFB三模式设置初始向量;
+	AesCrypt.setIV("Cache.0123456789");
+	AesCrypt.encryptString(lpPlainText, pOutCipherText, nPlainTextLen, AesCipher::CBC);
+	//pOutCipherText[nCipherTextLen] = '\0';
+	printf("CBC Encrypt mode \n %s \n %s \n\n", lpPlainText, pOutCipherText);
+	nPlainTextLen = AesCrypt.decryptString(pOutCipherText, pPlainText, nCipherTextLen, AesCipher::CBC);
+	pPlainText[nPlainTextLen] = '\0';
+	printf("CBC Decrypt mode \n %s \n %s \n\n", pOutCipherText, pPlainText);
+
+	// CFB mode;
+	printf("\n\nCFB*****************************************************\n");
+	memset(pOutCipherText, 0, nCipherTextLen + 1);
+	memset(pPlainText, 0 ,nCipherTextLen+1);
+
+	AesCrypt.encryptString(lpPlainText, pOutCipherText, nPlainTextLen, AesCipher::CFB);
+	//pOutCipherText[nCipherTextLen] = '\0';
+	printf("CFB Encrypt mode \n %s \n %s \n\n", lpPlainText, pOutCipherText);
+	nPlainTextLen = AesCrypt.decryptString(pOutCipherText, pPlainText, nCipherTextLen, AesCipher::CFB);
+	pPlainText[nPlainTextLen] = '\0';
+	printf("CFB Decrypt mode \n %s \n %s \n\n", pOutCipherText, pPlainText);
+
+	// OFB mode;
+	printf("\n\nOFB*****************************************************\n");
+	memset(pOutCipherText, 0, nCipherTextLen + 1);
+	memset(pPlainText, 0 ,nCipherTextLen+1);
+
+	AesCrypt.encryptString(lpPlainText, pOutCipherText, nPlainTextLen, AesCipher::OFB);
+	//pOutCipherText[nCipherTextLen] = '\0';
+	printf("OFB Encrypt mode \n %s \n %s \n\n", lpPlainText, pOutCipherText);
+	nPlainTextLen = AesCrypt.decryptString(pOutCipherText, pPlainText, nCipherTextLen, AesCipher::OFB);
+	pPlainText[nPlainTextLen] = '\0';
+	printf("OFB Decrypt mode \n %s \n %s \n\n", pOutCipherText, pPlainText);
+}
+//
+//void DES()
+//{
+//	int i, j;
+//	unsigned char buf[1024];
+//	unsigned long tsc;
+//	unsigned char tmp[64];
+//
+//	CHAR* pBase64 = NULL;
+//	//CHAR* pBinary = NULL;
+//	BYTE szVI[9] = "ABCD6789"; 
+//	CHAR szBinary[MAX_PATH] = {0};
+//
+//	des_context des;
+//	des3_context des3;
+//
+//	//密钥是01234567, 明文zth DES
+//	memset(tmp, 0, sizeof(tmp)); 
+//	strcpy((char*)tmp, "01234567");
+//	memset(buf, 0, sizeof(buf)); 
+//	strcpy((char*)buf, "zth");
+//
+//	// 设置加密的des结构体值;
+//	des_setkey_enc( &des, tmp);
+//
+//	printf("pwd=%s, txt=%s\n", tmp, buf);
+//	// 加密;
+//	des_crypt_cbc(&des, DES_ENCRYPT, 8, szVI, buf, buf );
+//	//Test_Base642Bin_ASCII();
+//
+//	Test_Bin2Base64_ASCII((char*)buf, strlen((char*)buf), &pBase64);
+//	Test_Base642Bin_ASCII(pBase64, strlen(pBase64), szBinary, MAX_PATH);
+//	/*printf("encrypt txt= \n %s\n%s\n%s\n", tmp, buf, buf);
+//	for(i=0; i<8; i++) printf("%x ", buf[i]); 
+//	printf("\n");*/
+//
+//	// 解密;
+//	memset(szVI, 0, sizeof(szVI));
+//	strcpy((char*)szVI, "ABCD6789");
+//	// 设置解密des结构体;
+//	des_setkey_dec(&des, tmp);
+//	// 解密;
+//	des_crypt_cbc(&des, DES_DECRYPT, 8, szVI, (BYTE*)szBinary, buf );
+//	/*printf("decrypt txt=");
+//	for(i=0; i<8; i++) printf("%x ", buf[i]); 
+//	printf("\n\n");*/
+//
+//	//密钥是01234567abcdefgh, 明文zth  DES3
+//	memset(tmp, 0, sizeof(tmp)); strcpy((char*)tmp, "01234567abcdefgh");
+//	memset(buf, 0, sizeof(buf)); strcpy((char*)buf, "zth");
+//	des3_set3key_enc( &des3, tmp);
+//	printf("DES3 pwd=%s, txt=%s\n", tmp, buf);
+//	des3_crypt_cbc(&des3, DES_ENCRYPT, 8, tmp, buf, buf );
+//	printf("encrypt txt=", tmp, buf, buf);
+//	for(i=0; i<8; i++) printf("%x ", buf[i]); 
+//	printf("\n");
+//
+//	memset(tmp, 0, sizeof(tmp)); strcpy((char*)tmp, "01234567abcdefgh");
+//	des3_set3key_dec(&des3, tmp);
+//	des3_crypt_cbc(&des3, DES_DECRYPT, 8, tmp, buf, buf );
+//	printf("decrypt txt=");
+//	for(i=0; i<8; i++) printf("%x ", buf[i]); 
+//	printf("\n");
+//
+//	system("pause");
+//}
+
+void DES_EncryptFile(IN LPCTSTR lpFile, IN LPBYTE lpKey, IN LPBYTE lpVI, IN LPCTSTR lpEncryFile)
+{
+	if ( lpFile == NULL )
+		return;
+
+	if ( lpKey == NULL || lpVI == NULL )
+		return;
+
+	INT nKeyLen = strlen((char*)lpKey);
+	if (nKeyLen != 8 )
+		return;
+
+	INT nVILen = strlen((char*)lpVI);
+	if ( nVILen != 8 ) 
+		return;
+
+	CFile cf;
+	BYTE *pFileData = NULL;
+	BYTE *pOutData = NULL;
+	INT nPadLen = 0;
+	ULONGLONG nFileLen = 0;
+	ULONGLONG nOutLen = 0;
+	if ( cf.Open(lpFile, CFile::modeRead) )
+	{
+		nFileLen = cf.GetLength();
+		nOutLen = des_enc_len(nFileLen);
+
+		pFileData = new BYTE[nOutLen];
+		memset(pFileData, 0, nOutLen);
+
+		cf.Read(pFileData,nFileLen);
+		cf.Close();
+	}
+
+	pOutData = new BYTE[nOutLen + 1];
+	memset(pOutData, 0, nOutLen + 1);
+
+	des_context des;
+	if ( des_key_check_key_parity(lpKey) == 1)
+	{
+		printf("key was not correct\n");
+		des_key_set_parity(lpKey);
+		if ( des_key_check_key_parity(lpKey) == 0 )
+		{
+			des_setkey_enc(&des, lpKey);
+		}
+	}
+	else
+		des_setkey_enc(&des, lpKey);
+
+	des_crypt_cbc(&des, DES_ENCRYPT, nOutLen, lpVI, pFileData, pOutData);
+
+	CFile cfo;
+	if ( cfo.Open(lpEncryFile, CFile::modeCreate|CFile::modeWrite) )
+	{
+		cfo.Write(pOutData, nOutLen);
+		cfo.Close();
+	}
+
+	if ( pOutData )
+		delete []pOutData;
+}
+
+void DES_DecryptFile(IN LPCTSTR lpFile, IN LPBYTE lpKey, IN LPBYTE lpVI, IN LPCTSTR lpDecryFile)
+{
+	if ( lpFile == NULL )
+		return;
+
+	if ( lpKey == NULL || lpVI == NULL )
+		return;
+
+	INT nKeyLen = strlen((char*)lpKey);
+	if (nKeyLen != 8 )
+		return;
+
+	INT nVILen = strlen((char*)lpVI);
+	if ( nVILen != 8 ) 
+		return;
+
+	CFile cf;
+	BYTE *pFileData = NULL;
+	BYTE *pOutData = NULL;
+	UINT64 nFileLen = 0;
+	if ( cf.Open(lpFile, CFile::modeRead) )
+	{
+		nFileLen = cf.GetLength();
+		pFileData = new BYTE[nFileLen];
+		memset(pFileData, 0, nFileLen);
+
+		cf.Read(pFileData,nFileLen);
+		cf.Close();
+	}
+
+	// nFileLen 是否是8的整数倍,不是则加满;
+	UINT64 nOutLen = nFileLen;
+	pOutData = new BYTE[nOutLen + 1];
+	memset(pOutData, 0, nOutLen + 1);
+
+	des_context des;
+	if ( des_key_check_key_parity(lpKey) == 1)
+	{
+		printf("key was not correct\n");
+		des_key_set_parity(lpKey);
+		if ( des_key_check_key_parity(lpKey) == 0 )
+		{
+			des_setkey_dec(&des, lpKey);
+		}
+	}
+	else
+		des_setkey_dec(&des, lpKey);
+	des_crypt_cbc(&des, DES_DECRYPT, nOutLen, lpVI, pFileData, pOutData);
+	// 解密后,要去除填充的字符;
+	/*while ( pOutData[nOutLen-1] == 0x00 )
+	{
+		nOutLen--;
+	}*/
+	nOutLen = des_dec_len(pOutData,nOutLen);
+
+	CFile cfo;
+	if ( cfo.Open(lpDecryFile, CFile::modeCreate|CFile::modeWrite) )
+	{
+		cfo.Write(pOutData, nOutLen);
+		cfo.Close();
+	}
+
+	if ( pOutData )
+		delete []pOutData;
+}
+
+
+CWinApp theApp;
+
+using namespace std;
+
+//#include "md5和sha1.h"
+#include "sha1.h"
+
+#include <list>
+using namespace std;
+
+int cmp(const void* a, const void* b){
+	return *(int*)a - *(int*)b;
+}
+
+inline void println(int arr[], int len){
+	for(int i = 0; i < len; i++){
+		cout << arr[i] << " ";
+	}
+	//cout << endl;
+}
+
+inline void reverse(int arr[], int left, int right){
+	while(right >= left){
+		swap(arr[left++], arr[right--]);
+	}
+}
+
+void full_permutation(int arr[], int len){
+	qsort(arr, len, sizeof(int), cmp);
+	println(arr, len);
+	while(true){
+		int j = len-1;
+		int t = len;
+		while(j >= 0 && arr[--j] >= arr[j+1]) ;
+		if(j >= 0){
+			while(arr[--t] <= arr[j]) ;
+			swap(arr[t], arr[j]);
+			reverse(arr, j+1, len-1);
+			println(arr, len);
+		}
+		else{
+			break;
+		}
+	}
+}
+
+// 冒泡排序;
+void BubbleSort(string *s, int count)  
+{  
+	string temp;  
+	for (int i = 1; i < count; i++)  
+	{  
+		for (int j = count - 1; j >= i; j--)  
+		{  
+			if (s[j].compare(s[j - 1]) < 0)  
+			{  
+				temp = s[j - 1];  
+				s[j - 1] = s[j];  
+				s[j] = temp;  
+			}  
+		}   
+	}  
+} 
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+	int nRetCode = 0;
+
+	// 初始化 MFC 并在失败时显示错误
+	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+	{
+		// TODO: 更改错误代码以符合您的需要
+		_tprintf(_T("错误: MFC 初始化失败\n"));
+		nRetCode = 1;
+	}
+	else
+	{
+#if 0
+		char sz[3] = {0};
+		BYTE by = 0xff;
+		ByteTurn2HexChar(by, sz);
+
+		string ss[3] = {"J8UcPVTTxPqZYRw2ZmVEznX6j","201607111759111","lyfz.net"};
+		BubbleSort(ss,3);
+
+		string sAll;
+		for ( int i = 0; i < 3; i++ )
+		{
+			sAll.append(ss[i]);
+		}
+
+		BYTE szSource[560] = "lyfz.net";
+		BYTE byResult[21] = {0};
+		BYTE byHexResult[250] = {0};
+
+		memset(szSource, 0, 560);
+		memcpy(szSource, sAll.c_str(), sAll.size());
+
+		sha1(szSource, sAll.size(), byResult);
+		ByteToTwoByte(byResult, 20, byHexResult);
+
+		sha1Hex(szSource, sAll.size(), byHexResult);
+		
+		sha1(szSource, strlen((char*)szSource), byResult);
+		sha1Hex(szSource, strlen((char*)szSource), byHexResult);
+
+		printf("原始加密:%s\n 16进制加密:%s\n", byResult, byHexResult);
+
+		system("pause");
+#endif
+
+#if 1
+		CONST TCHAR* pMD5 = NULL;
+		// TODO: 在此处为应用程序的行为编写代码。
+		printf("示例:MD5加密'订单1234', 结果如下:\n");
+
+		// 读取文件大小;
+		CStringA strpath = "D:\\0.dat";
+		struct stat statbuf;
+		stat(strpath.GetString(), &statbuf);
+		BYTE *pFileData = new BYTE[statbuf.st_size + 1];
+		memset(pFileData, 0, statbuf.st_size);
+
+		// 读取文件内容;
+#if 0
+		FILE *f = NULL;
+		fopen_s(&f,strpath, "r+");
+		if ( f != NULL )
+		{
+			fread_s(pFileData, statbuf.st_size, sizeof(BYTE), statbuf.st_size, f);
+			fclose(f);
+		}
+		else
+		{
+			return -1;
+		}
+#else
+		CFile cf;
+		if ( cf.Open(strpath, CFile::modeRead) )
+		{
+			//DWORD dwlen = cf.GetLength();
+			//if ( dwlen == statbuf.st_size )
+			//{
+			//	TRACE("dfdfdfd");
+			//}
+			cf.Read(pFileData, statbuf.st_size);
+
+		}
+#endif
+
+		CHAR *pUTF8 = new CHAR[statbuf.st_size+1];
+		StringProcess::ascii_to_utf8((const char*)pFileData, pUTF8);
+
+		CMD5 mdd5(pFileData, statbuf.st_size);
+		pMD5 = mdd5.GetMD5Digest();
+
+		mdd5.SetBYTEText(reinterpret_cast<BYTE*>(pUTF8), strlen(pUTF8));
+		pMD5 = mdd5.GetMD5Digest();
+		
+		
+		// 默认GB2321的md5值;
+		CMD5 md5((const BYTE*)("AT中国123"), strlen("AT中国123"));
+		pMD5 = md5.GetMD5Digest();
+		_tprintf(_T("GB2321\t\t:%s\n"), pMD5);
+
+		// 获取utf8的md5值;
+		CHAR szUtf8[MAX_PATH] = {0};
+		CHAR szbuffer[MAX_PATH] = "AT中国123";
+		StringProcess::ascii_to_utf8(szbuffer,szUtf8);
+		md5.SetBYTEText(reinterpret_cast<BYTE*>(szUtf8), strlen(szUtf8));
+		pMD5 = md5.GetMD5Digest();
+		_tprintf(_T("utf8\t\t:%s\n"), pMD5);
+
+		// 获取unicode的md5值;
+		WCHAR szUnicode[MAX_PATH] = L"AT中国123";
+		BYTE szUN[MAX_PATH] = {0};
+		INT nBytes = sizeof(WCHAR)*wcslen(szUnicode);
+		memcpy(szUN, szUnicode, nBytes);
+		//INT nChars = strlen((char*)szUN);
+		md5.SetBYTEText(reinterpret_cast<BYTE*>(szUN), nBytes);
+		pMD5 = md5.GetMD5Digest();
+		_tprintf(_T("unicode\t\t:%s\n"), pMD5);
+
+		// 获取ascii的md5值;
+		CHAR szAscii[MAX_PATH] = {0};
+		StringProcess::utf8_to_ascii(szUtf8,szAscii);
+		md5.SetBYTEText(reinterpret_cast<BYTE*>(szAscii), strlen(szAscii));
+		pMD5 = md5.GetMD5Digest();
+		_tprintf(_T("ascii\t\t:%s\n"), pMD5);
+#endif
+
+#if 0 // 测试Base64类的有效性;
+
+		Test_CreateBase64File(_T("D:\\dindansp2.txt"), _T("D:\\base64.txt"));
+		Test_CreateBindFile(_T("D:\\base64.txt"), _T("D:\\binary.txt"));
+		
+		WCHAR szString[MAX_PATH] = L"11寸水晶";
+		CHAR *pBase64 = NULL;
+		INT nBase64Len = Test_Bin2Base64_WChar(szString, _tcslen(szString)*sizeof(WCHAR), &pBase64);
+		
+		WCHAR szWBase64[MAX_PATH] = {0};
+		Test_Base642Bin_WChar(pBase64, nBase64Len, szWBase64, MAX_PATH);
+
+		if ( pBase64 )
+			delete []pBase64;
+		pBase64 = NULL;
+
+
+#endif
+
+#if 0
+		Test_Aes_Encryptfile_CTR(_T("F:\\刻录驱动.rar"), "A012369DFEROE.LKDJFOI*&^%$!@_+~!", _T("D:\\Aes_ke.txt"));
+		Test_CreateBase64File(_T("D:\\Aes_ke.txt"), _T("D:\\base64_ke.txt"));
+		Test_CreateBindFile(_T("D:\\base64_ke.txt"), _T("D:\\binary_ke.txt"));
+		Test_Aes_Decryptfile_CTR(_T("D:\\binary_ke.txt"), "A012369DFEROE.LKDJFOI*&^%$!@_+~!", _T("D:\\刻录驱动.rar"));
+#endif
+
+#if 0
+	// 方八水立方册;ecnrptyIyFsVC3Y65L3qv+jvdrH
+	CHAR szExample[MAX_PATH] = "方10公主梦幻册";
+	CHAR szUTF8[MAX_PATH] = {0};
+	StringProcess::ascii_to_utf8(szExample,szUTF8);
+	
+
+	CHAR szBase64[MAX_PATH] = "pagFVaDD8KfR24+mq4k=";
+	CHAR szBinary[MAX_PATH] = {0};
+	Test_Base642Bin_ASCII(szBase64, strlen(szBase64), szBinary, MAX_PATH);
+
+	StringProcess::utf8_to_ascii(szUTF8, szExample);
+	StringProcess::utf8_to_ascii(szBinary, szExample);
+
+	system("pause");
+#endif
+
+#if 0
+	CHAR szCounter[16] = {0};
+	szCounter[7] = 113;
+	szCounter[15] = -25;
+	Test_Aes_Decryptfile_Others("加拿大记者借“人权”问题发难 王毅怒斥:傲慢与偏见", "ABCD0123456789EF", NULL);
+	printf("\n\n\n使用计数器");// 证实计数器只对CTR模式有用;
+	Test_Aes_Decryptfile_Others("加拿大记者借“人权”问题发难 王毅怒斥:傲慢与偏见", "ABCD0123456789EF", szCounter);
+#endif
+
+
+#if 0
+	//DES();
+	BYTE szKey[MAX_PATH] = "lyfz.net";
+	BYTE szVI[MAX_PATH] = "WorkbyIT";
+	DES_EncryptFile(_T("E:\\dindansp.txt"), szKey, szVI, _T("E:\\out.txt"));
+	sprintf((char*)szVI, "%s", "WorkbyIT");
+	DES_DecryptFile(_T("E:\\out.txt"), szKey, szVI, _T("E:\\Decout.txt"));
+#endif
+
+#if 1
+	// N/jZ0RbjHYc=
+	BYTE szKey[MAX_PATH] = "mygz/ndu";
+	BYTE szVI[MAX_PATH] = "WorkbyIT";
+
+	CHAR szBinary[MAX_PATH] = {0};
+	CHAR szBase64[MAX_PATH] = "tO/cYVBbZ3vwZAJ8WQAgdQWLGyycqETbJDc7xB0xZKgK0Ps2noivrY/jhKTdevxI";//ALRJrTZYzN0
+
+	// 解密回二进制;
+	INT nReal = Test_Base642Bin_ASCII(szBase64, strlen(szBase64), szBinary, MAX_PATH);
+
+	// 解密;
+	des_context des;
+	if ( des_key_check_key_parity(szKey) == 1)
+	{
+		printf("key was not correct\n");
+		des_key_set_parity(szKey);
+		if ( des_key_check_key_parity(szKey) == 0 )
+		{
+			des_setkey_dec(&des, szKey);
+		}
+	}
+	else
+		des_setkey_dec(&des, szKey);
+
+	CHAR szDesDec[MAX_PATH] = {0};
+	INT nInputlen = strlen(szBinary);
+	des_crypt_cbc(&des, DES_DECRYPT, nReal, szVI, (const unsigned char*)szBinary, (unsigned char*)szDesDec);
+	// 解密后,要去除填充的字符;
+	while ( szDesDec[nInputlen-1] == 0x00 )
+	{
+		nInputlen--;
+	}
+	
+#endif
+
+#if 0
+	// N/jZ0RbjHYc=
+	BYTE szKey[MAX_PATH] = "mygz/ndu";
+	BYTE szVI[MAX_PATH] = "WorkbyIT";
+	
+	CFile cf;
+	if ( cf.Open(_T("input.txt"), CFile::modeRead) )
+	{
+		DWORD dwlength = cf.GetLength();
+		BYTE *pData = new BYTE[dwlength +1];
+		memset(pData, 0, dwlength + 1);
+
+		cf.Read(pData, dwlength);
+
+		// 解密回二进制;
+		INT nByteLen = CBase64::CalcBinLen(dwlength);
+		BYTE *pBinary = new BYTE[nByteLen+1];
+		memset(pBinary, 0, nByteLen+1);
+		Test_Base642Bin_ASCII((char*)pData, dwlength, (char*)pBinary, MAX_PATH);
+		cf.Close();
+
+		CFile ccf;
+		if ( ccf.Open(_T("output.txt"), CFile::modeCreate|CFile::modeReadWrite) )
+		{
+			ccf.Write(pBinary, nByteLen);
+			ccf.Close();
+		}
+	}
+
+	//DES_DecryptFile(_T("output.txt"), szKey, szVI, _T("decout.txt"));
+	sprintf((char*)szVI, "%s", "WorkbyIT");
+	DES_DecryptFile(_T("output.txt"), szKey, szVI, _T("decout.txt"));
+#endif
+
+	system("pause");
+	}
+
+	return nRetCode;
+}

+ 3 - 0
MD5Test/MD5Test.h

@@ -0,0 +1,3 @@
+#pragma once
+
+#include "resource.h"

+ 69 - 0
MD5Test/MD5Test.rc

@@ -0,0 +1,69 @@
+//Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#include "afxres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+   IDS_APP_TITLE       "MD5Test"
+END
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#ifndef _AFXDLL
+#include "l.CHS\\afxres.rc"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED

+ 20 - 0
MD5Test/MD5Test.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MD5Test", "MD5Test.vcproj", "{E6CB5BB6-77C2-4F01-89E3-93553936CC96}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E6CB5BB6-77C2-4F01-89E3-93553936CC96}.Debug|Win32.ActiveCfg = Debug|Win32
+		{E6CB5BB6-77C2-4F01-89E3-93553936CC96}.Debug|Win32.Build.0 = Debug|Win32
+		{E6CB5BB6-77C2-4F01-89E3-93553936CC96}.Release|Win32.ActiveCfg = Release|Win32
+		{E6CB5BB6-77C2-4F01-89E3-93553936CC96}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 303 - 0
MD5Test/MD5Test.vcproj

@@ -0,0 +1,303 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="MD5Test"
+	ProjectGUID="{E6CB5BB6-77C2-4F01-89E3-93553936CC96}"
+	RootNamespace="MD5Test"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;CIPHER_MODE_CBC;POLARSSL_SELF_TEST"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="源文件"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\3DES.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\AesCipher.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Base64.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\des.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\lzari.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\md5.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MD5Test.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\StringProcess.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="头文件"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\3DES.h"
+				>
+			</File>
+			<File
+				RelativePath=".\AesCipher.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Base64.h"
+				>
+			</File>
+			<File
+				RelativePath=".\des.h"
+				>
+			</File>
+			<File
+				RelativePath=".\lzari.h"
+				>
+			</File>
+			<File
+				RelativePath=".\md5.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MD5Test.h"
+				>
+			</File>
+			<File
+				RelativePath=".\md5和sha1.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sha1.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\StringProcess.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="资源文件"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\MD5Test.rc"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 40 - 0
MD5Test/ReadMe.txt

@@ -0,0 +1,40 @@
+========================================================================
+    控制台应用程序:MD5Test 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 MD5Test 应用程序。
+
+本文件概要介绍组成 MD5Test 应用程序的
+的每个文件的内容。
+
+
+MD5Test.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+MD5Test.cpp
+    这是主应用程序源文件。
+
+/////////////////////////////////////////////////////////////////////////////
+应用程序向导创建了下列资源:
+
+MD5Test.rc
+这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。
+此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 MD5Test.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 17 - 0
MD5Test/Resource.h

@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MD5Test.rc
+//
+
+#define IDS_APP_TITLE			103
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE	101
+#define _APS_NEXT_COMMAND_VALUE		40001
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		101
+#endif
+#endif

+ 645 - 0
MD5Test/StringProcess.cpp

@@ -0,0 +1,645 @@
+#include "StdAfx.h"
+#include "StringProcess.h"
+#include <strsafe.h>
+namespace StringProcess
+{
+	/************************************************************************/
+	/*
+	函数: utf82unicode
+	描述: utf8字符串转为unicode字符串;
+	参数:
+	pszutf8 utf8字符串;
+	返回: unicode字符串;
+	注意: 返回的指针所指向的内存需要释放;
+	*/
+	/************************************************************************/
+	WCHAR* utf8_to_unicode(IN const char *pszutf8)
+	{
+		int wnSize = MultiByteToWideChar(CP_UTF8, 0, pszutf8, -1, NULL, 0);
+		if (wnSize == ERROR_NO_UNICODE_TRANSLATION)
+		{
+			//throw std::exception("Invalide UTF-8 sequence");
+			return NULL;
+		}
+
+		if (wnSize == 0)
+		{
+			//throw std::exception("Error in conversion");
+			return NULL;
+		}
+
+		WCHAR *pwResult = new WCHAR[wnSize];
+		int nConvertSize = MultiByteToWideChar(CP_UTF8, 0, pszutf8, -1, pwResult, wnSize);
+		if (nConvertSize != wnSize)
+		{
+			//throw std::exception("la falla");
+			if (pwResult)
+				delete []pwResult;
+			return NULL;
+		}
+
+		return pwResult;
+	}
+
+	/************************************************************************/
+	/*
+	函数: utf82unicode
+	描述: utf8字符串转为unicode字符串;
+	参数:
+	pszutf8 utf8字符串;
+	pszunicode 返回的unicode字符串;
+	返回: unicode字符串大小;
+	*/
+	/************************************************************************/
+	int utf8_to_unicode(IN const char *pszutf8, IN OUT WCHAR *pszunicode)
+	{
+		int wnSize = MultiByteToWideChar(CP_UTF8, 0, pszutf8, -1, NULL, 0);
+		if (wnSize == ERROR_NO_UNICODE_TRANSLATION)
+		{
+			//throw std::exception("Invalide UTF-8 sequence");
+			return 0;
+		}
+
+		if (wnSize == 0)
+		{
+			//throw std::exception("Error in conversion");
+			return 0;
+		}
+
+		int nConvertSize = MultiByteToWideChar(CP_UTF8, 0, pszutf8, -1, pszunicode, wnSize);
+		if (nConvertSize != wnSize)
+		{
+			//throw std::exception("la falla");
+			return 0;
+		}
+
+		return wnSize;
+	}
+
+	/************************************************************************/
+	/*
+	函数: utf82ascii
+	描述: 将utf8字符串转为ascii字符串;
+	参数:
+	pszutf8 utf8字符串;
+
+	返回: ascii字符串;
+	注意: 返回的指针需要手动释放所指内存;
+	*/
+	/************************************************************************/
+	CHAR* utf8_to_ascii(const CHAR *pszutf8)
+	{
+		// 先把 utf8 转为 unicode ;
+		WCHAR *pwstr = utf8_to_unicode(pszutf8);
+
+		// 最后把 unicode 转为 ascii ;
+		CHAR *pacsii = NULL;
+		if (pwstr)
+			pacsii = unicode_to_ascii(pwstr);
+
+		if (pwstr)
+			delete []pwstr;
+
+		return pacsii;
+	}
+
+	/************************************************************************/
+	/*
+	函数: utf82ascii
+	描述: 将utf8字符串转为ascii字符串;
+	参数:
+	pszutf8 utf8字符串;
+
+	返回: ascii字符串;
+	注意: 返回的指针需要手动释放所指内存;
+	*/
+	/************************************************************************/
+	int utf8_to_ascii(IN const CHAR *pszutf8, IN OUT CHAR* pszacsii)
+	{
+		// 先把 utf8 转为 unicode ;
+		WCHAR *pwstr = utf8_to_unicode(pszutf8);
+
+		// 最后把 unicode 转为 ascii ;
+		int nascii = 0;
+		if (pwstr)
+			nascii = unicode_to_ascii(pwstr, pszacsii);
+
+		if (pwstr)
+			delete []pwstr;
+
+		return nascii;
+	}
+
+	/************************************************************************/
+	/*
+	函数: unicode2acsii
+	描述: unicode字符串转为acsii字符串;
+	参数:
+	pszunicode unicode字符串;
+	返回: acsii字符串;
+	注意: 返回的指针所指向的内存需要释放;
+	*/
+	/************************************************************************/
+	CHAR* unicode_to_ascii(IN const WCHAR *pszunicode)
+	{
+		int asciisize = WideCharToMultiByte(CP_OEMCP, 0, pszunicode, -1, NULL, 0, NULL, NULL);
+		if (asciisize == ERROR_NO_UNICODE_TRANSLATION)
+		{
+			//throw std::exception("Invalid UTF-8 sequence."); 
+			return NULL;
+		}
+		if (asciisize == 0)
+		{
+			//throw std::exception("Error in conversion."); 
+			return NULL;
+		}
+
+		CHAR *pAscii = new CHAR[asciisize];
+		int convresult = WideCharToMultiByte(CP_OEMCP, 0, pszunicode, -1, pAscii, asciisize, NULL, NULL);
+		if (convresult != asciisize)
+		{
+			//throw std::exception("La falla!"); 
+			if (pAscii) delete []pAscii;
+			return NULL;
+		}
+
+		return pAscii;
+	}
+
+	/************************************************************************/
+	/*
+	函数: unicode2acsii
+	描述: unicode字符串转为acsii字符串;
+	参数:
+	pszunicode unicode字符串;
+	pszacsii   返回的acsii字符串;
+	返回: acsii字符串大小;
+	*/
+	/************************************************************************/
+	int unicode_to_ascii(IN const WCHAR *pszunicode, IN OUT CHAR *pszacsii)
+	{
+		int asciisize = WideCharToMultiByte(CP_OEMCP, 0, pszunicode, -1, NULL, 0, NULL, NULL);
+		if (asciisize == ERROR_NO_UNICODE_TRANSLATION)
+		{
+			//throw std::exception("Invalid UTF-8 sequence."); 
+			return 0;
+		}
+
+		if (asciisize == 0)
+		{
+			//throw std::exception("Error in conversion."); 
+			return 0;
+		}
+
+		int convresult = WideCharToMultiByte(CP_OEMCP, 0, pszunicode, -1, pszacsii, asciisize, NULL, NULL);
+		if (convresult != asciisize)
+		{
+			//throw std::exception("La falla!"); 
+			return 0;
+		}
+
+		return asciisize;
+	}
+
+	/************************************************************************/
+	/*
+	函数: unicode2uft8
+	描述: 将unicode字符串转为utf8字符串;
+	参数:
+	pszunicode unicode字符串;
+
+	返回: utf8字符串;
+	注意: 返回的指针需要手动释放所指内存;
+	*/
+	/************************************************************************/
+	CHAR* unicode_to_uft8(IN const WCHAR *pszunicode)
+	{
+		int utf8size = WideCharToMultiByte(CP_UTF8, 0, pszunicode, -1, NULL, 0, NULL, NULL);
+		if (utf8size == 0)
+		{
+			//throw std::exception("Error in conversion."); 
+			return NULL;
+		}
+
+		CHAR* putf8 = new CHAR[utf8size];
+		int convresult = WideCharToMultiByte(CP_UTF8, 0, pszunicode, -1, putf8, utf8size, NULL, NULL);
+		if (convresult != utf8size)
+		{
+			//throw std::exception("La falla!"); 
+			if (putf8)delete []putf8;
+			return NULL;
+		}
+
+		return putf8;
+	}
+
+	/************************************************************************/
+	/*
+	函数: unicode2uft8
+	描述: 将unicode字符串转为utf8字符串;
+	参数:
+	pszunicode unicode字符串;
+	pszutf8 返回的utf8字符串;
+
+	返回: utf8字符串大小;
+	*/
+	/************************************************************************/
+	int unicode_to_uft8(IN const WCHAR *pszunicode, IN OUT CHAR* pszutf8)
+	{
+		int utf8size = WideCharToMultiByte(CP_UTF8, 0, pszunicode, -1, NULL, 0, NULL, NULL);
+		if (utf8size == 0)
+		{
+			//throw std::exception("Error in conversion."); 
+			return 0;
+		}
+
+		int convresult = WideCharToMultiByte(CP_UTF8, 0, pszunicode, -1, pszutf8, utf8size, NULL, NULL);
+		if (convresult != utf8size)
+		{
+			//throw std::exception("La falla!"); 
+			return 0;
+		}
+
+		return utf8size;
+	}
+
+	/************************************************************************/
+	/*
+	函数: ascii2unicode
+	描述: 将ascii字符串转为unicode字符串;
+	参数:
+	pszascii  ascii字符串;
+
+	返回: unicode字符串;
+	注意: 返回的指针需要手动释放其所指的内存;
+	*/
+	/************************************************************************/
+	WCHAR* ascii_to_unicode(IN const CHAR* pszascii)
+	{
+		int wSize = MultiByteToWideChar(CP_ACP, 0, pszascii, -1, NULL, 0);
+		if (wSize == ERROR_NO_UNICODE_TRANSLATION)
+		{
+			//throw std::exception("Invalid UTF-8 sequence."); 
+			return NULL;
+		}
+
+		if (wSize == 0)
+		{
+			//throw std::exception("Error in conversion."); 
+			return NULL;
+		}
+
+		WCHAR *punicode = new WCHAR[wSize];
+		int convresult = MultiByteToWideChar(CP_ACP, 0, pszascii, -1, punicode, wSize);
+		if (convresult != wSize)
+		{
+			//throw std::exception("La falla!"); 
+			if (punicode) delete []punicode;
+			return NULL;
+		}
+
+		return punicode;
+	}
+
+	/************************************************************************/
+	/*
+	函数: ascii2unicode
+	描述: 将ascii字符串转为unicode字符串;
+	参数:
+	pszascii  ascii字符串;
+
+	返回: unicode字符串;
+	注意: 返回的指针需要手动释放其所指的内存;
+	*/
+	/************************************************************************/
+	int ascii_to_unicode(IN const CHAR* pszascii, IN OUT WCHAR *pszunicode)
+	{
+		int wSize = MultiByteToWideChar(CP_ACP, 0, pszascii, -1, NULL, 0);
+		if (wSize == ERROR_NO_UNICODE_TRANSLATION)
+		{
+			//throw std::exception("Invalid UTF-8 sequence."); 
+			return 0;
+		}
+
+		if (wSize == 0)
+		{
+			//throw std::exception("Error in conversion.");
+			return 0;
+		}
+
+		int convresult = MultiByteToWideChar(CP_ACP, 0, pszascii, -1, pszunicode, wSize);
+		if (convresult != wSize)
+		{
+			//throw std::exception("La falla!"); 
+			return 0;
+		}
+
+		return wSize;
+	}
+
+	/************************************************************************/
+	/*
+	函数: ascii2utf8
+	描述: 将ascii字符串转为utf8字符串;
+	参数:
+	pszascii  ascii字符串;
+
+	返回: uft8字符串;
+	注意: 返回的指针需要手动释放其所指的内存;
+	*/
+	/************************************************************************/
+	CHAR* ascii_to_utf8(IN const CHAR* pszascii)
+	{
+		// 先把 ascii 转为 unicode ;
+		WCHAR *pwstr = ascii_to_unicode(pszascii);
+
+		// 最后把 unicode 转为 utf8 ;
+		CHAR* putf8 = NULL;
+		if (pwstr)
+			putf8 = unicode_to_uft8(pwstr);
+
+		if (pwstr)
+			delete []pwstr;
+
+		return putf8;
+	}
+
+	/************************************************************************/
+	/*
+	函数: ascii2utf8
+	描述: 将ascii字符串转为utf8字符串;
+	参数:
+	pszascii  ascii字符串;
+
+	返回: uft8字符串;
+	注意: 返回的指针需要手动释放其所指的内存;
+	*/
+	/************************************************************************/
+	int ascii_to_utf8(IN const CHAR* pszascii, IN OUT CHAR* pszutf8)
+	{
+		// 先把 ascii 转为 unicode ;
+		WCHAR *pwstr = ascii_to_unicode(pszascii);
+
+		// 最后把 unicode 转为 utf8 ;
+		int nSize = 0;
+		if (pwstr)
+			nSize = unicode_to_uft8(pwstr, pszutf8);
+
+		if (pwstr)
+			delete []pwstr;
+
+		return nSize;
+	}
+
+	//////////////////////////////////////////////////////////////////////////
+	void Gb2312ToUnicode(WCHAR* pOut, char *gbBuffer)
+	{
+		::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbBuffer, 2, pOut, 1);
+		return;
+	}
+
+	//-------------------------------------------------------------
+	// 函数:UTF_8ToUnicode
+	// 描述:把3个uft-8中文字符转为单个unicode字符;
+	// 参数:
+	//		pOut[IN OUT]: 返回的unicode字符;
+	//		pText[IN]:	uft-8字符;
+	// 返回:null;
+	//-------------------------------------------------------------
+	void UTF_8ToUnicode(WCHAR* pOut, char *pText)
+	{
+		char* uchar = (char *)pOut;
+
+		uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
+		uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
+
+		return;
+	}
+
+	//-------------------------------------------------------------
+	// 函数:UnicodeToUTF_8
+	// 描述:把单个unicode字符转为3个uft-8中文字符;
+	// 参数:
+	//		pOut[IN OUT]: 返回的unicode字符;
+	//		pText[IN]:	uft-8字符;
+	// 返回:null;
+	//-------------------------------------------------------------
+	void UnicodeToUTF_8(char* pOut, WCHAR* pText)
+	{
+		// 注意 WCHAR高低字的顺序,低字节在前,高字节在后
+		char* pchar = (char *)pText;
+
+		pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
+		pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
+		pOut[2] = (0x80 | (pchar[0] & 0x3F));
+
+		return;
+	}
+
+	void UnicodeToGB2312(char* pOut, WCHAR uData)
+	{
+		WideCharToMultiByte(CP_ACP, NULL, &uData, 1, pOut, sizeof(WCHAR), NULL, NULL);
+		return;
+	}
+
+	//做为解Url使用
+	char CharToInt(char ch)
+	{
+		if (ch >= '0' && ch <= '9')return (char)(ch - '0');
+		if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
+		if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
+		return -1;
+	}
+
+	char StrToBin(char *str)
+	{
+		char tempWord[2];
+		char chn;
+
+		tempWord[0] = CharToInt(str[0]);                         //make the B to 11 -- 00001011
+		tempWord[1] = CharToInt(str[1]);                         //make the 0 to 0  -- 00000000
+
+		chn = (tempWord[0] << 4) | tempWord[1];                //to change the BO to 10110000
+
+		return chn;
+	}
+
+	//UTF_8 转gb2312
+	void UTF_8ToGB2312(string &pOut, char *pText, int pLen)
+	{
+		char buf[4];
+		char* rst = new char[pLen + (pLen >> 2) + 2];
+		memset(buf, 0, 4);
+		memset(rst, 0, pLen + (pLen >> 2) + 2);
+
+		int i = 0;
+		int j = 0;
+
+		while (i < pLen)
+		{
+			if (*(pText + i) >= 0)
+			{
+				rst[j++] = pText[i++];
+			}
+			else
+			{
+				WCHAR Wtemp;
+				UTF_8ToUnicode(&Wtemp, pText + i);
+				UnicodeToGB2312(buf, Wtemp);
+
+				unsigned short int tmp = 0;
+				tmp = rst[j] = buf[0];
+				tmp = rst[j + 1] = buf[1];
+				tmp = rst[j + 2] = buf[2];
+
+				//newBuf[j] = Ctemp[0];
+				//newBuf[j + 1] = Ctemp[1];
+
+				i += 3;
+				j += 2;
+			}
+		}
+
+		if (i == 0)
+			rst[j] = '/0';
+		pOut = rst;
+		delete[]rst;
+	}
+
+	//GB2312 转为 UTF-8
+	void GB2312ToUTF_8(string& pOut, char *pText, int pLen)
+	{
+		char buf[4];
+		memset(buf, 0, 4);
+
+		pOut.clear();
+
+		int i = 0;
+		while (i < pLen)
+		{
+			//如果是英文直接复制就可以
+			if (pText[i] >= 0)
+			{
+				char asciistr[2] = { 0 };
+				asciistr[0] = (pText[i++]);
+				pOut.append(asciistr);
+			}
+			else
+			{
+				WCHAR pbuffer;
+				Gb2312ToUnicode(&pbuffer, pText + i);
+				UnicodeToUTF_8(buf, &pbuffer);
+				pOut.append(buf);
+				i += 2;
+			}
+		}
+
+		return;
+	}
+
+	//把str编码为网页中的 GB2312 url encode ,英文不变,汉字双字节  如%3D%AE%88
+	string UrlGB2312(char * str)
+	{
+		string dd;
+		size_t len = strlen(str);
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)str[i]))
+			{
+				char tempbuff[2];
+				//sprintf(tempbuff,"%c",str[i]);
+				//sprintf_s(tempbuff, "%c", str[i]);
+				StringCchPrintfA(tempbuff, 2, "%s",str[i]);
+				dd.append(tempbuff);
+			}
+			else if (isspace((BYTE)str[i]))
+			{
+				dd.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				//sprintf(tempbuff,"%%%X%X",((BYTE*)str)[i] >>4,((BYTE*)str)[i] %16);
+				//sprintf_s(tempbuff, "%%%X%X", ((BYTE*)str)[i] >> 4, ((BYTE*)str)[i] % 16);
+				StringCchPrintfA(tempbuff, 4, "%%%X%X", ((BYTE*)str)[i] >> 4, ((BYTE*)str)[i] % 16);
+				dd.append(tempbuff);
+			}
+		}
+		return dd;
+	}
+
+	//把str编码为网页中的 UTF-8 url encode ,英文不变,汉字三字节  如%3D%AE%88
+	string UrlUTF8(char * str)
+	{
+		string tt;
+		string dd;
+		GB2312ToUTF_8(tt, str, (int)strlen(str));
+
+		size_t len = tt.length();
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)tt.at(i)))
+			{
+				char tempbuff[2] = { 0 };
+				//sprintf(tempbuff,"%c",(BYTE)tt.at(i));
+				//sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+				StringCchPrintfA(tempbuff, 2, "%c", (BYTE)tt.at(i));
+				dd.append(tempbuff);
+			}
+			else if (isspace((BYTE)tt.at(i)))
+			{
+				dd.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				//sprintf(tempbuff,"%%%X%X",((BYTE)tt.at(i)) >>4,((BYTE)tt.at(i)) %16);
+				//sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				StringCchPrintfA(tempbuff, 4, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				dd.append(tempbuff);
+			}
+		}
+		return dd;
+	}
+
+	//把url GB2312解码
+	string UrlGB2312Decode(string str)
+	{
+		string output = "";
+		char tmp[2];
+		int i = 0, idx = 0, len = str.length();
+
+		while (i < len){
+			if (str[i] == '%')
+			{
+				tmp[0] = str[i + 1];
+				tmp[1] = str[i + 2];
+				output += StrToBin(tmp);
+				i = i + 3;
+			}
+			else if (str[i] == '+')
+			{
+				output += ' ';
+				i++;
+			}
+			else{
+				output += str[i];
+				i++;
+			}
+		}
+
+		return output;
+	}
+
+	//把url utf8解码
+	string UrlUTF8Decode(string str)
+	{
+		string output = "";
+
+		string temp = UrlGB2312Decode(str);//
+
+		UTF_8ToGB2312(output, (char *)temp.data(), strlen(temp.data()));
+
+		return output;
+	}
+}

+ 57 - 0
MD5Test/StringProcess.h

@@ -0,0 +1,57 @@
+#ifndef __STRING_PROCESS_20151214__
+#define __STRING_PROCESS_20151214__
+
+#pragma once
+
+#include <string.h>
+#include <vector>
+using namespace std;
+
+
+namespace StringProcess
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 将utf8字符串转为unicode字符串;
+	extern WCHAR*	utf8_to_unicode(IN const CHAR* pszutf8);
+	extern INT		utf8_to_unicode(IN const CHAR *pszutf8, OUT WCHAR *pszunicode);
+
+	// 将utf8字符串转为ascii字符串;
+	extern CHAR*	utf8_to_ascii(IN const CHAR *pszutf8);
+	extern int		utf8_to_ascii(IN const CHAR *pszutf8,OUT CHAR* pszacsii);
+
+	// 将unicode字符串转为acsii(gb312)字符串;
+	extern CHAR*	unicode_to_ascii(IN const WCHAR *pszunicode);
+	extern int		unicode_to_ascii(IN const WCHAR *pszunicode, OUT CHAR *pszacsii);
+
+	// 将unicode字符串转为utf8字符串;
+	extern CHAR*	unicode_to_uft8(IN const WCHAR *pszunicode);
+	extern int		unicode_to_uft8(IN const WCHAR *pszunicode,OUT CHAR* pszutf8);
+
+	// 将ascii字符串转为unicode字符串;
+	extern WCHAR*	ascii_to_unicode(IN const CHAR* pszascii);
+	extern int		ascii_to_unicode(IN const CHAR* pszascii,OUT WCHAR *pszunicode);
+
+	// 将ascii字符串转为utf8字符串;
+	extern CHAR*	ascii_to_utf8(IN const CHAR* pszascii);
+	extern int		ascii_to_utf8(IN const CHAR* pszascii, OUT CHAR* pszutf8);	
+
+
+	// http使用;
+	extern void UTF_8ToGB2312(string &pOut, char *pText, int pLen);//utf_8转为gb2312
+	extern void GB2312ToUTF_8(string& pOut, char *pText, int pLen); //gb2312 转utf_8
+	extern string UrlGB2312(char * str);                           //urlgb2312编码
+	extern string UrlUTF8(char * str);                             //urlutf8 编码
+	extern string UrlUTF8Decode(string str);						//urlutf8解码
+	extern string UrlGB2312Decode(string str);						//urlgb2312解码
+	// 下6函数为上6函数的私有函数;
+	extern void Gb2312ToUnicode(WCHAR* pOut, char *gbBuffer);
+	extern void UTF_8ToUnicode(WCHAR* pOut, char *pText);
+	extern void UnicodeToUTF_8(char* pOut, WCHAR* pText);
+	extern void UnicodeToGB2312(char* pOut, WCHAR uData);
+	extern char CharToInt(char ch);
+	extern char StrToBin(char *str);
+
+	
+};
+
+#endif

+ 336 - 0
MD5Test/config.h

@@ -0,0 +1,336 @@
+/**
+ * \file config.h
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/*
+ * Uncomment if native integers are 8-bit wide.
+ *
+#define POLARSSL_HAVE_INT8
+ */
+
+/*
+ * Uncomment if native integers are 16-bit wide.
+ *
+#define POLARSSL_HAVE_INT16
+ */
+
+/*
+ * Uncomment if the compiler supports long long.
+ *
+#define POLARSSL_HAVE_LONGLONG
+ */
+
+/*
+ * Uncomment to enable the use of assembly code.
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/polarssl/bn_mul.h
+ *
+ */
+#define POLARSSL_HAVE_ASM
+
+/*
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ *
+#define POLARSSL_HAVE_SSE2
+ */
+
+/*
+ * Enable all SSL/TLS debugging messages.
+ */
+#define POLARSSL_DEBUG_MSG
+
+/*
+ * Enable the checkup functions (*_self_test).
+ */
+#define POLARSSL_SELF_TEST
+
+/*
+ * Enable run-time version information functions
+ */
+#define POLARSSL_VERSION_C
+
+/*
+ * Enable the prime-number generation code.
+ */
+#define POLARSSL_GENPRIME
+
+/*
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+#define POLARSSL_AES_ROM_TABLES
+ */
+
+/*
+ * Module:  library/aes.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_AES_128_SHA
+ *      SSL_RSA_AES_256_SHA
+ *      SSL_EDH_RSA_AES_256_SHA
+ */
+#define POLARSSL_AES_C
+
+/*
+ * Module:  library/arc4.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_RC4_128_MD5
+ *      SSL_RSA_RC4_128_SHA
+ */
+#define POLARSSL_ARC4_C
+
+/*
+ * Module:  library/base64.c
+ * Caller:  library/x509parse.c
+ *
+ * This module is required for X.509 support.
+ */
+#define POLARSSL_BASE64_C
+
+/*
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/*
+ * Module:  library/camellia.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enabled the following cipher suites:
+ *      SSL_RSA_CAMELLIA_128_SHA
+ *      SSL_RSA_CAMELLIA_256_SHA
+ *      SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_CAMELLIA_C
+
+/*
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define POLARSSL_CERTS_C
+
+/*
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/*
+ * Module:  library/des.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_DES_168_SHA
+ *      SSL_EDH_RSA_DES_168_SHA
+ */
+#define POLARSSL_DES_C
+
+/*
+ * Module:  library/dhm.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_EDH_RSA_DES_168_SHA
+ *      SSL_EDH_RSA_AES_256_SHA
+ *      SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_DHM_C
+
+/*
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * This module enables the HAVEGE random number generator.
+ */
+#define POLARSSL_HAVEGE_C
+
+/*
+ * Module:  library/md2.c
+ * Caller:  library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+#define POLARSSL_MD2_C
+ */
+
+/*
+ * Module:  library/md4.c
+ * Caller:  library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+#define POLARSSL_MD4_C
+ */
+
+/*
+ * Module:  library/md5.c
+ * Caller:  library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ */
+#define POLARSSL_MD5_C
+
+/*
+ * Module:  library/net.c
+ * Caller:
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define POLARSSL_NET_C
+
+/*
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+#define POLARSSL_PADLOCK_C
+
+/*
+ * Module:  library/rsa.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509.c
+ *
+ * This module is required for SSL/TLS and MD5-signed certificates.
+ */
+#define POLARSSL_RSA_C
+
+/*
+ * Module:  library/sha1.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/*
+ * Module:  library/sha2.c
+ * Caller:
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ */
+#define POLARSSL_SHA2_C
+
+/*
+ * Module:  library/sha4.c
+ * Caller:
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define POLARSSL_SHA4_C
+
+/*
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/*
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define POLARSSL_SSL_SRV_C
+
+/*
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/*
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+#define POLARSSL_TIMING_C
+
+/*
+ * Module:  library/x509parse.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_PARSE_C
+
+/*
+ * Module:  library/x509_write.c
+ * Caller:
+ *
+ * This module is required for X.509 certificate writing.
+ */
+#define POLARSSL_X509_WRITE_C
+
+/*
+ * Module:  library/xtea.c
+ * Caller:
+ */
+#define POLARSSL_XTEA_C
+
+#endif /* config.h */

+ 1073 - 0
MD5Test/des.cpp

@@ -0,0 +1,1073 @@
+#include "stdafx.h"
+#include "des.h"
+#include <string.h>
+
+//32-bit integer manipulation macros (big endian)
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i)                             \
+{                                                       \
+	(n) = ( (unsigned long) (b)[(i)] << 24 )        \
+	| ( (unsigned long) (b)[(i) + 1] << 16 )        \
+	| ( (unsigned long) (b)[(i) + 2] <<  8 )        \
+	| ( (unsigned long) (b)[(i) + 3]       );       \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i)                             \
+{                                                       \
+	(b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+	(b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+	(b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+	(b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+//Expanded DES S-boxes
+static const unsigned long SB1[64] =
+{
+	0x01010400, 0x00000000, 0x00010000, 0x01010404,
+	0x01010004, 0x00010404, 0x00000004, 0x00010000,
+	0x00000400, 0x01010400, 0x01010404, 0x00000400,
+	0x01000404, 0x01010004, 0x01000000, 0x00000004,
+	0x00000404, 0x01000400, 0x01000400, 0x00010400,
+	0x00010400, 0x01010000, 0x01010000, 0x01000404,
+	0x00010004, 0x01000004, 0x01000004, 0x00010004,
+	0x00000000, 0x00000404, 0x00010404, 0x01000000,
+	0x00010000, 0x01010404, 0x00000004, 0x01010000,
+	0x01010400, 0x01000000, 0x01000000, 0x00000400,
+	0x01010004, 0x00010000, 0x00010400, 0x01000004,
+	0x00000400, 0x00000004, 0x01000404, 0x00010404,
+	0x01010404, 0x00010004, 0x01010000, 0x01000404,
+	0x01000004, 0x00000404, 0x00010404, 0x01010400,
+	0x00000404, 0x01000400, 0x01000400, 0x00000000,
+	0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const unsigned long SB2[64] =
+{
+	0x80108020, 0x80008000, 0x00008000, 0x00108020,
+	0x00100000, 0x00000020, 0x80100020, 0x80008020,
+	0x80000020, 0x80108020, 0x80108000, 0x80000000,
+	0x80008000, 0x00100000, 0x00000020, 0x80100020,
+	0x00108000, 0x00100020, 0x80008020, 0x00000000,
+	0x80000000, 0x00008000, 0x00108020, 0x80100000,
+	0x00100020, 0x80000020, 0x00000000, 0x00108000,
+	0x00008020, 0x80108000, 0x80100000, 0x00008020,
+	0x00000000, 0x00108020, 0x80100020, 0x00100000,
+	0x80008020, 0x80100000, 0x80108000, 0x00008000,
+	0x80100000, 0x80008000, 0x00000020, 0x80108020,
+	0x00108020, 0x00000020, 0x00008000, 0x80000000,
+	0x00008020, 0x80108000, 0x00100000, 0x80000020,
+	0x00100020, 0x80008020, 0x80000020, 0x00100020,
+	0x00108000, 0x00000000, 0x80008000, 0x00008020,
+	0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const unsigned long SB3[64] =
+{
+	0x00000208, 0x08020200, 0x00000000, 0x08020008,
+	0x08000200, 0x00000000, 0x00020208, 0x08000200,
+	0x00020008, 0x08000008, 0x08000008, 0x00020000,
+	0x08020208, 0x00020008, 0x08020000, 0x00000208,
+	0x08000000, 0x00000008, 0x08020200, 0x00000200,
+	0x00020200, 0x08020000, 0x08020008, 0x00020208,
+	0x08000208, 0x00020200, 0x00020000, 0x08000208,
+	0x00000008, 0x08020208, 0x00000200, 0x08000000,
+	0x08020200, 0x08000000, 0x00020008, 0x00000208,
+	0x00020000, 0x08020200, 0x08000200, 0x00000000,
+	0x00000200, 0x00020008, 0x08020208, 0x08000200,
+	0x08000008, 0x00000200, 0x00000000, 0x08020008,
+	0x08000208, 0x00020000, 0x08000000, 0x08020208,
+	0x00000008, 0x00020208, 0x00020200, 0x08000008,
+	0x08020000, 0x08000208, 0x00000208, 0x08020000,
+	0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const unsigned long SB4[64] =
+{
+	0x00802001, 0x00002081, 0x00002081, 0x00000080,
+	0x00802080, 0x00800081, 0x00800001, 0x00002001,
+	0x00000000, 0x00802000, 0x00802000, 0x00802081,
+	0x00000081, 0x00000000, 0x00800080, 0x00800001,
+	0x00000001, 0x00002000, 0x00800000, 0x00802001,
+	0x00000080, 0x00800000, 0x00002001, 0x00002080,
+	0x00800081, 0x00000001, 0x00002080, 0x00800080,
+	0x00002000, 0x00802080, 0x00802081, 0x00000081,
+	0x00800080, 0x00800001, 0x00802000, 0x00802081,
+	0x00000081, 0x00000000, 0x00000000, 0x00802000,
+	0x00002080, 0x00800080, 0x00800081, 0x00000001,
+	0x00802001, 0x00002081, 0x00002081, 0x00000080,
+	0x00802081, 0x00000081, 0x00000001, 0x00002000,
+	0x00800001, 0x00002001, 0x00802080, 0x00800081,
+	0x00002001, 0x00002080, 0x00800000, 0x00802001,
+	0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const unsigned long SB5[64] =
+{
+	0x00000100, 0x02080100, 0x02080000, 0x42000100,
+	0x00080000, 0x00000100, 0x40000000, 0x02080000,
+	0x40080100, 0x00080000, 0x02000100, 0x40080100,
+	0x42000100, 0x42080000, 0x00080100, 0x40000000,
+	0x02000000, 0x40080000, 0x40080000, 0x00000000,
+	0x40000100, 0x42080100, 0x42080100, 0x02000100,
+	0x42080000, 0x40000100, 0x00000000, 0x42000000,
+	0x02080100, 0x02000000, 0x42000000, 0x00080100,
+	0x00080000, 0x42000100, 0x00000100, 0x02000000,
+	0x40000000, 0x02080000, 0x42000100, 0x40080100,
+	0x02000100, 0x40000000, 0x42080000, 0x02080100,
+	0x40080100, 0x00000100, 0x02000000, 0x42080000,
+	0x42080100, 0x00080100, 0x42000000, 0x42080100,
+	0x02080000, 0x00000000, 0x40080000, 0x42000000,
+	0x00080100, 0x02000100, 0x40000100, 0x00080000,
+	0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const unsigned long SB6[64] =
+{
+	0x20000010, 0x20400000, 0x00004000, 0x20404010,
+	0x20400000, 0x00000010, 0x20404010, 0x00400000,
+	0x20004000, 0x00404010, 0x00400000, 0x20000010,
+	0x00400010, 0x20004000, 0x20000000, 0x00004010,
+	0x00000000, 0x00400010, 0x20004010, 0x00004000,
+	0x00404000, 0x20004010, 0x00000010, 0x20400010,
+	0x20400010, 0x00000000, 0x00404010, 0x20404000,
+	0x00004010, 0x00404000, 0x20404000, 0x20000000,
+	0x20004000, 0x00000010, 0x20400010, 0x00404000,
+	0x20404010, 0x00400000, 0x00004010, 0x20000010,
+	0x00400000, 0x20004000, 0x20000000, 0x00004010,
+	0x20000010, 0x20404010, 0x00404000, 0x20400000,
+	0x00404010, 0x20404000, 0x00000000, 0x20400010,
+	0x00000010, 0x00004000, 0x20400000, 0x00404010,
+	0x00004000, 0x00400010, 0x20004010, 0x00000000,
+	0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const unsigned long SB7[64] =
+{
+	0x00200000, 0x04200002, 0x04000802, 0x00000000,
+	0x00000800, 0x04000802, 0x00200802, 0x04200800,
+	0x04200802, 0x00200000, 0x00000000, 0x04000002,
+	0x00000002, 0x04000000, 0x04200002, 0x00000802,
+	0x04000800, 0x00200802, 0x00200002, 0x04000800,
+	0x04000002, 0x04200000, 0x04200800, 0x00200002,
+	0x04200000, 0x00000800, 0x00000802, 0x04200802,
+	0x00200800, 0x00000002, 0x04000000, 0x00200800,
+	0x04000000, 0x00200800, 0x00200000, 0x04000802,
+	0x04000802, 0x04200002, 0x04200002, 0x00000002,
+	0x00200002, 0x04000000, 0x04000800, 0x00200000,
+	0x04200800, 0x00000802, 0x00200802, 0x04200800,
+	0x00000802, 0x04000002, 0x04200802, 0x04200000,
+	0x00200800, 0x00000000, 0x00000002, 0x04200802,
+	0x00000000, 0x00200802, 0x04200000, 0x00000800,
+	0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const unsigned long SB8[64] =
+{
+	0x10001040, 0x00001000, 0x00040000, 0x10041040,
+	0x10000000, 0x10001040, 0x00000040, 0x10000000,
+	0x00040040, 0x10040000, 0x10041040, 0x00041000,
+	0x10041000, 0x00041040, 0x00001000, 0x00000040,
+	0x10040000, 0x10000040, 0x10001000, 0x00001040,
+	0x00041000, 0x00040040, 0x10040040, 0x10041000,
+	0x00001040, 0x00000000, 0x00000000, 0x10040040,
+	0x10000040, 0x10001000, 0x00041040, 0x00040000,
+	0x00041040, 0x00040000, 0x10041000, 0x00001000,
+	0x00000040, 0x10040040, 0x00001000, 0x00041040,
+	0x10001000, 0x00000040, 0x10000040, 0x10040000,
+	0x10040040, 0x10000000, 0x00040000, 0x10001040,
+	0x00000000, 0x10041040, 0x00040040, 0x10000040,
+	0x10040000, 0x10001000, 0x10001040, 0x00000000,
+	0x10041040, 0x00041000, 0x00041000, 0x00001040,
+	0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+//PC1: left and right halves bit-swap
+static const unsigned long LHs[16] =
+{
+	0x00000000, 0x00000001, 0x00000100, 0x00000101,
+	0x00010000, 0x00010001, 0x00010100, 0x00010101,
+	0x01000000, 0x01000001, 0x01000100, 0x01000101,
+	0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const unsigned long RHs[16] =
+{
+	0x00000000, 0x01000000, 0x00010000, 0x01010000,
+	0x00000100, 0x01000100, 0x00010100, 0x01010100,
+	0x00000001, 0x01000001, 0x00010001, 0x01010001,
+	0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
+        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+        254 
+};
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
+{
+    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+// Initial Permutation macro
+#define DES_IP(X,Y)                                             \
+{                                                               \
+	T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+	T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+	T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+	T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+	Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF;                    \
+	T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T;                   \
+	X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF;                    \
+	}
+
+// Final Permutation macro
+#define DES_FP(X,Y)                                             \
+{                                                               \
+	X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF;                    \
+	T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T;                   \
+	Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF;                    \
+	T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+	T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+	T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+	T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+	}
+
+// DES round macro
+#define DES_ROUND(X,Y)                          \
+{                                               \
+	T = *SK++ ^ X;                              \
+	Y ^= SB8[ (T) & 0x3F ] ^              		\
+		 SB6[ (T >>  8) & 0x3F ] ^              \
+		 SB4[ (T >> 16) & 0x3F ] ^              \
+		 SB2[ (T >> 24) & 0x3F ];               \
+												\
+	T = *SK++ ^ ((X << 28) | (X >> 4));         \
+	Y ^= SB7[ (T) & 0x3F ] ^              		\
+		 SB5[ (T >>  8) & 0x3F ] ^              \
+		 SB3[ (T >> 16) & 0x3F ] ^              \
+		 SB1[ (T >> 24) & 0x3F ];               \
+	}
+
+#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
+
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
+{
+    for(int i = 0; i < DES_KEY_SIZE; i++ )
+        key[i] = odd_parity_table[key[i] / 2];
+}
+
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
+{
+    for(int i = 0; i < DES_KEY_SIZE; i++ )
+        if( key[i] != odd_parity_table[key[i] / 2] )
+            return( 1 );
+
+    return( 0 );
+}
+
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
+{
+    for(int i = 0; i < WEAK_KEY_COUNT; i++ )
+        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0 )
+            return( 1 );
+
+    return( 0 );
+}
+
+unsigned __int64 des_enc_len(const unsigned __int64& nlen)
+{
+	unsigned __int64 npaddinglen = nlen;
+	int npad = nlen&7;//nFileLen & 7 <=> nFileLen%8
+	if ( npad != 0 )
+	{
+		npaddinglen += 8 - npad;
+	}
+	return npaddinglen;
+}
+
+unsigned __int64 des_dec_len(const unsigned char* input, unsigned __int64 nlen)
+{
+	while( input[--nlen] == 0x00 );
+	return ++nlen;
+}
+
+/************************************************************************/
+/*  函数:des_setkey[6/5/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+static void des_setkey( unsigned long SK[32], const unsigned char key[8] )
+{
+	int i;
+	unsigned long X, Y, T;
+
+	GET_ULONG_BE( X, key, 0 );
+	GET_ULONG_BE( Y, key, 4 );
+
+	// Permuted Choice 1
+	T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);
+	T =  ((Y      ) ^ X) & 0x10101010;  X ^= T; Y ^= (T      );
+
+	X =   (LHs[ (X      ) & 0xF] << 3) | (LHs[ (X >>  8) & 0xF ] << 2)
+		| (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ]     )
+		| (LHs[ (X >>  5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+		| (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+	Y =   (RHs[ (Y >>  1) & 0xF] << 3) | (RHs[ (Y >>  9) & 0xF ] << 2)
+		| (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ]     )
+		| (RHs[ (Y >>  4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+		| (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+	X &= 0x0FFFFFFF;
+	Y &= 0x0FFFFFFF;
+
+	// calculate subkeys
+	for( i = 0; i < 16; i++ )
+	{
+		if( i < 2 || i == 8 || i == 15 )
+		{
+			X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;
+			Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;
+		}
+		else
+		{
+			X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;
+			Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;
+		}
+
+		*SK++ =   ((X <<  4) & 0x24000000) | ((X << 28) & 0x10000000)
+			| ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+			| ((X <<  6) & 0x01000000) | ((X <<  9) & 0x00200000)
+			| ((X >>  1) & 0x00100000) | ((X << 10) & 0x00040000)
+			| ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)
+			| ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)
+			| ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)
+			| ((Y >> 14) & 0x00000200) | ((Y      ) & 0x00000100)
+			| ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+			| ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+			| ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+		*SK++ =   ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+			| ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+			| ((X >>  2) & 0x02000000) | ((X <<  1) & 0x01000000)
+			| ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+			| ((X <<  3) & 0x00080000) | ((X >>  6) & 0x00040000)
+			| ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)
+			| ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)
+			| ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)
+			| ((Y      ) & 0x00000200) | ((Y <<  7) & 0x00000100)
+			| ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)
+			| ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+	}
+}
+
+/************************************************************************/
+/*  函数:des_setkey_enc[6/5/2016 IT];
+/*  描述:设置DES加密密钥(56bit,加密);
+/*  参数:;
+/*  	[IN] ctx:要被初始化的DES结构体;
+/*  	[IN] key:8字节长度的加解密密钥;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void des_setkey_enc( IN des_context *ctx, IN const unsigned char key[8] )
+{
+	des_setkey( ctx->sk, key );
+}
+
+/************************************************************************/
+/*  函数:des_setkey_dec[6/5/2016 IT];
+/*  描述:设置DES解密密钥(56bit,解密);;
+/*  参数:;
+/*  	[IN] ctx:要被初始化的DES结构体;
+/*  	[IN] key:8字节长度的加解密密钥;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void des_setkey_dec( IN des_context *ctx, IN const unsigned char key[8] )
+{
+	int i;
+
+	des_setkey( ctx->sk, key );
+
+	for( i = 0; i < 16; i += 2 )
+	{
+		SWAP( ctx->sk[i], ctx->sk[30 - i] );
+		SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+	}
+}
+
+/************************************************************************/
+/*  函数:[6/5/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+static void des3_set2key( unsigned long esk[96],unsigned long dsk[96],const unsigned char key[16] )
+{
+	int i;
+
+	des_setkey( esk, key );
+	des_setkey( dsk + 32, key + 8 );
+
+	for( i = 0; i < 32; i += 2 )
+	{
+		dsk[i] = esk[30 - i];
+		dsk[i +  1] = esk[31 - i];
+
+		esk[i + 32] = dsk[62 - i];
+		esk[i + 33] = dsk[63 - i];
+
+		esk[i + 64] = esk[i];
+		esk[i + 65] = esk[i + 1];
+
+		dsk[i + 64] = dsk[i];
+		dsk[i + 65] = dsk[i + 1];
+	}
+}
+
+/************************************************************************/
+/*  函数:des3_set2key_enc[6/5/2016 IT];
+/*  描述:设置2层DES加密密钥(112bit,加密);
+/*  参数:;
+/*  	[IN] ctx:要被初始化的DES结构体;
+/*  	[IN] key:16字节长度的加解密密钥;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void des3_set2key_enc( des3_context *ctx, const unsigned char key[16] )
+{
+	unsigned long sk[96];
+
+	des3_set2key( ctx->sk, sk, key );
+	memset( sk,  0, sizeof( sk ) );
+}
+
+/************************************************************************/
+/*  函数:des3_set2key_dec[6/5/2016 IT];
+/*  描述:设置2层DES解密密钥(112bit,解密);;
+/*  参数:;
+/*  	[IN] ctx:要被初始化的DES结构体;
+/*  	[IN] key:16字节长度的加解密密钥;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void des3_set2key_dec( des3_context *ctx, const unsigned char key[16] )
+{
+	unsigned long sk[96];
+
+	des3_set2key( sk, ctx->sk, key );
+	memset( sk,  0, sizeof( sk ) );
+}
+
+/************************************************************************/
+/*  函数:[6/5/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+static void des3_set3key( unsigned long esk[96],unsigned long dsk[96],const unsigned char key[24] )
+{
+	int i;
+
+	des_setkey( esk, key );
+	des_setkey( dsk + 32, key +  8 );
+	des_setkey( esk + 64, key + 16 );
+
+	for( i = 0; i < 32; i += 2 )
+	{
+		dsk[i] 		= esk[94 - i];
+		dsk[i +  1] = esk[95 - i];
+
+		esk[i + 32] = dsk[62 - i];
+		esk[i + 33] = dsk[63 - i];
+
+		dsk[i + 64] = esk[30 - i];
+		dsk[i + 65] = esk[31 - i];
+	}
+}
+
+/************************************************************************/
+/*  函数:des3_set3key_enc[6/5/2016 IT];
+/*  描述:设置3层DES加密密钥(168bit,加密);
+/*  参数:;
+/*  	[IN] ctx:要被初始化的DES结构体;
+/*  	[IN] key:24字节长度的加解密密钥;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void des3_set3key_enc( des3_context *ctx, const unsigned char key[24] )
+{
+	unsigned long sk[96];
+
+	des3_set3key( ctx->sk, sk, key );
+	memset( sk, 0, sizeof( sk ) );
+}
+
+/************************************************************************/
+/*  函数:des3_set2key_dec[6/5/2016 IT];
+/*  描述:设置3层DES解密密钥(168bit,解密);;
+/*  参数:;
+/*  	[IN] ctx:要被初始化的DES结构体;
+/*  	[IN] key:24字节长度的加解密密钥;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void des3_set3key_dec( des3_context *ctx, const unsigned char key[24] )
+{
+	unsigned long sk[96];
+
+	des3_set3key( sk, ctx->sk, key );
+	memset( sk, 0, sizeof( sk ) );
+}
+
+/************************************************************************/
+/*  函数:[6/5/2016 IT];
+/*  描述:DES-ECB模式下加解密;
+/*  参数:;
+/*  	[IN] ctx:已经初始化过的DES结构体;
+/*  	[IN] input:64bit的输入缓存块;
+/*  	[OUT] output:64bit的输出缓存块;
+/*  返回:成功返回0;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int des_crypt_ecb( IN des_context *ctx, IN const unsigned char input[8], OUT unsigned char output[8] )
+{
+	int i;
+	unsigned long X, Y, T, *SK;
+
+	SK = ctx->sk;
+
+	GET_ULONG_BE( X, input, 0 );
+	GET_ULONG_BE( Y, input, 4 );
+
+	DES_IP( X, Y );
+
+	for( i = 0; i < 8; i++ )
+	{
+		DES_ROUND( Y, X );
+		DES_ROUND( X, Y );
+	}
+
+	DES_FP( Y, X );
+
+	PUT_ULONG_BE( Y, output, 0 );
+	PUT_ULONG_BE( X, output, 4 );
+
+	return( 0 );
+}
+
+/************************************************************************/
+/*  函数:des_crypt_cbc[6/5/2016 IT];
+/*  描述:DES-CBC模式加解密;
+/*  参数:;
+/*  	[IN] ctx:已经初始化过的DES结构体;
+/*  	[IN] mode:加密或解密模式;
+/*  	[IN] length:input长度;
+/*  	[IN] iv:初始向量(使用后更新);
+/*  	[IN] input:要加密或解密的数据;
+/*  	[OUT] output:加密或解密的数据;
+/*  返回:成功返回0;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int des_crypt_cbc( IN des_context *ctx, IN int mode, IN int length, IN unsigned char iv[8], IN const unsigned char *input, OUT unsigned char *output )
+{
+	int i;
+	unsigned char temp[8];
+
+	if( length % 8 )
+		return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+	if( mode == DES_ENCRYPT )
+	{
+		while( length > 0 )
+		{
+			for( i = 0; i < 8; i++ )
+				output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+			des_crypt_ecb( ctx, output, output );
+			memcpy( iv, output, 8 );
+
+			input  += 8;
+			output += 8;
+			length -= 8;
+		}
+	}
+	else /* DES_DECRYPT */
+	{
+		while( length > 0 )
+		{
+			memcpy( temp, input, 8 );
+			des_crypt_ecb( ctx, input, output );
+
+			for( i = 0; i < 8; i++ )
+				output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+			memcpy( iv, temp, 8 );
+
+			input  += 8;
+			output += 8;
+			length -= 8;
+		}
+	}
+
+	return( 0 );
+}
+
+/************************************************************************/
+/*  函数:des3_crypt_ecb[6/5/2016 IT];
+/*  描述:3层DES-ECB模式加解密;
+/*  参数:;
+/*  	[IN] ctx:已经初始化过的DES结构体;
+/*  	[IN] input:要加密或解密的数据;
+/*  	[OUT] output:加密或解密的数据;
+/*  返回:成功返回0;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int des3_crypt_ecb( des3_context *ctx, const unsigned char input[8],unsigned char output[8] )
+{
+	int i;
+	unsigned long X, Y, T, *SK;
+
+	SK = ctx->sk;
+
+	GET_ULONG_BE( X, input, 0 );
+	GET_ULONG_BE( Y, input, 4 );
+
+	DES_IP( X, Y );
+
+	for( i = 0; i < 8; i++ )
+	{
+		DES_ROUND( Y, X );
+		DES_ROUND( X, Y );
+	}
+
+	for( i = 0; i < 8; i++ )
+	{
+		DES_ROUND( X, Y );
+		DES_ROUND( Y, X );
+	}
+
+	for( i = 0; i < 8; i++ )
+	{
+		DES_ROUND( Y, X );
+		DES_ROUND( X, Y );
+	}
+
+	DES_FP( Y, X );
+
+	PUT_ULONG_BE( Y, output, 0 );
+	PUT_ULONG_BE( X, output, 4 );
+
+	return( 0 );
+}
+
+/************************************************************************/
+/*  函数:des3_crypt_cbc[6/5/2016 IT];
+/*  描述:3层DES-CBC加解密;
+/*  参数:;
+/*  	[IN] ctx:已经初始化过的DES结构体;
+/*  	[IN] mode:加密或解密模式;
+/*  	[IN] length:input长度;
+/*  	[IN] iv:初始向量(使用后更新);
+/*  	[IN] input:要加密或解密的数据;
+/*  	[OUT] output:加密或解密的数据;
+/*  返回:成功返回0;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int des3_crypt_cbc( des3_context *ctx,int mode,int length,unsigned char iv[8],const unsigned char *input,unsigned char *output )
+{
+	int i;
+	unsigned char temp[8];
+
+	if( length % 8 )
+		return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+	if( mode == DES_ENCRYPT )
+	{
+		while( length > 0 )
+		{
+			for( i = 0; i < 8; i++ )
+				output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+			des3_crypt_ecb( ctx, output, output );
+			memcpy( iv, output, 8 );
+
+			input  += 8;
+			output += 8;
+			length -= 8;
+		}
+	}
+	else /* DES_DECRYPT */
+	{
+		while( length > 0 )
+		{
+			memcpy( temp, input, 8 );
+			des3_crypt_ecb( ctx, input, output );
+
+			for( i = 0; i < 8; i++ )
+				output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+			memcpy( iv, temp, 8 );
+
+			input  += 8;
+			output += 8;
+			length -= 8;
+		}
+	}
+
+	return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+* DES and 3DES test vectors from:
+*
+* http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+*/
+static const unsigned char des3_test_keys[24] =
+{
+	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+	0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+	0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_iv[8] =
+{
+	0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+	0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+	{ 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+	{ 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+	{ 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+	{ 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+	{ 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+	{ 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+	{ 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+	{ 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+	{ 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+	{ 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+	{ 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+	{ 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+
+/************************************************************************/
+/*  函数:des_self_test[6/5/2016 IT];
+/*  描述:测试例子;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int des_self_test( int verbose )
+{
+	int i, j, u, v;
+	des_context ctx;
+	des3_context ctx3;
+	unsigned char key[24];
+	unsigned char buf[8];
+	unsigned char prv[8];
+	unsigned char iv[8];
+
+	memset( key, 0, 24 );
+
+	// ECB mode
+	for( i = 0; i < 6; i++ )
+	{
+		u = i >> 1;
+		v = i  & 1;
+
+		if( verbose != 0 )
+			printf( "  DES%c-ECB-%3d (%s): ",
+			( u == 0 ) ? ' ' : '3', 56 + u * 56,
+			( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+		memcpy( buf, des3_test_buf, 8 );
+
+		switch( i )
+		{
+		case 0:
+			des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
+			break;
+
+		case 1:
+			des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
+			break;
+
+		case 2:
+			des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		case 3:
+			des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		case 4:
+			des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		case 5:
+			des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		default:
+			return( 1 );
+		}
+
+		for( j = 0; j < 10000; j++ )
+		{
+			if( u == 0 )
+				des_crypt_ecb( &ctx, buf, buf );
+			else
+				des3_crypt_ecb( &ctx3, buf, buf );
+		}
+
+		if( ( v == DES_DECRYPT &&
+			memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+			( v != DES_DECRYPT &&
+			memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+		{
+			if( verbose != 0 )
+				printf( "failed\n" );
+
+			return( 1 );
+		}
+
+		if( verbose != 0 )
+			printf( "passed\n" );
+	}
+
+	if( verbose != 0 )
+		printf( "\n" );
+
+	// CBC mode
+	for( i = 0; i < 6; i++ )
+	{
+		u = i >> 1;
+		v = i  & 1;
+
+		if( verbose != 0 )
+			printf( "  DES%c-CBC-%3d (%s): ",
+			( u == 0 ) ? ' ' : '3', 56 + u * 56,
+			( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+		memcpy( iv,  des3_test_iv,  8 );
+		memcpy( prv, des3_test_iv,  8 );
+		memcpy( buf, des3_test_buf, 8 );
+
+		switch( i )
+		{
+		case 0:
+			des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
+			break;
+
+		case 1:
+			des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
+			break;
+
+		case 2:
+			des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		case 3:
+			des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		case 4:
+			des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		case 5:
+			des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
+			break;
+
+		default:
+			return( 1 );
+		}
+
+		if( v == DES_DECRYPT )
+		{
+			for( j = 0; j < 10000; j++ )
+			{
+				if( u == 0 )
+					des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+				else
+					des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+			}
+		}
+		else
+		{
+			for( j = 0; j < 10000; j++ )
+			{
+				unsigned char tmp[8];
+
+				if( u == 0 )
+					des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+				else
+					des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+				memcpy( tmp, prv, 8 );
+				memcpy( prv, buf, 8 );
+				memcpy( buf, tmp, 8 );
+			}
+
+			memcpy( buf, prv, 8 );
+		}
+
+		if( ( v == DES_DECRYPT &&
+			memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+			( v != DES_DECRYPT &&
+			memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+		{
+			if( verbose != 0 )
+				printf( "failed\n" );
+
+			return( 1 );
+		}
+
+		if( verbose != 0 )
+			printf( "passed\n" );
+	}
+
+	if( verbose != 0 )
+		printf( "\n" );
+
+	return( 0 );
+}
+
+#endif

+ 82 - 0
MD5Test/des.h

@@ -0,0 +1,82 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Home];
+/*  日    期:[6/5/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef POLARSSL_DES_H
+#define POLARSSL_DES_H
+
+#define DES_ENCRYPT     1
+#define DES_DECRYPT     0
+#define DES_KEY_SIZE    8
+
+#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH               -0x0C00
+
+// DES结构体;
+typedef struct
+{
+	unsigned long sk[32];       // DES 子密钥(由用户输入的密钥生成);
+}
+des_context;
+
+// 3层DES结构体;
+typedef struct
+{
+	unsigned long sk[96];       // DES 子密钥(由用户输入的密钥生成);
+}
+des3_context;
+
+// 设置密钥校验位为偶校验;
+void des_key_set_parity( unsigned char key[8] );
+// 判断密钥校验位是否为偶校验;
+int des_key_check_key_parity( const unsigned char key[8] );
+// 判断密钥是否为弱密钥;
+int des_key_check_weak( const unsigned char key[8] );
+
+// 返回加密时填充后的明文长度;
+unsigned __int64 des_enc_len(const unsigned __int64& nlen);
+// 返回解密后,去除填充的长度;
+unsigned __int64 des_dec_len(const unsigned char* input, unsigned __int64 nlen);
+
+// 设置DES加密密钥;
+void des_setkey_enc( IN des_context *ctx, IN const unsigned char key[8] );
+// 设置DES解密密钥;
+void des_setkey_dec( IN des_context *ctx, IN const unsigned char key[8] );
+
+// 设置2层DES加密密钥;
+void des3_set2key_enc( IN des3_context *ctx, IN const unsigned char key[16] );
+// 设置2层DES解密密钥;
+void des3_set2key_dec( IN des3_context *ctx, IN const unsigned char key[16] );
+
+// 设置3层DES加密密钥;
+void des3_set3key_enc( IN des3_context *ctx, IN const unsigned char key[24] );
+// 设置3层DES解密密钥;
+void des3_set3key_dec( IN des3_context *ctx, IN const unsigned char key[24] );
+
+// DES-ECB模式加解密;
+int des_crypt_ecb( IN des_context *ctx, IN const unsigned char input[8], IN unsigned char output[8] );
+// DES-CBC模式加解密;
+int des_crypt_cbc( IN des_context *ctx, IN int mode, IN int length, IN unsigned char iv[8], IN const unsigned char *input, IN unsigned char *output );
+// 3层DES-ECB模式加解密;
+int des3_crypt_ecb( IN des3_context *ctx, IN const unsigned char input[8], IN unsigned char output[8] );
+// 3层DES-CBC模式加解密;
+int des3_crypt_cbc( IN des3_context *ctx, IN int mode, IN int length, IN unsigned char iv[8], IN const unsigned char *input, IN unsigned char *output );
+
+// 测试例子;
+int des_self_test( int verbose );
+
+
+#endif // POLARSSL_DES_H

+ 275 - 0
MD5Test/des1.h

@@ -0,0 +1,275 @@
+#ifndef DES_H
+#define DES_H
+
+#include <stddef.h>
+//#include <stdint.h>
+typedef unsigned int uint32_t;
+
+#define DES_ENCRYPT     1
+#define DES_DECRYPT     0
+
+#define ERR_DES_INVALID_INPUT_LENGTH              -0x0032  /**< The data input has an invalid length. */
+
+#define DES_KEY_SIZE    8
+
+#if !defined(DES_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// DES上下文结构体;
+typedef struct
+{
+    uint32_t sk[32];           // DES subkeys;
+}
+des_context;
+
+// 3层(Triple)DES上下文结构体;
+typedef struct
+{
+    uint32_t sk[96];           // 3DES subkeys;
+}
+des3_context;
+
+/**
+ * \brief          Initialize DES context
+ *
+ * \param ctx      DES context to be initialized
+ */
+void des_init( des_context *ctx );
+
+/**
+ * \brief          Clear DES context
+ *
+ * \param ctx      DES context to be cleared
+ */
+void des_free( des_context *ctx );
+
+/**
+ * \brief          Initialize Triple-DES context
+ *
+ * \param ctx      DES3 context to be initialized
+ */
+void des3_init( des3_context *ctx );
+
+/**
+ * \brief          Clear Triple-DES context
+ *
+ * \param ctx      DES3 context to be cleared
+ */
+void des3_free( des3_context *ctx );
+
+/**
+ * \brief          Set key parity on the given key to odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ */
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          Check that key parity on the given key is odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ *
+ * \return         0 is parity was ok, 1 if parity was not correct.
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          Check that key is not a weak or semi-weak DES key
+ *
+ * \param key      8-byte secret key
+ *
+ * \return         0 if no weak key was found, 1 if a weak key was identified.
+ */
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          DES key schedule (56-bit, encryption)
+ *
+ * \param ctx      DES context to be initialized
+ * \param key      8-byte secret key
+ *
+ * \return         0
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          DES key schedule (56-bit, decryption)
+ *
+ * \param ctx      DES context to be initialized
+ * \param key      8-byte secret key
+ *
+ * \return         0
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          Triple-DES key schedule (112-bit, encryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      16-byte secret key
+ *
+ * \return         0
+ */
+int des3_set2key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief          Triple-DES key schedule (112-bit, decryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      16-byte secret key
+ *
+ * \return         0
+ */
+int des3_set2key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief          Triple-DES key schedule (168-bit, encryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      24-byte secret key
+ *
+ * \return         0
+ */
+int des3_set3key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief          Triple-DES key schedule (168-bit, decryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      24-byte secret key
+ *
+ * \return         0
+ */
+int des3_set3key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief          DES-ECB block encryption/decryption
+ *
+ * \param ctx      DES context
+ * \param input    64-bit input block
+ * \param output   64-bit output block
+ *
+ * \return         0 if successful
+ */
+int des_crypt_ecb( des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] );
+
+#if defined(CIPHER_MODE_CBC)
+/**
+ * \brief          DES-CBC buffer encryption/decryption
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      DES context
+ * \param mode     DES_ENCRYPT or DES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ */
+int des_crypt_cbc( des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /* CIPHER_MODE_CBC */
+
+/**
+ * \brief          3DES-ECB block encryption/decryption
+ *
+ * \param ctx      3DES context
+ * \param input    64-bit input block
+ * \param output   64-bit output block
+ *
+ * \return         0 if successful
+ */
+int des3_crypt_ecb( des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] );
+
+#if defined(CIPHER_MODE_CBC)
+/**
+ * \brief          3DES-CBC buffer encryption/decryption
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      3DES context
+ * \param mode     DES_ENCRYPT or DES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful, or ERR_DES_INVALID_INPUT_LENGTH
+ */
+int des3_crypt_cbc( des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output );
+#endif /* CIPHER_MODE_CBC */
+
+/**
+ * \brief          Internal function for key expansion.
+ *                 (Only exposed to allow overriding it,
+ *                 see DES_SETKEY_ALT)
+ *
+ * \param SK       Round keys
+ * \param key      Base key
+ */
+void des_setkey( uint32_t SK[32],
+                         const unsigned char key[DES_KEY_SIZE] );
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* DES_ALT */
+#include "des_alt.h"
+#endif /* DES_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int des_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* des.h */

+ 1035 - 0
MD5Test/des2.cpp

@@ -0,0 +1,1035 @@
+#include "stdafx.h"
+// #if !defined(CONFIG_FILE)
+// #include "mbedtls/config.h"
+// #else
+// #define CONFIG_FILE
+// #endif
+
+//#if defined(DES_C)
+
+#include "des.h"
+
+#include <string.h>
+
+#if defined(SELF_TEST)
+#if defined(PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define printf printf
+#endif /* PLATFORM_C */
+#endif /* SELF_TEST */
+
+#if !defined(DES_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * Expanded DES S-boxes
+ */
+static const uint32_t SB1[64] =
+{
+    0x01010400, 0x00000000, 0x00010000, 0x01010404,
+    0x01010004, 0x00010404, 0x00000004, 0x00010000,
+    0x00000400, 0x01010400, 0x01010404, 0x00000400,
+    0x01000404, 0x01010004, 0x01000000, 0x00000004,
+    0x00000404, 0x01000400, 0x01000400, 0x00010400,
+    0x00010400, 0x01010000, 0x01010000, 0x01000404,
+    0x00010004, 0x01000004, 0x01000004, 0x00010004,
+    0x00000000, 0x00000404, 0x00010404, 0x01000000,
+    0x00010000, 0x01010404, 0x00000004, 0x01010000,
+    0x01010400, 0x01000000, 0x01000000, 0x00000400,
+    0x01010004, 0x00010000, 0x00010400, 0x01000004,
+    0x00000400, 0x00000004, 0x01000404, 0x00010404,
+    0x01010404, 0x00010004, 0x01010000, 0x01000404,
+    0x01000004, 0x00000404, 0x00010404, 0x01010400,
+    0x00000404, 0x01000400, 0x01000400, 0x00000000,
+    0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const uint32_t SB2[64] =
+{
+    0x80108020, 0x80008000, 0x00008000, 0x00108020,
+    0x00100000, 0x00000020, 0x80100020, 0x80008020,
+    0x80000020, 0x80108020, 0x80108000, 0x80000000,
+    0x80008000, 0x00100000, 0x00000020, 0x80100020,
+    0x00108000, 0x00100020, 0x80008020, 0x00000000,
+    0x80000000, 0x00008000, 0x00108020, 0x80100000,
+    0x00100020, 0x80000020, 0x00000000, 0x00108000,
+    0x00008020, 0x80108000, 0x80100000, 0x00008020,
+    0x00000000, 0x00108020, 0x80100020, 0x00100000,
+    0x80008020, 0x80100000, 0x80108000, 0x00008000,
+    0x80100000, 0x80008000, 0x00000020, 0x80108020,
+    0x00108020, 0x00000020, 0x00008000, 0x80000000,
+    0x00008020, 0x80108000, 0x00100000, 0x80000020,
+    0x00100020, 0x80008020, 0x80000020, 0x00100020,
+    0x00108000, 0x00000000, 0x80008000, 0x00008020,
+    0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const uint32_t SB3[64] =
+{
+    0x00000208, 0x08020200, 0x00000000, 0x08020008,
+    0x08000200, 0x00000000, 0x00020208, 0x08000200,
+    0x00020008, 0x08000008, 0x08000008, 0x00020000,
+    0x08020208, 0x00020008, 0x08020000, 0x00000208,
+    0x08000000, 0x00000008, 0x08020200, 0x00000200,
+    0x00020200, 0x08020000, 0x08020008, 0x00020208,
+    0x08000208, 0x00020200, 0x00020000, 0x08000208,
+    0x00000008, 0x08020208, 0x00000200, 0x08000000,
+    0x08020200, 0x08000000, 0x00020008, 0x00000208,
+    0x00020000, 0x08020200, 0x08000200, 0x00000000,
+    0x00000200, 0x00020008, 0x08020208, 0x08000200,
+    0x08000008, 0x00000200, 0x00000000, 0x08020008,
+    0x08000208, 0x00020000, 0x08000000, 0x08020208,
+    0x00000008, 0x00020208, 0x00020200, 0x08000008,
+    0x08020000, 0x08000208, 0x00000208, 0x08020000,
+    0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const uint32_t SB4[64] =
+{
+    0x00802001, 0x00002081, 0x00002081, 0x00000080,
+    0x00802080, 0x00800081, 0x00800001, 0x00002001,
+    0x00000000, 0x00802000, 0x00802000, 0x00802081,
+    0x00000081, 0x00000000, 0x00800080, 0x00800001,
+    0x00000001, 0x00002000, 0x00800000, 0x00802001,
+    0x00000080, 0x00800000, 0x00002001, 0x00002080,
+    0x00800081, 0x00000001, 0x00002080, 0x00800080,
+    0x00002000, 0x00802080, 0x00802081, 0x00000081,
+    0x00800080, 0x00800001, 0x00802000, 0x00802081,
+    0x00000081, 0x00000000, 0x00000000, 0x00802000,
+    0x00002080, 0x00800080, 0x00800081, 0x00000001,
+    0x00802001, 0x00002081, 0x00002081, 0x00000080,
+    0x00802081, 0x00000081, 0x00000001, 0x00002000,
+    0x00800001, 0x00002001, 0x00802080, 0x00800081,
+    0x00002001, 0x00002080, 0x00800000, 0x00802001,
+    0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const uint32_t SB5[64] =
+{
+    0x00000100, 0x02080100, 0x02080000, 0x42000100,
+    0x00080000, 0x00000100, 0x40000000, 0x02080000,
+    0x40080100, 0x00080000, 0x02000100, 0x40080100,
+    0x42000100, 0x42080000, 0x00080100, 0x40000000,
+    0x02000000, 0x40080000, 0x40080000, 0x00000000,
+    0x40000100, 0x42080100, 0x42080100, 0x02000100,
+    0x42080000, 0x40000100, 0x00000000, 0x42000000,
+    0x02080100, 0x02000000, 0x42000000, 0x00080100,
+    0x00080000, 0x42000100, 0x00000100, 0x02000000,
+    0x40000000, 0x02080000, 0x42000100, 0x40080100,
+    0x02000100, 0x40000000, 0x42080000, 0x02080100,
+    0x40080100, 0x00000100, 0x02000000, 0x42080000,
+    0x42080100, 0x00080100, 0x42000000, 0x42080100,
+    0x02080000, 0x00000000, 0x40080000, 0x42000000,
+    0x00080100, 0x02000100, 0x40000100, 0x00080000,
+    0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const uint32_t SB6[64] =
+{
+    0x20000010, 0x20400000, 0x00004000, 0x20404010,
+    0x20400000, 0x00000010, 0x20404010, 0x00400000,
+    0x20004000, 0x00404010, 0x00400000, 0x20000010,
+    0x00400010, 0x20004000, 0x20000000, 0x00004010,
+    0x00000000, 0x00400010, 0x20004010, 0x00004000,
+    0x00404000, 0x20004010, 0x00000010, 0x20400010,
+    0x20400010, 0x00000000, 0x00404010, 0x20404000,
+    0x00004010, 0x00404000, 0x20404000, 0x20000000,
+    0x20004000, 0x00000010, 0x20400010, 0x00404000,
+    0x20404010, 0x00400000, 0x00004010, 0x20000010,
+    0x00400000, 0x20004000, 0x20000000, 0x00004010,
+    0x20000010, 0x20404010, 0x00404000, 0x20400000,
+    0x00404010, 0x20404000, 0x00000000, 0x20400010,
+    0x00000010, 0x00004000, 0x20400000, 0x00404010,
+    0x00004000, 0x00400010, 0x20004010, 0x00000000,
+    0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const uint32_t SB7[64] =
+{
+    0x00200000, 0x04200002, 0x04000802, 0x00000000,
+    0x00000800, 0x04000802, 0x00200802, 0x04200800,
+    0x04200802, 0x00200000, 0x00000000, 0x04000002,
+    0x00000002, 0x04000000, 0x04200002, 0x00000802,
+    0x04000800, 0x00200802, 0x00200002, 0x04000800,
+    0x04000002, 0x04200000, 0x04200800, 0x00200002,
+    0x04200000, 0x00000800, 0x00000802, 0x04200802,
+    0x00200800, 0x00000002, 0x04000000, 0x00200800,
+    0x04000000, 0x00200800, 0x00200000, 0x04000802,
+    0x04000802, 0x04200002, 0x04200002, 0x00000002,
+    0x00200002, 0x04000000, 0x04000800, 0x00200000,
+    0x04200800, 0x00000802, 0x00200802, 0x04200800,
+    0x00000802, 0x04000002, 0x04200802, 0x04200000,
+    0x00200800, 0x00000000, 0x00000002, 0x04200802,
+    0x00000000, 0x00200802, 0x04200000, 0x00000800,
+    0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const uint32_t SB8[64] =
+{
+    0x10001040, 0x00001000, 0x00040000, 0x10041040,
+    0x10000000, 0x10001040, 0x00000040, 0x10000000,
+    0x00040040, 0x10040000, 0x10041040, 0x00041000,
+    0x10041000, 0x00041040, 0x00001000, 0x00000040,
+    0x10040000, 0x10000040, 0x10001000, 0x00001040,
+    0x00041000, 0x00040040, 0x10040040, 0x10041000,
+    0x00001040, 0x00000000, 0x00000000, 0x10040040,
+    0x10000040, 0x10001000, 0x00041040, 0x00040000,
+    0x00041040, 0x00040000, 0x10041000, 0x00001000,
+    0x00000040, 0x10040040, 0x00001000, 0x00041040,
+    0x10001000, 0x00000040, 0x10000040, 0x10040000,
+    0x10040040, 0x10000000, 0x00040000, 0x10001040,
+    0x00000000, 0x10041040, 0x00040040, 0x10000040,
+    0x10040000, 0x10001000, 0x10001040, 0x00000000,
+    0x10041040, 0x00041000, 0x00041000, 0x00001040,
+    0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+/*
+ * PC1: left and right halves bit-swap
+ */
+static const uint32_t LHs[16] =
+{
+    0x00000000, 0x00000001, 0x00000100, 0x00000101,
+    0x00010000, 0x00010001, 0x00010100, 0x00010101,
+    0x01000000, 0x01000001, 0x01000100, 0x01000101,
+    0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const uint32_t RHs[16] =
+{
+    0x00000000, 0x01000000, 0x00010000, 0x01010000,
+    0x00000100, 0x01000100, 0x00010100, 0x01010100,
+    0x00000001, 0x01000001, 0x00010001, 0x01010001,
+    0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/*
+ * Initial Permutation macro
+ */
+#define DES_IP(X,Y)                                             \
+{                                                               \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T;                   \
+    X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF;                    \
+}
+
+/*
+ * Final Permutation macro
+ */
+#define DES_FP(X,Y)                                             \
+{                                                               \
+    X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T;                   \
+    Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF;                    \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+}
+
+/*
+ * DES round macro
+ */
+#define DES_ROUND(X,Y)                          \
+{                                               \
+    T = *SK++ ^ X;                              \
+    Y ^= SB8[ (T      ) & 0x3F ] ^              \
+         SB6[ (T >>  8) & 0x3F ] ^              \
+         SB4[ (T >> 16) & 0x3F ] ^              \
+         SB2[ (T >> 24) & 0x3F ];               \
+                                                \
+    T = *SK++ ^ ((X << 28) | (X >> 4));         \
+    Y ^= SB7[ (T      ) & 0x3F ] ^              \
+         SB5[ (T >>  8) & 0x3F ] ^              \
+         SB3[ (T >> 16) & 0x3F ] ^              \
+         SB1[ (T >> 24) & 0x3F ];               \
+}
+
+#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
+
+void des_init( des_context *ctx )
+{
+    memset( ctx, 0, sizeof( des_context ) );
+}
+
+void des_free( des_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    zeroize( ctx, sizeof( des_context ) );
+}
+
+void des3_init( des3_context *ctx )
+{
+    memset( ctx, 0, sizeof( des3_context ) );
+}
+
+void des3_free( des3_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    zeroize( ctx, sizeof( des3_context ) );
+}
+
+static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
+        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+        254 };
+
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        if( key[i] != odd_parity_table[key[i] / 2] )
+            return( 1 );
+
+    return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
+{
+    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < WEAK_KEY_COUNT; i++ )
+        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0 )
+            return( 1 );
+
+    return( 0 );
+}
+
+#if !defined(DES_SETKEY_ALT)
+void des_setkey( uint32_t SK[32], const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+    uint32_t X, Y, T;
+
+    GET_UINT32_BE( X, key, 0 );
+    GET_UINT32_BE( Y, key, 4 );
+
+    /*
+     * Permuted Choice 1
+     */
+    T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);
+    T =  ((Y      ) ^ X) & 0x10101010;  X ^= T; Y ^= (T      );
+
+    X =   (LHs[ (X      ) & 0xF] << 3) | (LHs[ (X >>  8) & 0xF ] << 2)
+        | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ]     )
+        | (LHs[ (X >>  5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+        | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+    Y =   (RHs[ (Y >>  1) & 0xF] << 3) | (RHs[ (Y >>  9) & 0xF ] << 2)
+        | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ]     )
+        | (RHs[ (Y >>  4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+        | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+    X &= 0x0FFFFFFF;
+    Y &= 0x0FFFFFFF;
+
+    /*
+     * calculate subkeys
+     */
+    for( i = 0; i < 16; i++ )
+    {
+        if( i < 2 || i == 8 || i == 15 )
+        {
+            X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;
+            Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;
+        }
+        else
+        {
+            X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;
+            Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;
+        }
+
+        *SK++ =   ((X <<  4) & 0x24000000) | ((X << 28) & 0x10000000)
+                | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+                | ((X <<  6) & 0x01000000) | ((X <<  9) & 0x00200000)
+                | ((X >>  1) & 0x00100000) | ((X << 10) & 0x00040000)
+                | ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)
+                | ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)
+                | ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)
+                | ((Y >> 14) & 0x00000200) | ((Y      ) & 0x00000100)
+                | ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+                | ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+                | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+        *SK++ =   ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+                | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+                | ((X >>  2) & 0x02000000) | ((X <<  1) & 0x01000000)
+                | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+                | ((X <<  3) & 0x00080000) | ((X >>  6) & 0x00040000)
+                | ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)
+                | ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)
+                | ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)
+                | ((Y      ) & 0x00000200) | ((Y <<  7) & 0x00000100)
+                | ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)
+                | ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+    }
+}
+#endif /* !DES_SETKEY_ALT */
+
+/*
+ * DES key schedule (56-bit, encryption)
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+    des_setkey( ctx->sk, key );
+
+    return( 0 );
+}
+
+/*
+ * DES key schedule (56-bit, decryption)
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    des_setkey( ctx->sk, key );
+
+    for( i = 0; i < 16; i += 2 )
+    {
+        SWAP( ctx->sk[i    ], ctx->sk[30 - i] );
+        SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+    }
+
+    return( 0 );
+}
+
+static void des3_set2key( uint32_t esk[96],
+                          uint32_t dsk[96],
+                          const unsigned char key[DES_KEY_SIZE*2] )
+{
+    int i;
+
+    des_setkey( esk, key );
+    des_setkey( dsk + 32, key + 8 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[30 - i];
+        dsk[i +  1] = esk[31 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        esk[i + 64] = esk[i    ];
+        esk[i + 65] = esk[i + 1];
+
+        dsk[i + 64] = dsk[i    ];
+        dsk[i + 65] = dsk[i + 1];
+    }
+}
+
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int des3_set2key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] )
+{
+    uint32_t sk[96];
+
+    des3_set2key( ctx->sk, sk, key );
+    zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int des3_set2key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] )
+{
+    uint32_t sk[96];
+
+    des3_set2key( sk, ctx->sk, key );
+    zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+static void des3_set3key( uint32_t esk[96],
+                          uint32_t dsk[96],
+                          const unsigned char key[24] )
+{
+    int i;
+
+    des_setkey( esk, key );
+    des_setkey( dsk + 32, key +  8 );
+    des_setkey( esk + 64, key + 16 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[94 - i];
+        dsk[i +  1] = esk[95 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        dsk[i + 64] = esk[30 - i];
+        dsk[i + 65] = esk[31 - i];
+    }
+}
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int des3_set3key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] )
+{
+    uint32_t sk[96];
+
+    des3_set3key( ctx->sk, sk, key );
+    zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int des3_set3key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] )
+{
+    uint32_t sk[96];
+
+    des3_set3key( sk, ctx->sk, key );
+    zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * DES-ECB block encryption/decryption
+ */
+#if !defined(DES_CRYPT_ECB_ALT)
+int des_crypt_ecb( des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] )
+{
+    int i;
+    uint32_t X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_UINT32_BE( X, input, 0 );
+    GET_UINT32_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_UINT32_BE( Y, output, 0 );
+    PUT_UINT32_BE( X, output, 4 );
+
+    return( 0 );
+}
+#endif /* !DES_CRYPT_ECB_ALT */
+
+#if defined(CIPHER_MODE_CBC)
+/*
+ * DES-CBC buffer encryption/decryption
+ */
+int des_crypt_cbc( des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == DES_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            des_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* DES_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            des_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* CIPHER_MODE_CBC */
+
+/*
+ * 3DES-ECB block encryption/decryption
+ */
+#if !defined(DES3_CRYPT_ECB_ALT)
+int des3_crypt_ecb( des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] )
+{
+    int i;
+    uint32_t X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_UINT32_BE( X, input, 0 );
+    GET_UINT32_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( X, Y );
+        DES_ROUND( Y, X );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_UINT32_BE( Y, output, 0 );
+    PUT_UINT32_BE( X, output, 4 );
+
+    return( 0 );
+}
+#endif /* !DES3_CRYPT_ECB_ALT */
+
+#if defined(CIPHER_MODE_CBC)
+/*
+ * 3DES-CBC buffer encryption/decryption
+ */
+int des3_crypt_cbc( des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output )
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == DES_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            des3_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* DES_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            des3_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* CIPHER_MODE_CBC */
+
+#endif /* !DES_ALT */
+
+#if defined(SELF_TEST)
+/*
+ * DES and 3DES test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+ */
+static const unsigned char des3_test_keys[24] =
+{
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+    0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+    0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+    0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+    { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+    { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+    { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+    { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+    { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+    { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+#if defined(CIPHER_MODE_CBC)
+static const unsigned char des3_test_iv[8] =
+{
+    0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+    { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+    { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+    { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+    { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+    { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+    { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+#endif /* CIPHER_MODE_CBC */
+
+/*
+ * Checkup routine
+ */
+int des_self_test( int verbose )
+{
+    int i, j, u, v, ret = 0;
+    des_context ctx;
+    des3_context ctx3;
+    unsigned char buf[8];
+#if defined(CIPHER_MODE_CBC)
+    unsigned char prv[8];
+    unsigned char iv[8];
+#endif
+
+    des_init( &ctx );
+    des3_init( &ctx3 );
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  DES%c-ECB-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            des_setkey_dec( &ctx, des3_test_keys );
+            break;
+
+        case 1:
+            des_setkey_enc( &ctx, des3_test_keys );
+            break;
+
+        case 2:
+            des3_set2key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 3:
+            des3_set2key_enc( &ctx3, des3_test_keys );
+            break;
+
+        case 4:
+            des3_set3key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 5:
+            des3_set3key_enc( &ctx3, des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        for( j = 0; j < 10000; j++ )
+        {
+            if( u == 0 )
+                des_crypt_ecb( &ctx, buf, buf );
+            else
+                des3_crypt_ecb( &ctx3, buf, buf );
+        }
+
+        if( ( v == DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+            ( v != DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+#if defined(CIPHER_MODE_CBC)
+    /*
+     * CBC mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  DES%c-CBC-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  des3_test_iv,  8 );
+        memcpy( prv, des3_test_iv,  8 );
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            des_setkey_dec( &ctx, des3_test_keys );
+            break;
+
+        case 1:
+            des_setkey_enc( &ctx, des3_test_keys );
+            break;
+
+        case 2:
+            des3_set2key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 3:
+            des3_set2key_enc( &ctx3, des3_test_keys );
+            break;
+
+        case 4:
+            des3_set3key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 5:
+            des3_set3key_enc( &ctx3, des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        if( v == DES_DECRYPT )
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                if( u == 0 )
+                    des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+            }
+        }
+        else
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                unsigned char tmp[8];
+
+                if( u == 0 )
+                    des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+                memcpy( tmp, prv, 8 );
+                memcpy( prv, buf, 8 );
+                memcpy( buf, tmp, 8 );
+            }
+
+            memcpy( buf, prv, 8 );
+        }
+
+        if( ( v == DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+            ( v != DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+#endif /* CIPHER_MODE_CBC */
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+exit:
+    des_free( &ctx );
+    des3_free( &ctx3 );
+
+    return( ret );
+}
+
+#endif /* SELF_TEST */
+
+//#endif /* DES_C */

+ 695 - 0
MD5Test/lzari.cpp

@@ -0,0 +1,695 @@
+/**************************************************************
+	LZARI.C -- A Data Compression Program
+	(tab = 4 spaces)
+***************************************************************
+	4/7/1989 Haruhiko Okumura
+	Use, distribute, and modify this program freely.
+	Please send me your improved versions.
+		PC-VAN		SCIENCE
+		NIFTY-Serve	PAF01022
+		CompuServe	74050,1022
+**************************************************************/
+
+/********************************************************************
+	lzari.cpp -- A Data Compression Class
+	created:	2004/10/04
+	created:	4:10:2004   16:44
+	file base:	lzari
+	file ext:	cpp
+	author:	阙荣文	(querw@sina.com)
+	
+	purpose: 如上所述,lzari.c提供了lzari压缩算法的实现,基于lzari.c我把它
+			 做成了一个c++类方便使用
+*********************************************************************/
+
+#include "stdafx.h"	  
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <string.h>
+//#include <ctype.h>
+#include "Lzari.h"
+
+LZARI::LZARI()
+{
+	infile = NULL;
+	outfile = NULL;
+
+	textsize = 0;
+	codesize = 0;
+	printcount = 0;
+
+	low = 0;
+	high = Q4;
+	value = 0;
+	shifts = 0;/* counts for magnifying low and high around Q2 */
+	
+	m_bMem = FALSE;
+
+	m_pInBuffer = NULL;
+	m_nInLength = 0;
+	m_nInCur = 0;
+
+	//m_pOutBuffer = NULL;
+	m_nOutLength = 0;
+//	m_nOutCur = 0;
+
+	buffer_putbit = 0;
+	mask_putbit = 128;
+
+	buffer_getbit = 0;
+	mask_getbit = 0;
+
+}
+
+LZARI::~LZARI()
+{
+	Release();
+}
+
+void LZARI::Error(char *message)
+{
+#ifdef _OUTPUT_STATUS
+	printf("\n%s\n", message);
+#endif
+	//exit(EXIT_FAILURE);
+	int e = 1;
+	throw e;
+}
+
+void LZARI::PutBit(int bit)  /* Output one bit (bit = 0,1) */
+{
+	if (bit) buffer_putbit |= mask_putbit;
+	if ((mask_putbit >>= 1) == 0) 
+	{
+		if (!m_bMem)
+		{
+			if (putc(buffer_putbit, outfile) == EOF) Error("Write Error");
+		}
+		else
+		{
+			//if (m_nOutCur == m_nOutLength) Error("Write Error");
+			//m_pOutBuffer[m_nOutCur++] = buffer;
+			m_OutBuffer.push_back(buffer_putbit);
+			//m_nOutCur++;
+		}
+		buffer_putbit = 0;  
+		mask_putbit = 128;  
+		codesize++;
+	}
+}
+
+void LZARI::FlushBitBuffer(void)  /* Send remaining bits */
+{
+	int  i;
+	
+	for (i = 0; i < 7; i++) PutBit(0);
+}
+
+int LZARI::GetBit(void)  /* Get one bit (0 or 1) */
+{	
+	if ((mask_getbit >>= 1) == 0) 
+	{
+		if (!m_bMem)
+			buffer_getbit = getc(infile);
+		else if (m_nInCur < m_nInLength)
+			buffer_getbit = m_pInBuffer[m_nInCur++];
+		mask_getbit = 128;
+	}
+	return ((buffer_getbit & mask_getbit) != 0);
+}
+
+/********** LZSS with multiple binary trees **********/
+
+void LZARI::InitTree(void)  /* Initialize trees */
+{
+	int  i;
+
+	/* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
+	   left children of node i.  These nodes need not be initialized.
+	   Also, dad[i] is the parent of node i.  These are initialized to
+	   NIL (= N), which stands for 'not used.'
+	   For i = 0 to 255, rson[N + i + 1] is the root of the tree
+	   for strings that begin with character i.  These are initialized
+	   to NIL.  Note there are 256 trees. */
+
+	for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;	/* root */
+	for (i = 0; i < N; i++) dad[i] = NIL;	/* node */
+}
+
+void LZARI::InsertNode(int r)
+	/* Inserts string of length F, text_buf[r..r+F-1], into one of the
+	   trees (text_buf[r]'th tree) and returns the longest-match position
+	   and length via the global variables match_position and match_length.
+	   If match_length = F, then removes the old node in favor of the new
+	   one, because the old one will be deleted sooner.
+	   Note r plays double role, as tree node and position in buffer. */
+{
+	int  i, p, cmp, temp;
+	unsigned char  *key;
+
+	cmp = 1;  key = &text_buf[r];  p = N + 1 + key[0];
+	rson[r] = lson[r] = NIL;  match_length = 0;
+	for ( ; ; ) 
+	{
+		if (cmp >= 0) 
+		{
+			if (rson[p] != NIL) p = rson[p];
+			else {  rson[p] = r;  dad[r] = p;  return;  }
+		} else 
+		{
+			if (lson[p] != NIL) p = lson[p];
+			else {  lson[p] = r;  dad[r] = p;  return;  }
+		}
+		for (i = 1; i < F; i++)
+			if ((cmp = key[i] - text_buf[p + i]) != 0)  break;
+		if (i > THRESHOLD) 
+		{
+			if (i > match_length) 
+			{
+				match_position = (r - p) & (N - 1);
+				if ((match_length = i) >= F) break;
+			} else if (i == match_length) 
+			{
+				if ((temp = (r - p) & (N - 1)) < match_position)
+					match_position = temp;
+			}
+		}
+	}
+	dad[r] = dad[p];  lson[r] = lson[p];  rson[r] = rson[p];
+	dad[lson[p]] = r;  dad[rson[p]] = r;
+	if (rson[dad[p]] == p) rson[dad[p]] = r;
+	else                   lson[dad[p]] = r;
+	dad[p] = NIL;  /* remove p */
+}
+
+void LZARI::DeleteNode(int p)  /* Delete node p from tree */
+{
+	int  q;
+	
+	if (dad[p] == NIL) return;  /* not in tree */
+	if (rson[p] == NIL) q = lson[p];
+	else if (lson[p] == NIL) q = rson[p];
+	else 
+	{
+		q = lson[p];
+		if (rson[q] != NIL) 
+		{
+			do {  q = rson[q];  } while (rson[q] != NIL);
+			rson[dad[q]] = lson[q];  dad[lson[q]] = dad[q];
+			lson[q] = lson[p];  dad[lson[p]] = q;
+		}
+		rson[q] = rson[p];  dad[rson[p]] = q;
+	}
+	dad[q] = dad[p];
+	if (rson[dad[p]] == p) rson[dad[p]] = q;
+	else                   lson[dad[p]] = q;
+	dad[p] = NIL;
+}
+
+/********** Arithmetic Compression **********/
+
+/*  If you are not familiar with arithmetic compression, you should read
+		I. E. Witten, R. M. Neal, and J. G. Cleary,
+			Communications of the ACM, Vol. 30, pp. 520-540 (1987),
+	from which much have been borrowed.  */
+
+	/* character code = 0, 1, ..., N_CHAR - 1 */
+
+
+void LZARI::StartModel(void)  /* Initialize model */
+{
+	int ch, sym, i;
+	
+	sym_cum[N_CHAR] = 0;
+	for (sym = N_CHAR; sym >= 1; sym--) 
+	{
+		ch = sym - 1;
+		char_to_sym[ch] = sym;  sym_to_char[sym] = ch;
+		sym_freq[sym] = 1;
+		sym_cum[sym - 1] = sym_cum[sym] + sym_freq[sym];
+	}
+	sym_freq[0] = 0;  /* sentinel (!= sym_freq[1]) */
+	position_cum[N] = 0;
+	for (i = N; i >= 1; i--)
+		position_cum[i - 1] = position_cum[i] + 10000 / (i + 200);
+			/* empirical distribution function (quite tentative) */
+			/* Please devise a better mechanism! */
+}
+
+void LZARI::UpdateModel(int sym)
+{
+	int i, c, ch_i, ch_sym;
+	
+	if (sym_cum[0] >= MAX_CUM) 
+	{
+		c = 0;
+		for (i = N_CHAR; i > 0; i--) 
+		{
+			sym_cum[i] = c;
+			c += (sym_freq[i] = (sym_freq[i] + 1) >> 1);
+		}
+		sym_cum[0] = c;
+	}
+	for (i = sym; sym_freq[i] == sym_freq[i - 1]; i--) ;
+	if (i < sym) 
+	{
+		ch_i = sym_to_char[i];    ch_sym = sym_to_char[sym];
+		sym_to_char[i] = ch_sym;  sym_to_char[sym] = ch_i;
+		char_to_sym[ch_i] = sym;  char_to_sym[ch_sym] = i;
+	}
+	sym_freq[i]++;
+	while (--i >= 0) sym_cum[i]++;
+}
+
+void LZARI::Output(int bit)  /* Output 1 bit, followed by its complements */
+{
+	PutBit(bit);
+	for ( ; shifts > 0; shifts--) PutBit(! bit);
+}
+
+void LZARI::EncodeChar(int ch)
+{
+	int  sym;
+	unsigned long int  range;
+
+	sym = char_to_sym[ch];
+	range = high - low;
+	high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
+	low +=       (range * sym_cum[sym    ]) / sym_cum[0];
+	for ( ; ; ) 
+	{
+		if (high <= Q2) Output(0);
+		else if (low >= Q2) 
+		{
+			Output(1);  low -= Q2;  high -= Q2;
+		} 
+		else if (low >= Q1 && high <= Q3) 
+		{
+			shifts++;  low -= Q1;  high -= Q1;
+		} 
+		else break;
+		low += low;
+		high += high;
+	}
+	UpdateModel(sym);
+}
+
+void LZARI::EncodePosition(int position)
+{
+	unsigned long int  range;
+
+	range = high - low;
+	high = low + (range * position_cum[position    ]) / position_cum[0];
+	low +=       (range * position_cum[position + 1]) / position_cum[0];
+	for ( ; ; ) 
+	{
+		if (high <= Q2) Output(0);
+		else if (low >= Q2) 
+		{
+			Output(1);  low -= Q2;  high -= Q2;
+		} 
+		else if (low >= Q1 && high <= Q3) 
+		{
+			shifts++;  low -= Q1;  high -= Q1;
+		} 
+		else break;
+		low += low;
+		high += high;
+	}
+}
+
+void LZARI::EncodeEnd(void)
+{
+	shifts++;
+	if (low < Q1) Output(0);  else Output(1);
+	FlushBitBuffer();  /* flush bits remaining in buffer */
+}
+
+int LZARI::BinarySearchSym(unsigned int x)
+	/* 1      if x >= sym_cum[1],
+	   N_CHAR if sym_cum[N_CHAR] > x,
+	   i such that sym_cum[i - 1] > x >= sym_cum[i] otherwise */
+{
+	int i, j, k;
+	
+	i = 1;  j = N_CHAR;
+	while (i < j) 
+	{
+		k = (i + j) / 2;
+		if (sym_cum[k] > x) i = k + 1;  else j = k;
+	}
+	return i;
+}
+
+int LZARI::BinarySearchPos(unsigned int x)
+	/* 0 if x >= position_cum[1],
+	   N - 1 if position_cum[N] > x,
+	   i such that position_cum[i] > x >= position_cum[i + 1] otherwise */
+{
+	int i, j, k;
+	
+	i = 1;  j = N;
+	while (i < j)
+	{
+		k = (i + j) / 2;
+		if (position_cum[k] > x) i = k + 1;  else j = k;
+	}
+	return i - 1;
+}
+
+void LZARI::StartDecode(void)
+{
+	int i;
+
+	for (i = 0; i < M + 2; i++)
+		value = 2 * value + GetBit();
+}
+
+int LZARI::DecodeChar(void)
+{
+	int	 sym, ch;
+	unsigned long int  range;
+	
+	range = high - low;
+	sym = BinarySearchSym((unsigned int)
+		(((value - low + 1) * sym_cum[0] - 1) / range));
+	high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
+	low +=       (range * sym_cum[sym    ]) / sym_cum[0];
+	for ( ; ; ) {
+		if (low >= Q2) {
+			value -= Q2;  low -= Q2;  high -= Q2;
+		} else if (low >= Q1 && high <= Q3) {
+			value -= Q1;  low -= Q1;  high -= Q1;
+		} else if (high > Q2) break;
+		low += low;  high += high;
+		value = 2 * value + GetBit();
+	}
+	ch = sym_to_char[sym];
+	UpdateModel(sym);
+	return ch;
+}
+
+int LZARI::DecodePosition(void)
+{
+	int position;
+	unsigned long int  range;
+	
+	range = high - low;
+	position = BinarySearchPos((unsigned int)
+		(((value - low + 1) * position_cum[0] - 1) / range));
+	high = low + (range * position_cum[position    ]) / position_cum[0];
+	low +=       (range * position_cum[position + 1]) / position_cum[0];
+	for ( ; ; ) {
+		if (low >= Q2) {
+			value -= Q2;  low -= Q2;  high -= Q2;
+		} else if (low >= Q1 && high <= Q3) {
+			value -= Q1;  low -= Q1;  high -= Q1;
+		} else if (high > Q2) break;
+		low += low;  high += high;
+		value = 2 * value + GetBit();
+	}
+	return position;
+}
+
+/********** Encode and Decode **********/
+
+void LZARI::Encode(void)
+{
+	int  i, c, len, r, s, last_match_length;
+	
+	if(!m_bMem)
+	{
+		fseek(infile, 0L, SEEK_END);
+		textsize = ftell(infile);
+		if (fwrite(&textsize, sizeof textsize, 1, outfile) < 1)
+			Error("Write Error");  /* output size of text */
+		codesize += sizeof textsize;
+		if (textsize == 0) return;
+		rewind(infile);
+		textsize = 0;
+	}
+	else
+	{
+		textsize = m_nInLength;
+		m_OutBuffer.resize(sizeof textsize);
+		memcpy(&m_OutBuffer[0],&textsize,sizeof textsize);
+		//m_nOutCur += sizeof textsize;
+		codesize += sizeof textsize;
+		if(textsize == 0) return;
+		m_nInCur = 0;
+		textsize = 0;
+	}
+	
+	StartModel(); 
+	InitTree();
+	s = 0;  r = N - F;
+	for (i = s; i < r; i++) text_buf[i] = ' ';
+	if(!m_bMem)
+		for (len = 0; len < F && (c = getc(infile)) != EOF; len++) text_buf[r + len] = c;
+	else
+		for (len = 0; len < F && m_nInCur < m_nInLength ; len++)
+		{
+			c = m_pInBuffer[m_nInCur++];
+			text_buf[r + len] = c;
+		}
+	
+	textsize = len;
+	for (i = 1; i <= F; i++) InsertNode(r - i);
+	
+	InsertNode(r);
+	
+	do {
+		if (match_length > len) match_length = len;
+		if (match_length <= THRESHOLD) 
+		{
+			match_length = 1;  EncodeChar(text_buf[r]);
+		} 
+		else 
+		{
+			EncodeChar(255 - THRESHOLD + match_length);
+			EncodePosition(match_position - 1);
+		}
+		last_match_length = match_length;
+		if(!m_bMem)
+		{
+			for (i = 0; i < last_match_length && (c = getc(infile)) != EOF; i++) 
+			{
+				DeleteNode(s);  text_buf[s] = c;
+				if (s < F - 1) text_buf[s + N] = c;
+				s = (s + 1) & (N - 1);
+				r = (r + 1) & (N - 1);
+				InsertNode(r);
+			}
+		}
+		else
+		{			
+			for (i = 0; i < last_match_length && m_nInCur < m_nInLength ; i++) 
+			{
+				c = m_pInBuffer[m_nInCur++];
+				DeleteNode(s);  
+				text_buf[s] = c;
+				if (s < F - 1) text_buf[s + N] = c;
+				s = (s + 1) & (N - 1);
+				r = (r + 1) & (N - 1);
+				InsertNode(r);
+			}
+		}
+		if ((textsize += i) > printcount) 
+		{
+#ifdef _OUTPUT_STATUS
+			printf("%12ld\r", textsize);
+#endif	
+			printcount += 1024;
+		}
+		while (i++ < last_match_length) 
+		{
+			DeleteNode(s);
+			s = (s + 1) & (N - 1);
+			r = (r + 1) & (N - 1);
+			if (--len) InsertNode(r);
+		}
+	} while (len > 0);
+	
+	EncodeEnd();
+
+#ifdef _OUTPUT_STATUS	
+	printf("In : %lu bytes\n", textsize);
+	printf("Out: %lu bytes\n", codesize);
+	printf("Out/In: %.3f\n", (double)codesize / textsize);
+#endif
+}
+
+void LZARI::Decode(void)
+{
+	int  i, j, k, r, c;
+	unsigned long int  count;
+
+	if (!m_bMem)
+	{
+		if (fread(&textsize, sizeof textsize, 1, infile) < 1)
+			Error("Read Error");  /* read size of text */
+	}
+	else
+	{
+		if(m_nInLength < sizeof textsize)
+			Error("Read Error");
+		memcpy(&textsize,m_pInBuffer + m_nInCur,sizeof textsize);
+		
+		//m_OutBuffer.reserve(textsize);
+		m_nOutLength = textsize;
+		//m_nOutCur = 0;
+		
+		m_nInCur += sizeof textsize;
+	}
+	
+	if (textsize == 0) return;
+	
+	StartDecode();
+	StartModel();
+	
+	for (i = 0; i < N - F; i++) text_buf[i] = ' ';
+	r = N - F;
+	for (count = 0; count < textsize; ) 
+	{
+		c = DecodeChar();
+		if (c < 256) 
+		{
+			if(!m_bMem)
+				putc(c, outfile);
+			else
+			{
+				//m_OutBuffer[m_nOutCur++] = c;
+				m_OutBuffer.push_back(c);
+				//m_nOutCur++;
+			}
+			text_buf[r++] = c;
+			r &= (N - 1);
+			count++;
+		}
+		else
+		{
+			i = (r - DecodePosition() - 1) & (N - 1);
+			j = c - 255 + THRESHOLD;
+			for (k = 0; k < j; k++) 
+			{
+				c = text_buf[(i + k) & (N - 1)];
+				if(!m_bMem)
+					putc(c, outfile);
+				else
+				{
+				//	m_pOutBuffer[m_nOutCur++] = c;
+					m_OutBuffer.push_back(c);
+					//m_nOutCur ++;
+				}
+				text_buf[r++] = c;
+				r &= (N - 1);
+				count++;
+			}
+		}
+		if (count > printcount) 
+		{
+#ifdef _OUTPUT_STATUS
+			printf("%12lu\r", count);
+#endif			
+			printcount += 1024;
+		}
+	}
+
+#ifdef _OUTPUT_STATUS
+	printf("%12lu\n", count);
+#endif
+}
+
+void LZARI::Compress(const char *lpszInfile,const char *lpszOutfile)
+{
+	m_bMem = FALSE;
+	
+	infile = fopen(lpszInfile,"rb");
+	outfile = fopen(lpszOutfile,"wb");
+	if(infile && outfile)
+	{
+		Encode();
+		fclose(infile);
+		fclose(outfile);
+		infile = NULL;
+		outfile = NULL;
+	}
+}
+
+void LZARI::UnCompress(const char *lpszInfile,const char *lpszOutfile)
+{
+	m_bMem = FALSE;
+
+	infile = fopen(lpszInfile,"rb");
+	outfile = fopen(lpszOutfile,"wb");
+	if(infile && outfile)
+	{
+		Decode();
+		fclose(infile);
+		fclose(outfile);
+		infile = NULL;
+		outfile = NULL;
+	}
+}
+
+void LZARI::Compress(const BYTE *pInBuffer,int nInLength,const BYTE *&pOutBuffer ,int &nOutLength)
+{
+	m_pInBuffer = pInBuffer;
+	m_nInLength = nInLength;
+	m_nInCur = 0;
+
+//	m_nOutCur = 0;
+
+	m_bMem = TRUE;
+	Encode();
+	pOutBuffer = &m_OutBuffer[0];
+	nOutLength = m_OutBuffer.size();
+}
+
+
+
+void LZARI::Release()
+{
+	if(!m_OutBuffer.empty())
+	{
+		infile = NULL;
+		outfile = NULL;
+		
+		textsize = 0;
+		codesize = 0;
+		printcount = 0;
+		
+		low = 0;
+		high = Q4;
+		value = 0;
+		shifts = 0;
+		
+		m_bMem = FALSE;
+		
+		m_pInBuffer = NULL;
+		m_nInLength = 0;
+		m_nInCur = 0;
+		
+		m_OutBuffer.clear();
+		m_nOutLength = 0;
+
+		buffer_putbit = 0;
+		mask_putbit = 128;
+		
+		buffer_getbit = 0;
+		mask_getbit = 0;
+	}
+}
+void LZARI::UnCompress(const BYTE *pInBuffer,int nInLength,const BYTE *&pOutBuffer ,int &nOutLength)
+{
+	m_pInBuffer = pInBuffer;
+	m_nInLength = nInLength;
+	m_nInCur = 0;
+
+	m_bMem = TRUE;
+	Decode();
+	pOutBuffer = &m_OutBuffer[0];
+	nOutLength = m_OutBuffer.size();
+	m_OutBuffer.push_back(0);
+
+}

+ 140 - 0
MD5Test/lzari.h

@@ -0,0 +1,140 @@
+
+/**************************************************************
+	LZARI.C -- A Data Compression Program
+	(tab = 4 spaces)
+***************************************************************
+	4/7/1989 Haruhiko Okumura
+	Use, distribute, and modify this program freely.
+	Please send me your improved versions.
+		PC-VAN		SCIENCE
+		NIFTY-Serve	PAF01022
+		CompuServe	74050,1022
+**************************************************************/
+
+/********** Bit I/O **********/
+#ifndef _FILE_H_COMPRESSION_LZARI_
+#define  _FILE_H_COMPRESSION_LZARI_
+//#pragma warning(disable:4786)
+// #include <VECTOR>
+
+// #define _OUTPUT_STATUS
+
+#define N		 4096	/* size of ring buffer */
+#define F		   60	/* upper limit for match_length */
+#define THRESHOLD	2   /* encode string into position and length
+						   if match_length is greater than this */
+#define NIL			N	/* index for root of binary search trees */
+/********** Arithmetic Compression **********/
+
+/*  If you are not familiar with arithmetic compression, you should read
+		I. E. Witten, R. M. Neal, and J. G. Cleary,
+			Communications of the ACM, Vol. 30, pp. 520-540 (1987),
+	from which much have been borrowed.  */
+
+#define M   15
+
+/*	Q1 (= 2 to the M) must be sufficiently large, but not so
+	large as the unsigned long 4 * Q1 * (Q1 - 1) overflows.  */
+
+#define Q1  (1UL << M)
+#define Q2  (2 * Q1)
+#define Q3  (3 * Q1)
+#define Q4  (4 * Q1)
+#define MAX_CUM (Q1 - 1)
+
+#define N_CHAR  (256 - THRESHOLD + F)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <VECTOR>
+
+
+
+
+typedef unsigned char BYTE;
+#define FALSE   0
+#define TRUE    1
+
+class LZARI
+{
+public:	
+	LZARI();
+	virtual ~LZARI();
+protected:
+	FILE  *infile, *outfile;
+	unsigned long textsize;
+	unsigned long codesize;
+	unsigned long printcount;
+	unsigned char  text_buf[N + F - 1];	/* ring buffer of size N,with extra F-1 bytes to facilitate string comparison */
+	int	match_position;
+	int	match_length;  /* of longest match.  These areset by the InsertNode() procedure. */
+	int	lson[N + 1];
+	int rson[N + 257];
+	int dad[N + 1];  /* left & right children &parents -- These constitute binary search trees. */
+
+	/* character code = 0, 1, ..., N_CHAR - 1 */
+
+	unsigned long low;
+	unsigned long high;
+	unsigned long value;
+	int  shifts;  /* counts for magnifying low and high around Q2 */
+	int  char_to_sym[N_CHAR];
+	int sym_to_char[N_CHAR + 1];
+	unsigned int sym_freq[N_CHAR + 1];  /* frequency for symbols */
+	unsigned int sym_cum[N_CHAR + 1];   /* cumulative freq for symbols */
+	unsigned int position_cum[N + 1];   /* cumulative freq for positions */
+
+	// Compress in memory;
+	bool m_bMem;
+
+	std::vector<BYTE> m_OutBuffer;
+	//BYTE *m_pOutBuffer;
+	int m_nOutLength;
+	//int m_nOutCur;
+
+	const BYTE *m_pInBuffer;
+	int m_nInLength;
+	int m_nInCur;
+
+	unsigned int  buffer_putbit, mask_putbit;
+	unsigned int  buffer_getbit, mask_getbit;
+
+private:
+	void Error(char *message);
+	void PutBit(int bit);  /* Output one bit (bit = 0,1) */
+	void FlushBitBuffer(void);  /* Send remaining bits */
+	int GetBit(void);  /* Get one bit (0 or 1) */
+
+/********** LZSS with multiple binary trees **********/
+
+	void InitTree(void);  /* Initialize trees */
+	void InsertNode(int r);
+	void DeleteNode(int p);  /* Delete node p from tree */
+	void StartModel(void); /* Initialize model */
+	void UpdateModel(int sym);
+	void Output(int bit);  /* Output 1 bit, followed by its complements */
+	void EncodeChar(int ch);
+	void EncodePosition(int position);
+	void EncodeEnd(void);
+	int BinarySearchSym(unsigned int x);
+	int BinarySearchPos(unsigned int x);
+	void StartDecode(void);
+	int DecodeChar(void);
+	int DecodePosition(void);
+
+	void Encode(void);
+	void Decode(void);
+
+public:
+	void Compress(const char *lpszInfile,const char *lpszOutfile);
+	void UnCompress(const char *lpszInfile,const char *lpszOutfile);
+
+	void Compress(const BYTE *pInBuffer,int nInLength,const BYTE * &pOutBuffer ,int &nOutLength);
+	void UnCompress(const BYTE *pInBuffer,int nInLength,const BYTE * &pOutBuffer,int &nOutLength);
+	
+	void Release();
+};
+
+#endif

+ 290 - 0
MD5Test/md5.cpp

@@ -0,0 +1,290 @@
+#include "StdAfx.h"
+#include "MD5.h"
+#include <strsafe.h>
+
+// MD5Transform函数使用的常量;
+#define S11 7  
+#define S12 12  
+#define S13 17  
+#define S14 22  
+#define S21 5  
+#define S22 9  
+#define S23 14  
+#define S24 20  
+#define S31 4  
+#define S32 11  
+#define S33 16  
+#define S34 23  
+#define S41 6  
+#define S42 10  
+#define S43 15  
+#define S44 21  
+
+// 基础的MD5函数(四个非线性函数(每轮一个))
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+// 将x左移n个bit位;
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+// FF, GG, HH, 和 II 是用来转换 Rounds1,2,3,4的 ;
+// Rotation is separate from addition to prevent recomputation;
+#define FF(a, b, c, d, x, s, ac) { \
+	(a) += F ((b), (c), (d)) + (x) + (UINT32)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define GG(a, b, c, d, x, s, ac) { \
+	(a) += G ((b), (c), (d)) + (x) + (UINT32)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define HH(a, b, c, d, x, s, ac) { \
+	(a) += H ((b), (c), (d)) + (x) + (UINT32)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define II(a, b, c, d, x, s, ac) { \
+	(a) += I ((b), (c), (d)) + (x) + (UINT32)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+
+static unsigned char PADDING[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+CMD5::CMD5(void)
+{
+	m_nInputLen = 0;
+	m_pInputText = NULL;
+	m_bValidDigest = FALSE;
+	memset(m_digestStr,0,33);
+}
+
+CMD5::CMD5(IN CONST BYTE* szInput,IN CONST INT& nInputLen)
+{
+	m_pInputText =  const_cast<BYTE*>(szInput); 
+	m_nInputLen = nInputLen;
+	memset(m_digestStr, 0, 33);
+	m_bValidDigest = CalcDigest();
+}
+
+CMD5::~CMD5(void)
+{
+
+}
+
+void CMD5::Decode(IN UINT32 *output, IN UINT8 *input, IN CONST UINT32& len)
+{
+	UINT32 i, j;
+	for (i = 0, j = 0; j < len; i++, j += 4)
+		output[i] = (input[j]) | ((input[j+1]) << 8) | ((input[j+2]) << 16) | ((input[j+3]) << 24);
+}
+
+void CMD5::Encode(IN UINT8 *output, IN UINT32 *input, IN CONST UINT32& len)
+{
+	UINT32 i, j;
+	for (i = 0, j = 0; j < len; i++, j += 4) 
+	{
+		output[j] = input[i] & 0xFF;
+		output[j+1] = (input[i] >> 8) & 0xFF;
+		output[j+2] = (input[i] >> 16) & 0xFF;
+		output[j+3] = (input[i] >> 24) & 0xFF;
+	}
+}
+
+void CMD5::MD5Init(IN MD5_CTX* md5ctx)
+{
+	md5ctx->count[0] = md5ctx->count[1] = 0;
+	// 用魔数常量来初始化;
+	md5ctx->state[0] = 0x67452301;
+	md5ctx->state[1] = 0xefcdab89;
+	md5ctx->state[2] = 0x98badcfe;
+	md5ctx->state[3] = 0x10325476;
+}
+
+void CMD5::MD5Update(IN MD5_CTX* md5ctx, IN UINT8* Input, IN CONST UINT32& InputLen)
+{
+	UINT32 i, nIndex, nPartLen;
+
+	// 计算出模64(0x3F)后的值;
+	nIndex = (md5ctx->count[0] >> 3) & 0x3F;
+
+	// 更新bit位数;
+	if ( (md5ctx->count[0] += (InputLen << 3))< (InputLen << 3) )
+		md5ctx->count[1]++;
+	md5ctx->count[1] += (InputLen >> 29);
+
+	// 设置缓冲区的字节数;
+	nPartLen = 64 - nIndex;
+
+	// 尽可能多的转换;
+	if (InputLen >= nPartLen) 
+	{
+		memcpy(&md5ctx->buffer[nIndex], Input, nPartLen);
+		MD5Transform(md5ctx->state, md5ctx->buffer);
+
+		for (i = nPartLen; i + 63 < InputLen; i += 64)
+			MD5Transform(md5ctx->state, &Input[i]);
+
+		nIndex = 0;
+	}
+	else
+		i = 0;
+
+	// 复制剩余的缓冲内容;
+	memcpy(&md5ctx->buffer[nIndex], &Input[i], InputLen-i);
+}
+
+void CMD5::MD5Transform(IN UINT32 state[4], IN UINT8 block[64] )
+{
+	UINT32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+	Decode(x, block, 64);
+
+	// 第一轮分组运算;
+	FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+	FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+	FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+	FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+	FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+	FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+	FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+	FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+	FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+	FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+	FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+	FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+	FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+	FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+	FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+	FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+	// 第二轮分组运算;
+	GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+	GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+	GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+	GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+	GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+	GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+	GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+	GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+	GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+	GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+	GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+	GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+	GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+	GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+	GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+	GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+	// 第三轮分组运算;
+	HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+	HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+	HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+	HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+	HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+	HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+	HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+	HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+	HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+	HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+	HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+	HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+	HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+	HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+	HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+	HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+	// 第四轮分组运算;
+	II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+	II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+	II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+	II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+	II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+	II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+	II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+	II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+	II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+	II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+	II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+	II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+	II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+	II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+	II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+	II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+
+	memset(x, 0, sizeof(x));
+}
+
+void CMD5::MD5Final(IN UINT8 digest[16], IN MD5_CTX* md5ctx)
+{
+	UINT8 bits[8];
+	UINT32 index, padLen;
+
+	// 保存2进制位数;
+	Encode(bits, md5ctx->count, 8);
+
+	/* Pad out to 56 mod 64.*/
+	index = (unsigned int)((md5ctx->count[0] >> 3) & 0x3f);
+	padLen = (index < 56) ? (56 - index) : (120 - index);
+	MD5Update(md5ctx, PADDING, padLen);
+
+	/* Append length (before padding) */
+	MD5Update(md5ctx, bits, 8);
+
+	/* Store state in digest */
+	Encode(digest, md5ctx->state, 16);
+
+	memset(md5ctx, 0, sizeof(*md5ctx));
+}
+
+void CMD5::SetBYTEText(IN CONST BYTE* szInput, IN CONST INT& nInputLen)
+{
+	m_pInputText =  const_cast<BYTE*>(szInput); 
+	m_nInputLen = nInputLen;
+	m_bValidDigest = CalcDigest();
+}
+
+BOOL CMD5::CalcDigest()
+{
+	MD5_CTX md5ctx;
+	// 初始化md5;
+	MD5Init(&md5ctx); 
+	MD5Update(&md5ctx, m_pInputText, m_nInputLen);
+	MD5Final(m_digest,&md5ctx);
+
+	// 转化为32位的16进制字符;
+	int p = 0;
+	for (int i = 0; i < 16; i++)
+	{
+		StringCchPrintf(&m_digestStr[p], 3, _T("%02x"), m_digest[i]);
+		p += 2;
+	}
+
+	return TRUE;
+}
+
+CONST TCHAR* CMD5::GetMD5Digest()
+{
+	if( m_bValidDigest )
+		return m_digestStr;
+	
+	return NULL;
+}
+

+ 55 - 0
MD5Test/md5.h

@@ -0,0 +1,55 @@
+#ifndef __MD5_20160124__
+#define __MD5_20160124__
+
+#pragma once
+
+// MD5的Context结构体;
+typedef struct 
+{
+	// 状态 (ABCD);
+	UINT32 state[4];     
+	// 2进制位个数, modulo 2^64 (lsb first);
+	UINT32 count[2];  
+	// 输入的缓冲区;
+	UINT8  buffer[64];                        
+} MD5_CTX;
+
+class CMD5
+{
+public:
+	CMD5(void);
+	CMD5(IN CONST BYTE* szInput,IN CONST INT& nInputLen);
+	~CMD5(void);
+
+private:
+	// md5核心算法;
+	void MD5Init(IN MD5_CTX* md5ctx);
+	void MD5Update(IN MD5_CTX* md5ctx, IN UINT8* Input, IN CONST UINT32& InputLen);
+	void MD5Transform(IN UINT32 state[4], IN UINT8 block[64] );
+	void MD5Final(IN UINT8 digest[16], IN MD5_CTX* md5ctx);
+
+	void Decode(IN UINT32 *output, IN UINT8 *input, IN CONST UINT32& len);
+	void Encode(IN UINT8 *output, IN UINT32 *input, IN CONST UINT32& len);
+
+private:
+	// md5封装;
+	// 计算md5是否成功;
+	BOOL	m_bValidDigest;
+	// md5计算后的结果值;
+	UINT8	m_digest[16];
+	// 将md5数值转化为16进制字符串;
+	TCHAR	m_digestStr[33];
+	// 要计算的字符串;
+	BYTE*	m_pInputText;
+	// 要计算的字符串长度;
+	INT     m_nInputLen;
+	// 计算出md5转化结果;
+	BOOL CalcDigest();
+
+	// 对外接口;
+public:
+	void SetBYTEText(IN CONST BYTE* szInput,IN CONST INT& nInputLen);
+	CONST TCHAR* GetMD5Digest();
+};
+
+#endif  //__MD5_20160124__

+ 320 - 0
MD5Test/md5c.cpp

@@ -0,0 +1,320 @@
+//See internet RFC 1321, "The MD5 Message-Digest Algorithm"
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+*/
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+*/
+#include "stdafx.h"
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+*/
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4],unsigned char [64]));
+static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int));
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+static unsigned char PADDING[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+*/
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+*/
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+*/
+#define FF(a, b, c, d, x, s, ac) { \
+	(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define GG(a, b, c, d, x, s, ac) { \
+	(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define HH(a, b, c, d, x, s, ac) { \
+	(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+#define II(a, b, c, d, x, s, ac) { \
+	(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+	(a) = ROTATE_LEFT ((a), (s)); \
+	(a) += (b); \
+	}
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+*/
+void MD5Init(MD5_CTX * context)
+{
+	context->count[0] = context->count[1] = 0;
+	/* Load magic initialization constants.
+	*/
+	context->state[0] = 0x67452301;
+	context->state[1] = 0xefcdab89;
+	context->state[2] = 0x98badcfe;
+	context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+operation, processing another message block, and updating the
+context.
+*/
+void MD5Update(MD5_CTX *context,                         /* context */
+			   unsigned char *input,                    /* input block */
+			   unsigned int inputLen                 /* length of input block */
+			   )
+{
+	unsigned int i, index, partLen;
+
+	/* Compute number of bytes mod 64 */
+	index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+	/* Update number of bits */
+	if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
+		context->count[1]++;
+	context->count[1] += ((UINT4)inputLen >> 29);
+
+	partLen = 64 - index;
+
+	/* Transform as many times as possible.
+	*/
+	if (inputLen >= partLen) {
+		MD5_memcpy
+			((POINTER)&context->buffer[index], (POINTER)input, partLen);
+		MD5Transform (context->state, context->buffer);
+
+		for (i = partLen; i + 63 < inputLen; i += 64)
+			MD5Transform (context->state, &input[i]);
+
+		index = 0;
+	}
+	else
+		i = 0;
+
+	/* Buffer remaining input */
+	MD5_memcpy
+		((POINTER)&context->buffer[index], (POINTER)&input[i],
+		inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+the message digest and zeroizing the context.
+*/
+void MD5Final(unsigned char digest[16],                         /* message digest */
+			  MD5_CTX *context)                                      /* context */
+{
+	unsigned char bits[8];
+	unsigned int index, padLen;
+
+	/* Save number of bits */
+	Encode (bits, context->count, 8);
+
+	/* Pad out to 56 mod 64.
+	*/
+	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+	padLen = (index < 56) ? (56 - index) : (120 - index);
+	MD5Update (context, PADDING, padLen);
+
+	/* Append length (before padding) */
+	MD5Update (context, bits, 8);
+
+	/* Store state in digest */
+	Encode (digest, context->state, 16);
+
+	/* Zeroize sensitive information.
+	*/
+	MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+*/
+static void MD5Transform (UINT4 state[4],unsigned char block[64])
+{
+	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+	Decode (x, block, 64);
+
+	/* Round 1 */
+	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+	/* Round 2 */
+	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+
+	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+	/* Round 3 */
+	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+	/* Round 4 */
+	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+
+	/* Zeroize sensitive information.
+
+	*/
+	MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+a multiple of 4.
+*/
+static void Encode (unsigned char *output,UINT4 *input,unsigned int len)
+{
+	unsigned int i, j;
+
+	for (i = 0, j = 0; j < len; i++, j += 4) {
+		output[j] = (unsigned char)(input[i] & 0xff);
+		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+	}
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+a multiple of 4.
+*/
+static void Decode (UINT4 *output,unsigned char *input,unsigned int len)
+{
+	unsigned int i, j;
+
+	for (i = 0, j = 0; j < len; i++, j += 4)
+		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+		(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+*/
+
+static void MD5_memcpy (POINTER output,POINTER input,unsigned int len)
+{
+	unsigned int i;
+
+	for (i = 0; i < len; i++)
+
+		output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+*/
+static void MD5_memset (POINTER output,int value,unsigned int len)
+{
+	unsigned int i;
+
+	for (i = 0; i < len; i++)
+		((char *)output)[i] = (char)value;
+}

+ 94 - 0
MD5Test/md5class.cpp

@@ -0,0 +1,94 @@
+// md5class.cpp: implementation of the CMD5 class.
+//See internet RFC 1321, "The MD5 Message-Digest Algorithm"
+//
+//Use this code as you see fit. It is provided "as is"
+//without express or implied warranty of any kind.
+
+//////////////////////////////////////////////////////////////////////
+#include "stdafx.h"
+#include "md5class.h"
+#include "md5.h" //declarations from RFC 1321
+#include <string.h>	  
+#include <stdio.h>
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CMD5::CMD5()
+{
+	m_digestValid = false; //we don't have a plaintext string yet
+	m_digestString[32]=0;  //the digest string is always 32 characters, so put a null in position 32
+}
+
+CMD5::~CMD5()
+{
+
+}
+
+CMD5::CMD5(const char* plainText)  
+{	
+	m_plainText =  const_cast<char*>(plainText); //get a pointer to the plain text.  If casting away the const-ness worries you,
+												 //you could make a local copy of the plain text string.
+   	m_digestString[32]=0;
+	m_digestValid = calcDigest();
+}
+
+//////////////////////////////////////////////////////////////////////
+// Implementation
+//////////////////////////////////////////////////////////////////////
+
+void CMD5::setPlainText(const char* plainText)
+{
+  //set plaintext with a mutator, it's ok to 
+  //to call this multiple times.  If casting away the const-ness of plainText 
+  //worries you, you could either make a local copy of the plain 
+  //text string instead of just pointing at the user's string, or 
+  //modify the RFC 1321 code to take 'const' plaintext, see example below. 
+
+  m_plainText = const_cast<char*>(plainText);
+  m_digestValid = calcDigest();
+}
+
+/* Use a function of this type with your favorite string class
+   if casting away the const-ness of the user's text buffer violates you
+   coding standards. 
+
+void CMD5::setPlainText(CString& strPlainText)
+{
+	static CString plaintext(strPlainText);
+	m_plainText = strPlainText.GetBuffer();
+	m_digestValid = calcDigest();
+}
+*/
+
+const char* CMD5::getMD5Digest()
+ {	//access message digest (aka hash), return 0 if plaintext has not been set
+	if(m_digestValid)
+	{
+		return m_digestString;
+	} else return 0;
+ }
+
+bool CMD5::calcDigest()
+{
+  //See RFC 1321 for details on how MD5Init, MD5Update, and MD5Final 
+  //calculate a digest for the plain text
+  MD5_CTX context;
+  MD5Init(&context); 
+
+  //the alternative to these ugly casts is to go into the RFC code and change the declarations
+  MD5Update(&context, reinterpret_cast<unsigned char *>(m_plainText), ::strlen(m_plainText));
+  MD5Final(reinterpret_cast <unsigned char *>(m_digest),&context);
+  
+  //make a string version of the numeric digest value
+  int p=0;
+  for (int i = 0; i<16; i++)
+  {
+	::sprintf(&m_digestString[p],"%02x", m_digest[i]);
+	p+=2;
+  }
+  return true;
+}
+
+

+ 87 - 0
MD5Test/md5class.h

@@ -0,0 +1,87 @@
+// md5class.h: interface for the CMD5 class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MD51_H__2A1EA377_D065_11D4_A8C8_0050DAC6D85C__INCLUDED_)
+#define AFX_MD51_H__2A1EA377_D065_11D4_A8C8_0050DAC6D85C__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+  /***************************************************************************
+
+   This class is a utility wrapper for 'C' code contained in internet RFC 1321, 
+   "The MD5 Message-Digest Algorithm".
+
+   It calculates a cryptological hash value, called a "digest" from a character 
+   string.  For every unique character string the MD5 hash is guaranteed to be 
+   unique.  The MD5 hash has the property that given the digest, it's 
+   thought to be impossible to get back to the plain text string with existing 
+   technology. In this implementation the digest is always a 32 digit hex number,
+   regardless of the length of the input plaintext.
+
+   This class is helpful for programs which store passwords.  Rather than storing 
+   the password directly, the programmer should store the MD5 digest of the password. 
+   Then when the user enters a password, compute the MD5 digest of the input password.
+   If it is identical to the stored digest, then the user
+   has entered the correct password.  It doesn't matter if an evil person sees the 
+   digest, since he or she can't get from the digest to the password. At least not 
+   unless the user enters a word out of the dictionary, since the evil person could 
+   hash the whole dictionary.  One way to defeat a dictionary attack is to append 
+   a non-text character onto the password, so that even if the user enters a dumb 
+   password like "password", you just append some non alpha character to the entered
+   password, i.e. password = "password" + "$".  By always appending a nonalpha 
+   character, your stored digest isn't in the attacker's dictionary. You can 
+   then safely post the digest of the password on a highway billboard.
+    
+   Example pseudocode:
+  {
+	std::string storedPasswordDigest = GetPasswordDigestFromStorage();
+	std::string passwordEnteredbyUser;
+	cout << "Enter password:" ;
+	cin >> passwordEnteredbyUser;
+	
+	CMD5 md5(passwordEnteredbyUser.c_str()); //note c_str() returns a pointer to the std::string's character buffer, just like CString's "GetBuffer" member function.
+	
+	if(md5.getMD5Digest != storedPasswordDigest)
+	{
+		//user has entered an invalid password
+		cout << "Incorrect password!";
+		exit(1);
+	}
+	
+    //if we get here, then the user entered a valid password
+  }
+  **************************************************************************
+  Use this code as you see fit. It is provided "as is"
+  without express or implied warranty of any kind.
+  
+  Jim Howard, jnhtx@jump.net
+  ***************************************************************************/
+
+class CMD5  
+{
+public:
+	CMD5();	//default ctor
+	CMD5(const char* plainText);  //set plaintext in ctor
+	void setPlainText(const char* plainText); //set plaintext with a mutator, it's ok to 
+				                              //to call this multiple times, the digest is recalculated after each call.
+	const char* getMD5Digest();	  //access message digest (aka hash), return 0 if plaintext has not been set
+
+	virtual ~CMD5();
+private:
+	bool calcDigest(); //this function computes the digest by calling the RFC 1321 'C' code
+
+	bool m_digestValid; //false until the plaintext has been set and digest computed
+	unsigned char  m_digest[16]; //the numerical value of the digest
+	char  m_digestString[33];  //Null terminated string value of the digest expressed in hex digits
+	char* m_plainText; //a pointer to the plain text.  If casting away the const-ness 
+	                   //worries you, you could either make a local copy of the plain 
+	                   //text string instead of just pointing at the user's string or 
+					   //modify the RFC 1321 code to take 'const' plaintext. 
+
+};
+
+#endif // !defined(AFX_MD51_H__2A1EA377_D065_11D4_A8C8_0050DAC6D85C__INCLUDED_)

+ 657 - 0
MD5Test/md5和sha1.h

@@ -0,0 +1,657 @@
+#include "stdafx.h"
+#include <stdio.h>
+//#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+typedef unsigned int uint32_t; 
+typedef unsigned long long uint64_t;
+//字节序的小头和大头的问题
+#define ZEN_LITTLE_ENDIAN  0x0123
+#define ZEN_BIG_ENDIAN     0x3210
+
+//目前所有的代码都是为了小头党服务的,不知道有生之年这套代码是否还会为大头党服务一次?
+#ifndef ZEN_BYTES_ORDER
+#define ZEN_BYTES_ORDER    ZEN_LITTLE_ENDIAN
+#endif
+
+#ifndef ZEN_SWAP_UINT16
+#define ZEN_SWAP_UINT16(x)  ((((x) & 0xff00) >>  8) | (((x) & 0x00ff) <<  8))
+#endif
+#ifndef ZEN_SWAP_UINT32
+#define ZEN_SWAP_UINT32(x)  ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
+	(((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
+#endif
+#ifndef ZEN_SWAP_UINT64
+#define ZEN_SWAP_UINT64(x)  ((((x) & 0xff00000000000000) >> 56) | (((x) & 0x00ff000000000000) >>  40) | \
+	(((x) & 0x0000ff0000000000) >> 24) | (((x) & 0x000000ff00000000) >>  8) | \
+	(((x) & 0x00000000ff000000) << 8 ) | (((x) & 0x0000000000ff0000) <<  24) | \
+	(((x) & 0x000000000000ff00) << 40 ) | (((x) & 0x00000000000000ff) <<  56))
+#endif
+
+//将一个(字符串)数组,拷贝到另外一个uint32_t数组,同时每个uint32_t反字节序
+void *swap_uint32_memcpy(void *to, const void *from, size_t length)
+{
+	memcpy(to, from, length);
+	size_t remain_len =  (4 - (length & 3)) & 3;
+
+	//数据不是4字节的倍数,补充0
+	if (remain_len)
+	{
+		for (size_t i = 0; i < remain_len; ++i)
+		{
+			*((char *)(to) + length + i) = 0;
+		}
+		//调整成4的倍数
+		length += remain_len;
+	}
+
+	//所有的数据反转
+	for (size_t i = 0; i < length / 4; ++i)
+	{
+		((uint32_t *)to)[i] = ZEN_SWAP_UINT32(((uint32_t *)to)[i]);
+	}
+
+	return to;
+}
+
+///MD5的结果数据长度
+static const size_t ZEN_MD5_HASH_SIZE   = 16;
+///SHA1的结果数据长度
+static const size_t ZEN_SHA1_HASH_SIZE  = 20;
+
+
+
+namespace ZEN_LIB
+{
+
+
+	/*!
+	@brief      求某个内存块的MD5,
+	@return     unsigned char* 返回的的结果,
+	@param[in]  buf    求MD5的内存BUFFER指针
+	@param[in]  size   BUFFER长度
+	@param[out] result 结果
+	*/
+	unsigned char *md5(const unsigned char *buf,
+		size_t size,
+		unsigned char result[ZEN_MD5_HASH_SIZE]);
+
+
+	/*!
+	@brief      求内存块BUFFER的SHA1值
+	@return     unsigned char* 返回的的结果
+	@param[in]  buf    求SHA1的内存BUFFER指针
+	@param[in]  size   BUFFER长度
+	@param[out] result 结果
+	*/
+	unsigned char *sha1(const unsigned char *buf,
+		size_t size,
+		unsigned char result[ZEN_SHA1_HASH_SIZE]);
+};
+
+
+//================================================================================================
+//MD5的算法
+
+//每次处理的BLOCK的大小
+static const size_t ZEN_MD5_BLOCK_SIZE = 64;
+
+//md5算法的上下文,保存一些状态,中间数据,结果
+typedef struct md5_ctx
+{
+	//处理的数据的长度
+	uint64_t length_;
+	//还没有处理的数据长度
+	uint64_t unprocessed_;
+	//取得的HASH结果(中间数据)
+	uint32_t  hash_[4];
+} md5_ctx;
+
+
+#define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
+#define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
+#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
+#define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
+
+
+/*!
+@brief      内部函数,初始化MD5的context,内容
+@param      ctx
+*/
+static void zen_md5_init(md5_ctx *ctx)
+{
+	ctx->length_ = 0;
+	ctx->unprocessed_ = 0;
+
+	/* initialize state */
+	ctx->hash_[0] = 0x67452301;
+	ctx->hash_[1] = 0xefcdab89;
+	ctx->hash_[2] = 0x98badcfe;
+	ctx->hash_[3] = 0x10325476;
+}
+
+/* First, define four auxiliary functions that each take as input
+* three 32-bit words and returns a 32-bit word.*/
+
+/* F(x,y,z) = ((y XOR z) AND x) XOR z - is faster then original version */
+#define MD5_F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
+#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define MD5_H(x, y, z) ((x) ^ (y) ^ (z))
+#define MD5_I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* transformations for rounds 1, 2, 3, and 4. */
+#define MD5_ROUND1(a, b, c, d, x, s, ac) { \
+	(a) += MD5_F((b), (c), (d)) + (x) + (ac); \
+	(a) = ROTL32((a), (s)); \
+	(a) += (b); \
+}
+#define MD5_ROUND2(a, b, c, d, x, s, ac) { \
+	(a) += MD5_G((b), (c), (d)) + (x) + (ac); \
+	(a) = ROTL32((a), (s)); \
+	(a) += (b); \
+}
+#define MD5_ROUND3(a, b, c, d, x, s, ac) { \
+	(a) += MD5_H((b), (c), (d)) + (x) + (ac); \
+	(a) = ROTL32((a), (s)); \
+	(a) += (b); \
+}
+#define MD5_ROUND4(a, b, c, d, x, s, ac) { \
+	(a) += MD5_I((b), (c), (d)) + (x) + (ac); \
+	(a) = ROTL32((a), (s)); \
+	(a) += (b); \
+}
+
+
+/*!
+@brief      内部函数,将64个字节,16个uint32_t的数组进行摘要(杂凑)处理,处理的数据自己序是小头数据
+@param      state 存放处理的hash数据结果
+@param      block 要处理的block,64个字节,16个uint32_t的数组
+*/
+static void zen_md5_process_block(uint32_t state[4], const uint32_t block[ZEN_MD5_BLOCK_SIZE / 4])
+{
+	register unsigned a, b, c, d;
+	a = state[0];
+	b = state[1];
+	c = state[2];
+	d = state[3];
+
+	const uint32_t *x = NULL;
+
+	//MD5里面计算的数据都是小头数据.大头党的数据要处理
+#if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
+	x = block;
+#else
+	uint32_t swap_block[ZEN_MD5_BLOCK_SIZE / 4];
+	swap_uint32_memcpy(swap_block, block, 64);
+	x = swap_block;
+#endif
+
+
+	MD5_ROUND1(a, b, c, d, x[ 0],  7, 0xd76aa478);
+	MD5_ROUND1(d, a, b, c, x[ 1], 12, 0xe8c7b756);
+	MD5_ROUND1(c, d, a, b, x[ 2], 17, 0x242070db);
+	MD5_ROUND1(b, c, d, a, x[ 3], 22, 0xc1bdceee);
+	MD5_ROUND1(a, b, c, d, x[ 4],  7, 0xf57c0faf);
+	MD5_ROUND1(d, a, b, c, x[ 5], 12, 0x4787c62a);
+	MD5_ROUND1(c, d, a, b, x[ 6], 17, 0xa8304613);
+	MD5_ROUND1(b, c, d, a, x[ 7], 22, 0xfd469501);
+	MD5_ROUND1(a, b, c, d, x[ 8],  7, 0x698098d8);
+	MD5_ROUND1(d, a, b, c, x[ 9], 12, 0x8b44f7af);
+	MD5_ROUND1(c, d, a, b, x[10], 17, 0xffff5bb1);
+	MD5_ROUND1(b, c, d, a, x[11], 22, 0x895cd7be);
+	MD5_ROUND1(a, b, c, d, x[12],  7, 0x6b901122);
+	MD5_ROUND1(d, a, b, c, x[13], 12, 0xfd987193);
+	MD5_ROUND1(c, d, a, b, x[14], 17, 0xa679438e);
+	MD5_ROUND1(b, c, d, a, x[15], 22, 0x49b40821);
+
+	MD5_ROUND2(a, b, c, d, x[ 1],  5, 0xf61e2562);
+	MD5_ROUND2(d, a, b, c, x[ 6],  9, 0xc040b340);
+	MD5_ROUND2(c, d, a, b, x[11], 14, 0x265e5a51);
+	MD5_ROUND2(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
+	MD5_ROUND2(a, b, c, d, x[ 5],  5, 0xd62f105d);
+	MD5_ROUND2(d, a, b, c, x[10],  9,  0x2441453);
+	MD5_ROUND2(c, d, a, b, x[15], 14, 0xd8a1e681);
+	MD5_ROUND2(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
+	MD5_ROUND2(a, b, c, d, x[ 9],  5, 0x21e1cde6);
+	MD5_ROUND2(d, a, b, c, x[14],  9, 0xc33707d6);
+	MD5_ROUND2(c, d, a, b, x[ 3], 14, 0xf4d50d87);
+	MD5_ROUND2(b, c, d, a, x[ 8], 20, 0x455a14ed);
+	MD5_ROUND2(a, b, c, d, x[13],  5, 0xa9e3e905);
+	MD5_ROUND2(d, a, b, c, x[ 2],  9, 0xfcefa3f8);
+	MD5_ROUND2(c, d, a, b, x[ 7], 14, 0x676f02d9);
+	MD5_ROUND2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
+
+	MD5_ROUND3(a, b, c, d, x[ 5],  4, 0xfffa3942);
+	MD5_ROUND3(d, a, b, c, x[ 8], 11, 0x8771f681);
+	MD5_ROUND3(c, d, a, b, x[11], 16, 0x6d9d6122);
+	MD5_ROUND3(b, c, d, a, x[14], 23, 0xfde5380c);
+	MD5_ROUND3(a, b, c, d, x[ 1],  4, 0xa4beea44);
+	MD5_ROUND3(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
+	MD5_ROUND3(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
+	MD5_ROUND3(b, c, d, a, x[10], 23, 0xbebfbc70);
+	MD5_ROUND3(a, b, c, d, x[13],  4, 0x289b7ec6);
+	MD5_ROUND3(d, a, b, c, x[ 0], 11, 0xeaa127fa);
+	MD5_ROUND3(c, d, a, b, x[ 3], 16, 0xd4ef3085);
+	MD5_ROUND3(b, c, d, a, x[ 6], 23,  0x4881d05);
+	MD5_ROUND3(a, b, c, d, x[ 9],  4, 0xd9d4d039);
+	MD5_ROUND3(d, a, b, c, x[12], 11, 0xe6db99e5);
+	MD5_ROUND3(c, d, a, b, x[15], 16, 0x1fa27cf8);
+	MD5_ROUND3(b, c, d, a, x[ 2], 23, 0xc4ac5665);
+
+	MD5_ROUND4(a, b, c, d, x[ 0],  6, 0xf4292244);
+	MD5_ROUND4(d, a, b, c, x[ 7], 10, 0x432aff97);
+	MD5_ROUND4(c, d, a, b, x[14], 15, 0xab9423a7);
+	MD5_ROUND4(b, c, d, a, x[ 5], 21, 0xfc93a039);
+	MD5_ROUND4(a, b, c, d, x[12],  6, 0x655b59c3);
+	MD5_ROUND4(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
+	MD5_ROUND4(c, d, a, b, x[10], 15, 0xffeff47d);
+	MD5_ROUND4(b, c, d, a, x[ 1], 21, 0x85845dd1);
+	MD5_ROUND4(a, b, c, d, x[ 8],  6, 0x6fa87e4f);
+	MD5_ROUND4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
+	MD5_ROUND4(c, d, a, b, x[ 6], 15, 0xa3014314);
+	MD5_ROUND4(b, c, d, a, x[13], 21, 0x4e0811a1);
+	MD5_ROUND4(a, b, c, d, x[ 4],  6, 0xf7537e82);
+	MD5_ROUND4(d, a, b, c, x[11], 10, 0xbd3af235);
+	MD5_ROUND4(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
+	MD5_ROUND4(b, c, d, a, x[ 9], 21, 0xeb86d391);
+
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+}
+
+
+/*!
+@brief      内部函数,处理数据的前面部分(>64字节的部分),每次组成一个64字节的block就进行杂凑处理
+@param[out] ctx  算法的context,用于记录一些处理的上下文和结果
+@param[in]  buf  处理的数据,
+@param[in]  size 处理的数据长度
+*/
+static void zen_md5_update(md5_ctx *ctx, const unsigned char *buf, size_t size)
+{
+	//为什么不是=,因为在某些环境下,可以多次调用zen_md5_update,但这种情况,必须保证前面的调用,每次都没有unprocessed_
+	ctx->length_ += size;
+
+	//每个处理的块都是64字节
+	while (size >= ZEN_MD5_BLOCK_SIZE)
+	{
+		zen_md5_process_block(ctx->hash_, reinterpret_cast<const uint32_t *>(buf));
+		buf  += ZEN_MD5_BLOCK_SIZE;
+		size -= ZEN_MD5_BLOCK_SIZE;
+	}
+
+	ctx->unprocessed_ = size;
+}
+
+
+/*!
+@brief      内部函数,处理数据的末尾部分,我们要拼出最后1个(或者两个)要处理的BLOCK,加上0x80,加上长度进行处理
+@param[in]  ctx    算法的context,用于记录一些处理的上下文和结果
+@param[in]  buf    处理的数据
+@param[in]  size   处理buffer的长度
+@param[out] result 返回的结果,
+*/
+static void zen_md5_final(md5_ctx *ctx, const unsigned char *buf, size_t size, unsigned char *result)
+{
+	uint32_t message[ZEN_MD5_BLOCK_SIZE / 4];
+
+	//保存剩余的数据,我们要拼出最后1个(或者两个)要处理的块,前面的算法保证了,最后一个块肯定小于64个字节
+	if (ctx->unprocessed_)
+	{
+		memcpy(message, buf + size - ctx->unprocessed_, static_cast<size_t>( ctx->unprocessed_));
+	}
+
+	//得到0x80要添加在的位置(在uint32_t 数组中),
+	uint32_t index = ((uint32_t)ctx->length_ & 63) >> 2;
+	uint32_t shift = ((uint32_t)ctx->length_ & 3) * 8;
+
+	//添加0x80进去,并且把余下的空间补充0
+	message[index]   &= ~(0xFFFFFFFF << shift);
+	message[index++] ^= 0x80 << shift;
+
+	//如果这个block还无法处理,其后面的长度无法容纳长度64bit,那么先处理这个block
+	if (index > 14)
+	{
+		while (index < 16)
+		{
+			message[index++] = 0;
+		}
+
+		zen_md5_process_block(ctx->hash_, message);
+		index = 0;
+	}
+
+	//补0
+	while (index < 14)
+	{
+		message[index++] = 0;
+	}
+
+	//保存长度,注意是bit位的长度,这个问题让我看着郁闷了半天,
+	uint64_t data_len = (ctx->length_) << 3;
+
+	//注意MD5算法要求的64bit的长度是小头LITTLE-ENDIAN编码,注意下面的比较是!=
+#if ZEN_BYTES_ORDER != ZEN_LITTLE_ENDIAN
+	data_len = ZEN_SWAP_UINT64(data_len);
+#endif
+
+	message[14] = (uint32_t) (data_len & 0x00000000FFFFFFFF);
+	message[15] = (uint32_t) ((data_len & 0xFFFFFFFF00000000ULL) >> 32);
+
+	zen_md5_process_block(ctx->hash_, message);
+
+	//注意结果是小头党的,在大头的世界要进行转换
+#if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
+	memcpy(result, &ctx->hash_, ZEN_MD5_HASH_SIZE);
+#else
+	swap_uint32_memcpy(result, &ctx->hash_, ZEN_MD5_HASH_SIZE);
+#endif
+
+}
+
+
+//计算一个内存数据的MD5值
+unsigned char *ZEN_LIB::md5(const unsigned char *buf,
+							size_t size,
+							unsigned char result[ZEN_MD5_HASH_SIZE])
+{
+	assert(result != NULL);
+
+	md5_ctx ctx;
+	zen_md5_init(&ctx);
+	zen_md5_update(&ctx, buf, size);
+	zen_md5_final(&ctx, buf, size, result);
+	return result;
+}
+
+
+
+
+//================================================================================================
+//SHA1的算法
+
+//每次处理的BLOCK的大小
+static const size_t ZEN_SHA1_BLOCK_SIZE = 64;
+
+//SHA1算法的上下文,保存一些状态,中间数据,结果
+typedef struct sha1_ctx
+{
+
+	//处理的数据的长度
+	uint64_t length_;
+	//还没有处理的数据长度
+	uint64_t unprocessed_;
+	/* 160-bit algorithm internal hashing state */
+	uint32_t hash_[5];
+} sha1_ctx;
+
+//内部函数,SHA1算法的上下文的初始化
+static void zen_sha1_init(sha1_ctx *ctx)
+{
+	ctx->length_ = 0;
+	ctx->unprocessed_ = 0;
+	// 初始化算法的几个常量,魔术数;
+	ctx->hash_[0] = 0x67452301;
+	ctx->hash_[1] = 0xefcdab89;
+	ctx->hash_[2] = 0x98badcfe;
+	ctx->hash_[3] = 0x10325476;
+	ctx->hash_[4] = 0xc3d2e1f0;
+}
+
+
+/*!
+@brief      内部函数,对一个64bit内存块进行摘要(杂凑)处理,
+@param      hash  存放计算hash结果的的数组
+@param      block 要计算的处理得内存块
+*/
+static void zen_sha1_process_block(uint32_t hash[5],
+								   const uint32_t block[ZEN_SHA1_BLOCK_SIZE / 4])
+{
+	size_t        t;
+	uint32_t      wblock[80];
+	register uint32_t      a, b, c, d, e, temp;
+
+	//SHA1算法处理的内部数据要求是大头党的,在小头的环境转换
+#if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
+	swap_uint32_memcpy(wblock, block, ZEN_SHA1_BLOCK_SIZE);
+#else
+	::memcpy(wblock, block, ZEN_SHA1_BLOCK_SIZE);
+#endif
+
+	//处理
+	for (t = 16; t < 80; t++)
+	{
+		wblock[t] = ROTL32(wblock[t - 3] ^ wblock[t - 8] ^ wblock[t - 14] ^ wblock[t - 16], 1);
+	}
+
+	a = hash[0];
+	b = hash[1];
+	c = hash[2];
+	d = hash[3];
+	e = hash[4];
+
+	for (t = 0; t < 20; t++)
+	{
+		/* the following is faster than ((B & C) | ((~B) & D)) */
+		temp =  ROTL32(a, 5) + (((c ^ d) & b) ^ d)
+			+ e + wblock[t] + 0x5A827999;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	for (t = 20; t < 40; t++)
+	{
+		temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0x6ED9EBA1;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	for (t = 40; t < 60; t++)
+	{
+		temp = ROTL32(a, 5) + ((b & c) | (b & d) | (c & d))
+			+ e + wblock[t] + 0x8F1BBCDC;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	for (t = 60; t < 80; t++)
+	{
+		temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0xCA62C1D6;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	hash[0] += a;
+	hash[1] += b;
+	hash[2] += c;
+	hash[3] += d;
+	hash[4] += e;
+}
+
+
+/*!
+@brief      内部函数,处理数据的前面部分(>64字节的部分),每次组成一个64字节的block就进行杂凑处理
+@param      ctx  算法的上下文,记录中间数据,结果等
+@param      msg  要进行计算的数据buffer
+@param      size 长度
+*/
+static void zen_sha1_update(sha1_ctx *ctx,
+							const unsigned char *buf, 
+							size_t size)
+{
+	//为了让zen_sha1_update可以多次进入,长度可以累计
+	ctx->length_ += size;
+
+	//每个处理的块都是64字节
+	while (size >= ZEN_SHA1_BLOCK_SIZE)
+	{
+		zen_sha1_process_block(ctx->hash_, reinterpret_cast<const uint32_t *>(buf));
+		buf  += ZEN_SHA1_BLOCK_SIZE;
+		size -= ZEN_SHA1_BLOCK_SIZE;
+	}
+
+	ctx->unprocessed_ = size;
+}
+
+
+/*!
+@brief      内部函数,处理数据的最后部分,添加0x80,补0,增加长度信息
+@param      ctx    算法的上下文,记录中间数据,结果等
+@param      msg    要进行计算的数据buffer
+@param      result 返回的结果
+*/
+static void zen_sha1_final(sha1_ctx *ctx, 
+						   const unsigned char *msg,
+						   size_t size, 
+						   unsigned char *result)
+{
+
+	uint32_t message[ZEN_SHA1_BLOCK_SIZE / 4];
+
+	//保存剩余的数据,我们要拼出最后1个(或者两个)要处理的块,前面的算法保证了,最后一个块肯定小于64个字节
+	if (ctx->unprocessed_)
+	{
+		memcpy(message, msg + size - ctx->unprocessed_, static_cast<size_t>( ctx->unprocessed_));
+	}
+
+	//得到0x80要添加在的位置(在uint32_t 数组中),
+	uint32_t index = ((uint32_t)ctx->length_ & 63) >> 2;
+	uint32_t shift = ((uint32_t)ctx->length_ & 3) * 8;
+
+	//添加0x80进去,并且把余下的空间补充0
+	message[index]   &= ~(0xFFFFFFFF << shift);
+	message[index++] ^= 0x80 << shift;
+
+	//如果这个block还无法处理,其后面的长度无法容纳长度64bit,那么先处理这个block
+	if (index > 14)
+	{
+		while (index < 16)
+		{
+			message[index++] = 0;
+		}
+
+		zen_sha1_process_block(ctx->hash_, message);
+		index = 0;
+	}
+
+	//补0
+	while (index < 14)
+	{
+		message[index++] = 0;
+	}
+
+	//保存长度,注意是bit位的长度,这个问题让我看着郁闷了半天,
+	uint64_t data_len = (ctx->length_) << 3;
+
+	//注意SHA1算法要求的64bit的长度是大头BIG-ENDIAN,在小头的世界要进行转换
+#if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
+	data_len = ZEN_SWAP_UINT64(data_len);
+#endif
+
+	message[14] = (uint32_t) (data_len & 0x00000000FFFFFFFF);
+	message[15] = (uint32_t) ((data_len & 0xFFFFFFFF00000000ULL) >> 32);
+
+	zen_sha1_process_block(ctx->hash_, message);
+
+	//注意结果是大头党的,在小头的世界要进行转换
+#if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
+	swap_uint32_memcpy(result, &ctx->hash_, ZEN_SHA1_HASH_SIZE);
+#else
+	memcpy(result, &ctx->hash_, ZEN_SHA1_HASH_SIZE);
+#endif
+}
+
+
+
+//计算一个内存数据的SHA1值
+unsigned char *ZEN_LIB::sha1(const unsigned char *msg,
+							 size_t size,
+							 unsigned char result[ZEN_SHA1_HASH_SIZE])
+{
+	assert(result != NULL);
+
+	sha1_ctx ctx;
+	zen_sha1_init(&ctx);
+	zen_sha1_update(&ctx, msg, size);
+	zen_sha1_final(&ctx, msg, size, result);
+	return result;
+}
+
+/*
+int main(int argc, char * argv[])
+{
+
+	int ret = 0;
+	static unsigned char test_buf[7][81] =
+	{
+		{ "" }, 
+		{ "a" },
+		{ "abc" },
+		{ "message digest" },
+		{ "abcdefghijklmnopqrstuvwxyz" },
+		{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+		{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
+	};
+
+	static const size_t test_buflen[7] =
+	{
+		0, 1, 3, 14, 26, 62, 80
+	};
+
+	static const unsigned char md5_test_sum[7][16] =
+	{
+		{ 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,  0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
+		{ 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,  0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
+		{ 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,  0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
+		{ 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,  0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
+		{ 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,  0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
+		{ 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,  0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
+		{ 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,  0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
+	};
+	unsigned char result[32] ={0};
+
+	for(size_t i=0;i<7;++i)
+	{
+		ZEN_LIB::md5(test_buf[i],test_buflen[i],result);
+		ret = memcmp(result,md5_test_sum[i],16);
+		if (ret != 0)
+		{
+			assert(false);
+		}
+	}
+
+	static const unsigned char sha1_test_sum[7][20] =
+	{
+		{ 0xda,0x39,0xa3,0xee,0x5e,0x6b,0x4b,0x0d,0x32,0x55,0xbf,0xef,0x95,0x60,0x18,0x90,0xaf,0xd8,0x07,0x09 },
+		{ 0x86,0xf7,0xe4,0x37,0xfa,0xa5,0xa7,0xfc,0xe1,0x5d,0x1d,0xdc,0xb9,0xea,0xea,0xea,0x37,0x76,0x67,0xb8 },
+		{ 0xa9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e,0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d },
+		{ 0xc1,0x22,0x52,0xce,0xda,0x8b,0xe8,0x99,0x4d,0x5f,0xa0,0x29,0x0a,0x47,0x23,0x1c,0x1d,0x16,0xaa,0xe3 },
+		{ 0x32,0xd1,0x0c,0x7b,0x8c,0xf9,0x65,0x70,0xca,0x04,0xce,0x37,0xf2,0xa1,0x9d,0x84,0x24,0x0d,0x3a,0x89 },
+		{ 0x76,0x1c,0x45,0x7b,0xf7,0x3b,0x14,0xd2,0x7e,0x9e,0x92,0x65,0xc4,0x6f,0x4b,0x4d,0xda,0x11,0xf9,0x40 },
+		{ 0x50,0xab,0xf5,0x70,0x6a,0x15,0x09,0x90,0xa0,0x8b,0x2c,0x5e,0xa4,0x0f,0xa0,0xe5,0x85,0x55,0x47,0x32 },
+	};
+	for(size_t i=0;i<7;++i)
+	{
+		ZEN_LIB::sha1(test_buf[i],test_buflen[i],result);
+		ret = memcmp(result,sha1_test_sum[i],20);
+		if (ret != 0)
+		{
+			assert(false);
+		}
+	}
+	return 0;
+}*/

+ 428 - 0
MD5Test/sha1.h

@@ -0,0 +1,428 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[7/11/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __SHA1_HEADER__
+#define __SHA1_HEADER__
+
+#include <assert.h>
+
+typedef unsigned int uint32_t; 
+typedef unsigned long long uint64_t;
+
+// 字节序的小头和大头的问题;
+#define LITTLE_ENDIAN  0x0123
+#define BIG_ENDIAN     0x3210
+
+#ifndef BYTES_ORDER
+#define BYTES_ORDER    LITTLE_ENDIAN
+#endif
+
+#ifndef SWAP_UINT16
+#define SWAP_UINT16(x)  ((((x) & 0xff00) >>  8) | (((x) & 0x00ff) <<  8))
+#endif
+#ifndef SWAP_UINT32
+#define SWAP_UINT32(x)  ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
+	(((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
+#endif
+#ifndef SWAP_UINT64
+#define SWAP_UINT64(x)  ((((x) & 0xff00000000000000) >> 56) | (((x) & 0x00ff000000000000) >>  40) | \
+	(((x) & 0x0000ff0000000000) >> 24) | (((x) & 0x000000ff00000000) >>  8) | \
+	(((x) & 0x00000000ff000000) << 8 ) | (((x) & 0x0000000000ff0000) <<  24) | \
+	(((x) & 0x000000000000ff00) << 40 ) | (((x) & 0x00000000000000ff) <<  56))
+#endif
+
+#define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
+#define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
+#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
+#define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
+
+// SHA1的结果数据长度;
+static const size_t SHA1_HASH_SIZE  = 20;
+// SHA1每次处理的BLOCK的大小;
+static const size_t SHA1_BLOCK_SIZE = 64;
+
+/************************************************************************/
+/*  函数:ByteTrun2Hex[7/11/2016 IT];
+/*  描述:将每个字节转化成由2个十六进制字符表示的字符串;
+/*  参数:;
+/*  	[IN] szMsg:要被转换的字节数组;
+/*  	[IN] nCount:要被转换的字节数组长度;
+/*  	[IN/OUT] szConvMsg:转换成2个十六进制字符表示的字符串;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void ByteTrun2Hex( unsigned char *szMsg, int nCount, unsigned char *szConvMsg )
+{
+	unsigned char lh[2];
+	for (int i = 0; i < nCount; i++)
+	{
+		lh[0] = szMsg[i] >> 4;
+		lh[1] = szMsg[i] & 0x0f;
+
+		for ( int j = 0; j < 2; j++ )
+		{
+			if ( lh[j] <= 9 )
+				szConvMsg[i*2 + j] = lh[j] + '0';
+			else 
+			{
+				switch ( lh[j] )
+				{
+				case 10:
+					szConvMsg[i*2 + j] = 'a';
+					break;
+				case 11:
+					szConvMsg[i*2 + j] = 'b';
+					break;
+				case 12:
+					szConvMsg[i*2 + j] = 'c';
+					break;
+				case 13:
+					szConvMsg[i*2 + j] = 'd';
+					break;
+				case 14:
+					szConvMsg[i*2 + j] = 'e';
+					break;
+				case 15:
+					szConvMsg[i*2 + j] = 'f';
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	}
+}
+
+/************************************************************************/
+/*  函数:swap_uint32_memcpy[7/11/2016 IT];
+/*  描述:将一个(字符串)数组,拷贝到另外一个uint32_t数组,同时每个uint32_t反字节序;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void *swap_uint32_memcpy(void *to, const void *from, size_t length)
+{
+	memcpy(to, from, length);
+	size_t remain_len =  (4 - (length & 3)) & 3;
+
+	// 数据不是4字节的倍数,补充0;
+	if (remain_len)
+	{
+		for (size_t i = 0; i < remain_len; ++i)
+		{
+			*((char *)(to) + length + i) = 0;
+		}
+		//调整成4的倍数;
+		length += remain_len;
+	}
+
+	// 所有的数据反转;
+	for (size_t i = 0; i < length / 4; ++i)
+	{
+		((uint32_t *)to)[i] = SWAP_UINT32(((uint32_t *)to)[i]);
+	}
+
+	return to;
+}
+
+//SHA1算法的上下文,保存一些状态,中间数据,结果;
+typedef struct sha1_ctx
+{
+
+	// 处理的数据的长度;
+	uint64_t length_;
+	// 还没有处理的数据长度;
+	uint64_t unprocessed_;
+	/* 160-bit algorithm internal hashing state */
+	uint32_t hash_[5];
+} sha1_ctx;
+
+//内部函数,SHA1算法的上下文的初始化;
+static void sha1_init(sha1_ctx *ctx)
+{
+	ctx->length_ = 0;
+	ctx->unprocessed_ = 0;
+	// 初始化算法的几个常量,魔术数;
+	ctx->hash_[0] = 0x67452301;
+	ctx->hash_[1] = 0xefcdab89;
+	ctx->hash_[2] = 0x98badcfe;
+	ctx->hash_[3] = 0x10325476;
+	ctx->hash_[4] = 0xc3d2e1f0;
+}
+
+/************************************************************************/
+/*  函数:sha1_process_block[7/12/2016 IT];
+/*  描述:内部函数,对一个64bit内存块进行摘要(杂凑)处理;
+/*  参数:;
+/*  	[IN] hash:存放计算hash结果的的数组;
+/*  	[IN] block:要计算的处理得内存块;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+static void sha1_process_block(uint32_t hash[5],const uint32_t block[SHA1_BLOCK_SIZE / 4])
+{
+	size_t        t;
+	uint32_t      wblock[80];
+	register uint32_t      a, b, c, d, e, temp;
+
+	//SHA1算法处理的内部数据要求是大头党的,在小头的环境转换;
+#if BYTES_ORDER == LITTLE_ENDIAN
+	swap_uint32_memcpy(wblock, block, SHA1_BLOCK_SIZE);
+#else
+	::memcpy(wblock, block, SHA1_BLOCK_SIZE);
+#endif
+
+	//处理
+	for (t = 16; t < 80; t++)
+	{
+		wblock[t] = ROTL32(wblock[t - 3] ^ wblock[t - 8] ^ wblock[t - 14] ^ wblock[t - 16], 1);
+	}
+
+	a = hash[0];
+	b = hash[1];
+	c = hash[2];
+	d = hash[3];
+	e = hash[4];
+
+	for (t = 0; t < 20; t++)
+	{
+		/* the following is faster than ((B & C) | ((~B) & D)) */
+		temp =  ROTL32(a, 5) + (((c ^ d) & b) ^ d) + e + wblock[t] + 0x5A827999;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	for (t = 20; t < 40; t++)
+	{
+		temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0x6ED9EBA1;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	for (t = 40; t < 60; t++)
+	{
+		temp = ROTL32(a, 5) + ((b & c) | (b & d) | (c & d)) + e + wblock[t] + 0x8F1BBCDC;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	for (t = 60; t < 80; t++)
+	{
+		temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0xCA62C1D6;
+		e = d;
+		d = c;
+		c = ROTL32(b, 30);
+		b = a;
+		a = temp;
+	}
+
+	hash[0] += a;
+	hash[1] += b;
+	hash[2] += c;
+	hash[3] += d;
+	hash[4] += e;
+}
+
+/************************************************************************/
+/*  函数:sha1_update[7/12/2016 IT];
+/*  描述:内部函数,处理数据的前面部分(>64字节的部分),每次组成一个64字节的block就进行杂凑处理;
+/*  参数:;
+/*  	[IN] ctx:算法的上下文,记录中间数据,结果等;
+/*  	[IN] msg:要进行计算的数据buffer;
+/*  	[IN] size:长度;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+static void sha1_update(sha1_ctx *ctx,const unsigned char *buf, size_t size)
+{
+	//为了让zen_sha1_update可以多次进入,长度可以累计;
+	ctx->length_ += size;
+
+	//每个处理的块都是64字节;
+	while (size >= SHA1_BLOCK_SIZE)
+	{
+		sha1_process_block(ctx->hash_, reinterpret_cast<const uint32_t *>(buf));
+		buf  += SHA1_BLOCK_SIZE;
+		size -= SHA1_BLOCK_SIZE;
+	}
+
+	ctx->unprocessed_ = size;
+}
+
+/************************************************************************/
+/*  函数:sha1_final[7/12/2016 IT];
+/*  描述:内部函数,处理数据的最后部分,添加0x80,补0,增加长度信息;
+/*  参数:;
+/*  	[IN] ctx:算法的上下文,记录中间数据,结果等;
+/*  	[IN] msg:要进行计算的数据buffer;
+/*  	[IN] result:返回的结果;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+static void sha1_final(sha1_ctx *ctx, const unsigned char *msg,size_t size, unsigned char *result)
+{
+
+	uint32_t message[SHA1_BLOCK_SIZE / 4];
+
+	//保存剩余的数据,我们要拼出最后1个(或者两个)要处理的块,前面的算法保证了,最后一个块肯定小于64个字节;
+	if (ctx->unprocessed_)
+	{
+		memcpy(message, msg + size - ctx->unprocessed_, static_cast<size_t>( ctx->unprocessed_));
+	}
+
+	//得到0x80要添加在的位置(在uint32_t 数组中);
+	uint32_t index = ((uint32_t)ctx->length_ & 63) >> 2;
+	uint32_t shift = ((uint32_t)ctx->length_ & 3) * 8;
+
+	//添加0x80进去,并且把余下的空间补充0;
+	message[index]   &= ~(0xFFFFFFFF << shift);
+	message[index++] ^= 0x80 << shift;
+
+	//如果这个block还无法处理,其后面的长度无法容纳长度64bit,那么先处理这个block;
+	if (index > 14)
+	{
+		while (index < 16)
+		{
+			message[index++] = 0;
+		}
+
+		sha1_process_block(ctx->hash_, message);
+		index = 0;
+	}
+
+	//补0;
+	while (index < 14)
+	{
+		message[index++] = 0;
+	}
+
+	// 保存长度,注意是bit位的长度,这个问题让我看着郁闷了半天;
+	uint64_t data_len = (ctx->length_) << 3;
+
+	//注意SHA1算法要求的64bit的长度是大头BIG-ENDIAN,在小头的世界要进行转换;
+#if BYTES_ORDER == LITTLE_ENDIAN
+	data_len = SWAP_UINT64(data_len);
+#endif
+
+	message[14] = (uint32_t) (data_len & 0x00000000FFFFFFFF);
+	message[15] = (uint32_t) ((data_len & 0xFFFFFFFF00000000ULL) >> 32);
+
+	sha1_process_block(ctx->hash_, message);
+
+	// 注意结果是大头党的,在小头的世界要进行转换;
+#if BYTES_ORDER == LITTLE_ENDIAN
+	swap_uint32_memcpy(result, &ctx->hash_, SHA1_HASH_SIZE);
+#else
+	memcpy(result, &ctx->hash_, SHA1_HASH_SIZE);
+#endif
+}
+
+/************************************************************************/
+/*  函数:sha1[7/12/2016 IT];
+/*  描述:求内存块BUFFER的SHA1值;
+/*  参数:;
+/*  	[IN] msg:求SHA1的内存BUFFER指针;
+/*  	[OUT] size:BUFFER长度;
+/*  	[IN/OUT] result:结果;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+unsigned char *sha1(const unsigned char *msg,size_t size,unsigned char result[SHA1_HASH_SIZE])
+{
+	assert(result != NULL);
+
+	sha1_ctx ctx;
+	sha1_init(&ctx);
+	sha1_update(&ctx, msg, size);
+	sha1_final(&ctx, msg, size, result);
+
+	return result;
+}
+
+/************************************************************************/
+/*  函数:sha1Hex[7/12/2016 IT];
+/*  描述:求内存块BUFFER的SHA1值的十六进制字符表示的字符串值;
+/*  参数:;
+/*  	[IN] msg:求SHA1的内存BUFFER指针;
+/*  	[OUT] size:BUFFER长度;
+/*  	[IN/OUT] szHexResult:十六进制字符结果;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+unsigned char *sha1Hex(const unsigned char *msg, size_t size, unsigned char szHexResult[41])
+{
+	assert(szHexResult != NULL);
+
+	sha1_ctx ctx;
+	unsigned char result[21] = {0};
+	sha1_init(&ctx);
+	sha1_update(&ctx, msg, size);
+	sha1_final(&ctx, msg, size, result);
+
+	ByteTrun2Hex(result, 20, szHexResult);
+
+	return szHexResult;
+}
+
+#endif

+ 314 - 0
MD5Test/stdafx.cpp

@@ -0,0 +1,314 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// MD5Test.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用
+WCHAR* ASCII2UNICODE(IN LPCCH lpASCIIStr)
+{
+	if ( lpASCIIStr == NULL )
+		return NULL;
+
+	// 获取宽字符字节数;
+	int cchWideChar  = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+	if ( cchWideChar == 0)
+		return NULL;
+
+	// 转换成宽字符串;
+	WCHAR *pWideChar = new WCHAR[cchWideChar + 1];
+	memset(pWideChar, 0 , sizeof(WCHAR)*(cchWideChar + 1));
+	int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pWideChar, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+	{ 
+		if (pWideChar) 
+			delete []pWideChar;
+		return NULL;
+	}
+
+	return pWideChar;
+}
+
+BOOL ASCII2UNICODE(IN LPCCH lpASCIIStr, OUT PWCH pUNICODEStr, IN CONST INT& nUNICODEStrLen)
+{
+	if ( lpASCIIStr == NULL )
+		return FALSE;
+
+	// 获取宽字符字节数;
+	int cchWideChar  = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+	if ( cchWideChar == 0 || cchWideChar >= nUNICODEStrLen)
+		return FALSE;
+
+	// 转换成宽字符串;
+	memset(pUNICODEStr, 0 , sizeof(WCHAR)*nUNICODEStrLen);
+	int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pUNICODEStr, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+		return FALSE;
+
+	return TRUE;
+}
+
+CHAR* UNICODE2ASCII(IN LPWCH lpUNICODEStr)
+{
+	if ( lpUNICODEStr == NULL )
+		return NULL;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 )
+		return NULL;
+
+	// 转换成多字节字符;
+	CHAR *pMultiByteStr = new CHAR[cbMultiByte+1];
+	memset(pMultiByteStr, 0, cbMultiByte + 1);
+	int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pMultiByteStr, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		if (pMultiByteStr) 
+			delete []pMultiByteStr;
+		return NULL;
+	}
+
+	return pMultiByteStr;
+}
+
+BOOL UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen)
+{
+	if ( lpUNICODEStr == NULL )
+		return FALSE;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 || cbMultiByte >= nASCIIStrLen )
+		return FALSE;
+
+	// 转换成多字节字符;
+	memset((void*)pASCIIStr, 0, nASCIIStrLen);
+	int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pASCIIStr, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+CHAR* UNICODE2UTF8(IN LPWCH lpUNICODEStr)
+{
+	if ( lpUNICODEStr == NULL )
+		return NULL;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 )
+		return NULL;
+
+	// 转换成多字节字符;
+	CHAR* pMultiByteStr = new CHAR[cbMultiByte+1];
+	memset(pMultiByteStr, 0, cbMultiByte + 1);
+	int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pMultiByteStr, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		if (pMultiByteStr) 
+			delete []pMultiByteStr;
+		return NULL;
+	}
+
+	return pMultiByteStr;
+}
+
+BOOL UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen)
+{
+	if ( lpUNICODEStr == NULL )
+		return FALSE;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 || cbMultiByte >= nUTF8StrLen )
+		return FALSE;
+
+	// 转换成多字节字符;
+	memset(pUTF8Str, 0, nUTF8StrLen);
+	int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pUTF8Str, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+CHAR* ASCII2UTF8(IN LPCCH lpASCIIStr)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+	if ( pWideChar == NULL )
+		return NULL;
+
+	// 再将UICODE转成UTF8;
+	CHAR* pUTF8 = UNICODE2UTF8(pWideChar);
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return pUTF8;
+}
+
+BOOL ASCII2UTF8(IN LPCCH lpASCIIStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+	if ( pWideChar == NULL )
+		return FALSE;
+
+	// 再将UICODE转成UTF8;
+	BOOL bResult = UNICODE2UTF8(pWideChar, pUTF8Str, nUTF8StrLen);
+
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return bResult;
+}
+
+WORD AsciiToBYTE(BYTE btSrc)
+{
+	WORD chDest = (WORD)btSrc;
+	if ((btSrc >= 'A')&&(btSrc <= 'F'))
+	{
+		chDest = chDest - 'A' + 10;
+	}
+	else if ((btSrc >= 'a')&&(btSrc <= 'f'))
+	{
+		chDest = chDest - 'a' + 10;
+	}
+	else if ((btSrc >= '0')&&(btSrc <= '9'))
+	{
+		chDest -= '0';
+	}
+	return chDest;
+}
+
+void ByteToTwoByte( unsigned char *szMsg, int nCount, unsigned char *szConvMsg )
+{
+	char ch[3];
+	unsigned char lh[2];
+	for (int i = 0; i < nCount; i++)
+	{
+		lh[0] = szMsg[i] >> 4;
+		lh[1] = szMsg[i] & 0x0f;
+	
+		for ( int j = 0; j < 2; j++ )
+		{
+			if ( lh[j] <= 9 )
+				szConvMsg[i*2 + j] = lh[j] + '0';
+			else 
+			{
+				switch ( lh[j] )
+				{
+				case 10:
+					szConvMsg[i*2 + j] = 'a';
+					break;
+				case 11:
+					szConvMsg[i*2 + j] = 'b';
+					break;
+				case 12:
+					szConvMsg[i*2 + j] = 'c';
+					break;
+				case 13:
+					szConvMsg[i*2 + j] = 'd';
+					break;
+				case 14:
+					szConvMsg[i*2 + j] = 'e';
+					break;
+				case 15:
+					szConvMsg[i*2 + j] = 'f';
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	}
+}
+
+// 1个字节转成2个十六进制字符;
+void ByteTurn2HexChar( unsigned char by, char (&szHex)[3] )
+{
+	unsigned char lh[2];
+	lh[0] = by >> 4;
+	lh[1] = by & 0x0f;
+	
+	for ( int i = 0; i < 2; i++ )
+	{
+		if ( lh[i] <= 9 )
+			szHex[i] = lh[i] + '0';
+		else 
+		{
+			switch ( lh[i] )
+			{
+			case 10:
+				szHex[i] = 'a';
+				break;
+			case 11:
+				szHex[i] = 'b';
+				break;
+			case 12:
+				szHex[i] = 'c';
+				break;
+			case 13:
+				szHex[i] = 'd';
+				break;
+			case 14:
+				szHex[i] = 'e';
+				break;
+			case 15:
+				szHex[i] = 'f';
+				break;
+			default:
+				break;
+			}
+		}
+	}
+}
+
+char Hex16(char WillChangeNum[])   //该函数把四位二进制转换成十六进制数; 
+{
+	int i;
+	i = (WillChangeNum[3]) + (WillChangeNum[2] * 10) + (WillChangeNum[1] * 100) + (WillChangeNum[0] * 1000);
+	switch(i) 
+	{
+	case 0:
+		return 0;
+	case 1:
+		return 1;
+	case 10:
+		return 2;
+	case 11:
+		return 3;
+	case 100:
+		return 4;
+	case 101:
+		return 5;
+	case 110:
+		return 6;
+	case 111:
+		return 7;
+	case 1000:
+		return 8;
+	case 1001:
+		return 9;
+	case 1010:
+		return 0x0A;
+	case 1011:
+		return 0x0B;
+	case 1100:
+		return 0x0C;
+	case 1101:
+		return 0x0D;
+	case 1110:
+		return 0x0E;
+	case 1111:
+		return 0x0F;
+	}
+	return -1;
+}

+ 53 - 0
MD5Test/stdafx.h

@@ -0,0 +1,53 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include <afx.h>
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                     // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <iostream>
+
+//////////////////////////////////////////////////////////////////////////
+// 字符串系列全局函数;
+// 将ASCII字符串转成UNICODE字符串;
+WCHAR* ASCII2UNICODE(IN LPCCH lpASCIIStr);
+BOOL   ASCII2UNICODE(IN LPCCH lpASCIIStr, OUT PWCH pUNICODEStr, IN CONST INT& nUNICODEStrLen);
+
+// 将UNICODE字符串转成ASCII字符串;
+CHAR* UNICODE2ASCII(IN LPWCH lpUNICODEStr);
+BOOL  UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen);
+
+// 将UNICODE字符串转成UFT8字符串;
+CHAR* UNICODE2UTF8(IN LPWCH lpUNICODEStr);
+BOOL  UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen);
+
+// 将ASCII字符串转成UTF8字符串;
+CHAR* ASCII2UTF8(IN LPCCH lpASCIIStr);
+BOOL  ASCII2UTF8(IN LPCCH lpASCIIStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen);
+
+WORD AsciiToBYTE(BYTE btSrc);
+
+void ByteToTwoByte( unsigned char *szMsg, int nCount, unsigned char *szConvMsg );
+
+void ByteTurn2HexChar( unsigned char by, char (&szHex)[3] );
+// TODO: 在此处引用程序需要的其他头文件

+ 24 - 0
MD5Test/targetver.h

@@ -0,0 +1,24 @@
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif

+ 258 - 0
MD5Test/timing.c

@@ -0,0 +1,258 @@
+/*
+ *  Portable interface to the CPU cycle counter
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_TIMING_C)
+
+#include "timing.h"
+
+#if defined(_WIN32)
+
+#include <windows.h>
+#include <winbase.h>
+
+struct _hr_time
+{
+    LARGE_INTEGER start;
+};
+
+#else
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <time.h>
+
+struct _hr_time
+{
+    struct timeval start;
+};
+
+#endif
+
+#if defined(POLARSSL_HAVE_ASM) && 					\
+	(defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+unsigned long hardclock( void )
+{
+    unsigned long tsc;
+    __asm   rdtsc
+    __asm   mov  [tsc], eax
+    return( tsc );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
+
+unsigned long hardclock( void )
+{
+    unsigned long tsc;
+    asm( "rdtsc" : "=a" (tsc) );
+    return( tsc );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && 			\
+	(defined(__amd64__) || defined(__x86_64__))
+
+unsigned long hardclock( void )
+{
+    unsigned long lo, hi;
+    asm( "rdtsc" : "=a" (lo), "=d" (hi) ); 
+    return( lo | (hi << 32) );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && 			\
+	(defined(__powerpc__) || defined(__ppc__))
+
+unsigned long hardclock( void )
+{
+    unsigned long tbl, tbu0, tbu1;
+
+    do
+    {
+        asm( "mftbu %0" : "=r" (tbu0) );
+        asm( "mftb  %0" : "=r" (tbl ) );
+        asm( "mftbu %0" : "=r" (tbu1) );
+    }
+    while( tbu0 != tbu1 );
+
+    return( tbl );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__sparc__)
+
+unsigned long hardclock( void )
+{
+    unsigned long tick;
+    asm( ".byte 0x83, 0x41, 0x00, 0x00" );
+    asm( "mov   %%g1, %0" : "=r" (tick) );
+    return( tick );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__alpha__)
+
+unsigned long hardclock( void )
+{
+    unsigned long cc;
+    asm( "rpcc %0" : "=r" (cc) );
+    return( cc & 0xFFFFFFFF );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__ia64__)
+
+unsigned long hardclock( void )
+{
+    unsigned long itc;
+    asm( "mov %0 = ar.itc" : "=r" (itc) );
+    return( itc );
+}
+
+#else
+
+static int hardclock_init = 0;
+static struct timeval tv_init;
+
+unsigned long hardclock( void )
+{
+    struct timeval tv_cur;
+
+    if( hardclock_init == 0 )
+    {
+        gettimeofday( &tv_init, NULL );
+        hardclock_init = 1;
+    }
+
+    gettimeofday( &tv_cur, NULL );
+    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000
+          + ( tv_cur.tv_usec - tv_init.tv_usec ) );
+}
+
+#endif /* generic */
+#endif /* IA-64   */
+#endif /* Alpha   */
+#endif /* SPARC8  */
+#endif /* PowerPC */
+#endif /* AMD64   */
+#endif /* i586+   */
+
+int alarmed = 0;
+
+#if defined(_WIN32)
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+    unsigned long delta;
+    LARGE_INTEGER offset, hfreq;
+    struct _hr_time *t = (struct _hr_time *) val;
+
+    QueryPerformanceCounter(  &offset );
+    QueryPerformanceFrequency( &hfreq );
+
+    delta = (unsigned long)( ( 1000 *
+        ( offset.QuadPart - t->start.QuadPart ) ) /
+           hfreq.QuadPart );
+
+    if( reset )
+        QueryPerformanceCounter( &t->start );
+
+    return( delta );
+}
+
+DWORD WINAPI TimerProc( LPVOID uElapse )
+{   
+    Sleep( (DWORD) uElapse );
+    alarmed = 1; 
+    return( TRUE );
+}
+
+void set_alarm( int seconds )
+{   
+    DWORD ThreadId;
+
+    alarmed = 0; 
+    CloseHandle( CreateThread( NULL, 0, TimerProc,
+        (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
+}
+
+void m_sleep( int milliseconds )
+{
+    Sleep( milliseconds );
+}
+
+#else
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+    unsigned long delta;
+    struct timeval offset;
+    struct _hr_time *t = (struct _hr_time *) val;
+
+    gettimeofday( &offset, NULL );
+
+    delta = ( offset.tv_sec  - t->start.tv_sec  ) * 1000
+          + ( offset.tv_usec - t->start.tv_usec ) / 1000;
+
+    if( reset )
+    {
+        t->start.tv_sec  = offset.tv_sec;
+        t->start.tv_usec = offset.tv_usec;
+    }
+
+    return( delta );
+}
+
+static void sighandler( int signum )
+{   
+    alarmed = 1;
+    signal( signum, sighandler );
+}
+
+void set_alarm( int seconds )
+{
+    alarmed = 0;
+    signal( SIGALRM, sighandler );
+    alarm( seconds );
+}
+
+void m_sleep( int milliseconds )
+{
+    struct timeval tv;
+
+    tv.tv_sec  = milliseconds / 1000;
+    tv.tv_usec = milliseconds * 1000;
+
+    select( 0, NULL, NULL, NULL, &tv );
+}
+
+#endif
+
+#endif

+ 73 - 0
MD5Test/timing.h

@@ -0,0 +1,73 @@
+/**
+ * \file timing.h
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_TIMING_H
+#define POLARSSL_TIMING_H
+
+/**
+ * \brief          timer structure
+ */
+struct hr_time
+{
+    unsigned char opaque[32];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int alarmed;
+
+/**
+ * \brief          Return the CPU cycle counter value
+ */
+unsigned long hardclock( void );
+
+/**
+ * \brief          Return the elapsed time in milliseconds
+ *
+ * \param val      points to a timer structure
+ * \param reset    if set to 1, the timer is restarted
+ */
+unsigned long get_timer( struct hr_time *val, int reset );
+
+/**
+ * \brief          Setup an alarm clock
+ *
+ * \param seconds  delay before the "alarmed" flag is set
+ */
+void set_alarm( int seconds );
+
+/**
+ * \brief          Sleep for a certain amount of time
+ *
+ * \param          Delay in milliseconds
+ */
+void m_sleep( int milliseconds );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* timing.h */