消息摘要算法第五版(英语:Message-Digest Algorithm 5,缩写为MD5),是当前计算机领域用于确保信息传输完整一致而广泛使用的散列算法之一(又译哈希算法、摘要算法等),主流编程语言普遍已有MD5的实现。
将数据 (如一段文字)运算变为另一固定长度值,是散列算法的基础原理,MD5的前身有MD2、MD3和MD4。MD5由MD4、MD3、MD2改进而来,主要增强算法复杂度和不可逆性。
目前,MD5算法因其普遍、稳定、快速的特点,仍广泛应用于普通 数据的错误检查领域。例如在一些BitTorrent下载中,软件将通过计算MD5检验下载到的文件片段的完整性。
MD5已经广泛使用在为文件传输提供一定的可靠性方面。例如,服务器预先提供一个MD5校验和,用户下载完文件以后, 用MD5算法计算下载文件的MD5校验和,然后通过检查这两个校验和是否一致,就能判断下载的文件是否出错。
MD5是输入不定长度信息,输出固定长度128-bits的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个 128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。
假设输入信息(input message)的长度为b(bit),我们想要产生它的报文摘要,在此处b为任意的非负整数:b也可能为0,也不一定为8的整数倍,且可能是任意大的长度。设该信息的比特流表示如下: M[0] M[1] M[2] ... M[b-1] 计算此信息的报文摘要需要如下5步:
信息计算前先要进行位补位,设补位后信息的长度为LEN(bit),则LEN%512 = 448(bit),即数据扩展至 K * 512 + 448(bit)。即K * 64+56(byte),K为整数。补位操作始终要执行,即使补位前信息的长度对512求余的结果是448。具体补位操作:补一个1,然后补0至满足上述要求。总共最少要补1bit,最多补512bit。
将输入信息的原始长度b(bit)表示成一个64-bit的数字,把它添加到上一步的结果后面(在32位的机器上,这64位将用2个字来表示并且低位在前)。当遇到b大于2^64这种极少的情况时,b的高位被截去,仅使用b的低64位。
经过上面两步,数据就被填补成长度为512(bit)的倍数。也就是说,此时的数据长度是16个字(32byte)的整数倍。此时的数据表示为: M[0 ... N-1] 其中的N是16的倍数。
用一个四个字的缓冲器(A,B,C,D)来计算报文摘要,A,B,C,D分别是32位的寄存器,初始化使用的是十六进制表示的数字,注意低字节在前: word A: 01 23 45 67 word B: 89 ab cd ef word C: fe dc ba 98 word D: 76 54 32 10
首先定义4个辅助函数,每个函数的输入是三个32位的字,输出是一个32位的字: F(X,Y,Z) = XY v not(X) Z G(X,Y,Z) = XZ v Y not(Z) H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z))
- #ifndef MD5_H
- #define MD5_H
- typedef struct
- {
- unsigned int count[2];
- unsigned int state[4];
- unsigned char buffer[64];
- }MD5_CTX;
- #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))
-
- #define ROTATE_LEFT(x,n) ((x > (32-n)))
-
- #define FF(a,b,c,d,x,s,ac) { \
- a += F(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
- }
- #define GG(a,b,c,d,x,s,ac) { \
- a += G(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
- }
- #define HH(a,b,c,d,x,s,ac) { \
- a += H(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
- }
- #define II(a,b,c,d,x,s,ac) { \
- a += I(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
- }
- void MD5Init(MD5_CTX *context);
- void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen);
- void MD5Final(MD5_CTX *context, unsigned char digest[16]);
- void MD5Transform(unsigned int state[4], unsigned char block[64]);
- void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len);
- void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len);
- #endif
- MD5算法的实现文件Md5.cpp:
- unsigned char PADDING[] = {
- 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 };
- //在逆向代码的时候,需要关注下面的特征值
-
- void MD5Init(MD5_CTX *context)
- {
- context->count[0] = 0;
- context->count[1] = 0;
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- }
- void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen)
- {
- unsigned int i = 0, index = 0, partlen = 0;
- index = (context->count[0] >> 3) & 0x3F;
- partlen = 64 - index;
- context->count[0] += inputlen count[0] count[1]++;
- context->count[1] += inputlen >> 29;
- if (inputlen >= partlen)
- {
- memcpy(&context->buffer[index], input, partlen);
- MD5Transform(context->state, context->buffer);
- for (i = partlen; i + 64 state, &input[i]);
- index = 0;
- }
- else
- {
- i = 0;
- }
- memcpy(&context->buffer[index], &input[i], inputlen - i);
- }
- void MD5Final(MD5_CTX *context, unsigned char digest[16])
- {
- unsigned int index = 0, padlen = 0;
- unsigned char bits[8];
- index = (context->count[0] >> 3) & 0x3F;
- padlen = (index count, 8);
- MD5Update(context, PADDING, padlen);
- MD5Update(context, bits, 8);
- MD5Encode(digest, context->state, 16);
- }
- void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len)
- {
- unsigned int i = 0, j = 0;
- while (j > 8) & 0xFF;
- output[j + 2] = (input[i] >> 16) & 0xFF;
- output[j + 3] = (input[i] >> 24) & 0xFF;
- i++;
- j += 4;
- }
- }
- void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len)
- {
- unsigned int i = 0, j = 0;
- while (j
- MD5算法的调用测试:
- int _tmain(int argc, _TCHAR* argv[])
- {
- int i;
- unsigned char encrypt[] = "admin";//21232f297a57a5a743894a0e4a801fc3
- unsigned char decrypt[16];
- MD5_CTX md5;
- MD5Init(&md5);
- MD5Update(&md5, encrypt, strlen((char *)encrypt));
- MD5Final(&md5, decrypt);
- //Md5加密后的32位结果
- printf("加密前:%s\n加密后16位:", encrypt);