Md5c语言加密算法

MD5加密算法简介

一.概述

MD5的全称是message-digest algorithm 5,由麻省理工学院计算机科学实验室和rsa data security inc的ronald l. rivest在90年代初开发,由md2、md3和md4开发。其作用是在用数字签名软件签署私钥之前,将大容量的信息“压缩”成安全的格式(即将任意长度的字节串转换成一定长度的大整数)。无论是md2、md4还是md5,都需要得到一个随机长度的信息,生成一个128位的信息摘要。虽然这些算法的结构或多或少有些相似,但md2的设计与md4和md5完全不同,因为md2是为8位机优化的,而md4和md5是为32位机设计的。这三种算法的描述和C语言的源代码在internet rfcs 1321()中有详细的描述,这是ronald l. rivest于1992年8月提交给ieft的最权威的文档。

Rivest在1989年开发了md2算法。在这个算法中,首先用数据补充信息,使信息的字节长度是16的倍数。然后,16位校验和被附加到消息的末尾。并基于这个新生成的信息计算哈希值。后来,rogier和chauvaud发现,如果忽略校验和,就会发生md2冲突。md2算法的加密结果是唯一的,没有重复。

为了加强算法的安全性,rivest在1990年开发了md4算法。md4算法还需要填充信息,以保证信息的字节长度加448后能被512整除(信息字节长度mod 512 = 448)。然后,添加64位二进制消息的初始长度。信息处理成512位damg?rd/merkle迭代结构的块,每个块都要经过三个不同的步骤。Den boer、bosselaers和其他人很快发现了攻击md4版本中第一步和第三步的漏洞。Dobbertin向您展示了如何使用一台普通的个人电脑在几分钟内找到完整版md4中的冲突(这种冲突实际上是一个漏洞,会导致不同内容的加密但可能得到相同的加密结果)。毫无疑问,md4已经被淘汰了。

md4算法的安全性虽然有这么大的漏洞,但是对后来发展起来的几个信息安全加密算法的出现起到了重要的指导作用。除了md5,还有sha-1,ripe-md,哈弗也很有名。

一年后的1991年,rivest开发了一种更成熟的md5算法。它在md4的基础上增加了“安全带”的概念。虽然md5比md4稍慢,但它更安全。该算法显然由四个步骤组成,与md4设计略有不同。在md5算法中,信息摘要的大小和填充的必要条件与md4完全相同。Den boer和bosselaers曾经发现了md5算法中的伪碰撞,但是没有其他发现的加密结果。

Van oorschot和wiener曾经考虑使用一种暴力哈希函数来搜索哈希中的冲突,他们猜测一台专门设计来搜索md5冲突的机器(1994年这台机器的制造成本约为100万美元)平均每24天就可以找到一个冲突。但是从1991年到2001年,并没有md6或者其他什么新的算法取代md5,所以我们可以看到这个缺陷并没有对md5的安全性造成太大的影响。以上都不足以成为md5实际应用中的问题。而且,由于使用md5算法不需要支付任何版权费用,所以在一般情况下(非绝密应用领域。但即使用在绝密领域,md5也是一种优秀的中间技术),md5在任何情况下都应该被认为是非常安全的。

二、算法的应用

md5的典型应用是为一条消息生成消息摘要,以防止它被篡改。比如在unix下,很多软件在下载的时候都有一个文件名相同,文件扩展名为. md5的文件。在这个文件中,通常只有一行文本,一般结构如下:

MD5(tanajiya.tar.gz)= 0ca 175 b 9 c 0 f 726 a 831d 895 e 269332461

这是tanajiya.tar.gz文档的数字签名。Md5将整个文件视为一个大的文本消息,通过其不可逆的字符串变换算法,生成这个唯一的md5消息摘要。如果以后在传播这个文件的过程中,无论文件的内容发生了什么变化(包括人为修改或者下载时线路不稳定导致的传输错误等。),只要重新计算一下这个文件的md5,就会发现信息汇总是不一样的,所以可以确定你得到的只是一个不正确的文件。如果有第三方认证机构,md5还可以防止文档作者的“否认”,也就是所谓的数字签名应用。

Md5也广泛应用于加密和解密技术。例如,在unix系统中,用户的密码通过md5(或其他类似的计算方法)加密,并存储在文件系统中。当用户登录时,系统将用户输入的密码计算为md5值,然后与文件系统中保存的md5值进行比较,以确定输入的密码是否正确。通过这样的步骤,系统可以在不知道用户密码明码的情况下,确定用户登录系统的合法性。这样既可以防止用户的密码被拥有系统管理员权限的用户知道,也在一定程度上增加了密码破解的难度。

正是因为这个原因,黑客破译密码最常用的方法之一就是一种叫做“润子典”的方法。字典的获取方式有两种,一种是日常收集的用作密码的字符串表,另一种是通过排列组合的方法生成的。首先用md5程序计算这些字典项的md5值,然后在这个字典中查找目标的md5值。我们假设密码的最大长度是8个字节,密码只能是字母和数字,总共26 ^ 26 ^ 10 = 62个字符。字典中的条目数是P (62,1) P (62,2)...P (62,8),这已经是一个非常天文的数字了,需要tb来存储这个字典。这种加密技术在unix系统中被广泛使用,这也是unix系统比一般操作系统更健壮的重要原因。

三、算法描述

对md5算法的简单描述可以是这样的:md5将输入的信息处理成512位的数据包,每个数据包被分成16个32位的数据包。经过一系列的处理后,算法的输出由四个32位的包组成,将这四个32位的包串联起来将生成一个128位的哈希值。

在md5算法中,需要先填充信息,这样字节长度为512的结果等于448。因此,信息的比特长度将扩展到n*512 448,即n*64 56字节,其中n是正整数。填充的方法如下:在信息后面填充一个1和无数个0,不满足以上条件不要停止用0填充信息。然后,在该结果之后,附加以64位二进制表示的预填充信息长度。经过这两步处理后,当前信息字长= n * 512 448 64 =(n-1)* 512,即长度正好是512的整数倍。这样做的原因是为了满足后期处理中对信息长度的要求。

md5中有四个32位整数参数称为chaining变量,分别是:a=0x01234567,b=0x89abcdef,c=0xfedcba98,d=0x76543210。

当这四个链接变量被设置时,算法开始进入四轮循环操作。循环数是信息中512位信息包的数量。

将上述四个链接变量复制到另外四个变量中:A到A,B到B,C到C,D到D。

主要有四个循环(md4只有三个),每个循环都很相似。第一轮是16次手术。对A、B、C、D中的三个做一次非线性函数运算,每次运算,然后将第四个变量、文本的一个子组和一个常数加到结果中。然后将结果右移一个不定数,加上A、B、C或D中的一个,最后用结果替换A、B、C或D中的一个。

让我们来看看每个操作中使用的四个非线性函数(每轮一个)。

f(x,y,z) =(xy)|((~x)z)

g(x,y,z) =(xz)|(y(~z))

=x^y^z(x,y,z)

i(x,y,z)=y^(x|(~z))

(是与|是或~是与否,异或)

这四个函数的解释:如果X,Y,Z对应的位是独立且一致的,那么结果的每一位也应该是独立且一致的。

f是位运算的函数。即,如果x,则y,否则z。函数h是按位奇偶运算符。

假设mj表示消息的第j个子分组(从0到15 ),

Ff(a,b,c,d,mj,s,ti)表示a=b ((a (f(b,c,d) mj ti))

Gg(a,b,c,d,mj,s,ti)表示a=b ((a (g(b,c,d) mj ti))

Hh(a,b,c,d,mj,s,ti)表示a=b ((a (h(b,c,d) mj ti))。

Ii(a,b,c,d,mj,s,ti)表示a=b ((a (i(b,c,d) mj ti))

这四轮(64步)是:

第一轮

ff(a,b,c,d,m0,7,0x d 76 a 478)

ff(d,a,b,c,m1,12,0xe8c7b756)

ff(c,d,a,b,m2,17,0x242070db)

ff(b,c,d,a,m3,22,0xc1bdceee)

ff(a,b,c,d,m4,7,0xf57c0faf)

ff(d,a,b,c,m5,12,0x4787c62a)

ff(c、d、a、b、m6、17、0xa8304613)

ff(b,c,d,a,m7,22,0xfd469501)

ff(a,b,c,d,m8,7,0x698098d8)

ff(d,a,b,c,m9,12,0x8b44f7af)

ff(c,d,a,b,m10,17,0x ffff 5b 1)

ff(b,c,d,a,m11,22,0x895cd7be)

ff(a,b,c,d,m12,7,0x6b901122)

ff(d,a,b,c,m13,12,0xfd987193)

ff(c,d,a,b,m14,17,0xa679438e)

ff(b,c,d,a,m15,22,0x49b40821)

第二轮

gg(a,b,c,d,m1,5,0xf61e2562)

gg(d,a,b,c,m6,9,0xc040b340)

gg(c,d,a,b,m11,14,0x265e5a51)

gg(b,c,d,a,m0,20,0xe9b6c7aa)

gg(a,b,c,d,m5,5,0xd62f105d)

gg(d,a,b,c,m10,9,0x02441453)

gg(c,d,a,b,m15,14,0xd8a1e681)

gg(b,c,d,a,m4,20,0xe7d3fbc8)

gg(a,b,c,d,m9,5,0x21e1cde6)

gg(d,a,b,c,m14,9,0xc33707d6)

gg(c,d,a,b,m3,14,0xf4d50d87)

gg(b,c,d,a,m8,20,0x455a14ed)

gg(a,b,c,d,m13,5,0xa9e3e905)

gg(d,a,b,c,m2,9,0xfcefa3f8)

gg(c,d,a,b,m7,14,0x676f02d9)

gg(b,c,d,a,m12,20,0x8d2a4c8a)

第三轮

hh(a,b,c,d,m5,4,0xfffa3942)

hh(d,a,b,c,m8,11,0x8771f681)

hh(c,d,a,b,m11,16,0x6d9d6122)

hh(b,c,d,a,m14,23,0xfde5380c)

hh(a,b,c,d,m1,4,0xa4beea44)

hh(d,a,b,c,m4,11,0x4bdecfa9)

hh(c,d,a,b,m7,16,0xf6bb4b60)

hh(b,c,d,a,m10,23,0x befbc 70)

hh(a,b,c,d,m13,4,0x289b7ec6)

hh(d,a,b,c,m0,11,0xeaa127fa)

hh(c,d,a,b,m3,16,0xd4ef3085)

hh(b,c,d,a,m6,23,0x04881d05)

hh(a,b,c,d,m9,4,0xd9d4d039)

hh(d,a,b,c,m12,11,0xe6db99e5)

hh(c,d,a,b,m15,16,0x1fa27cf8)

hh(b,c,d,a,m2,23,0xc4ac5665)

第四轮

二(a,b,c,d,m0,6,0xf4292244)

二(d,a,b,c,m7,10,0x 432 af 97)

二(c,d,a,b,m14,15,0xab9423a7)

二(b,c,d,a,m5,21,0xfc93a039)

二(a,b,c,d,m12,6,0x655b59c3)

二(d,a,b,c,m3,10,0x8f0ccc92)

二(c,d,a,b,m10,15,0xffeff47d)

二(b,c,d,a,m1,21,0x85845dd1)

二(a,b,c,d,m8,6,0x6fa87e4f)

二(d,a,b,c,m15,10,0xfe2ce6e0)

二(c、d、a、b、m6、15、0xa3014314)

二(b,c,d,a,m13,21,0x4e0811a1)

二(a、b、c、d、m4、6、0xf7537e82)

二(d,a,b,c,m11,10,0xbd3af235)

二(c,d,a,b,m2,15,0x2ad7d2bb)

二(b,c,d,a,m9,21,0xeb86d391)

常数ti可以选择如下:

在步骤I中,ti是4294967296*abs(sin(i))的整数部分,I的单位是弧度。(4294967296等于2的32次方)

这些都做好之后,再分别加上A,B,C,D。然后对下一个数据包继续运行算法,最终输出是A、B、C、D的级联..

当你按照我上面提到的方法实现md5算法的时候,你可以用下面的信息对你的程序做一个简单的测试,看看程序有没有错误。

MD5(" " = d 41 D8 CD 98 f 00 b 204 e 9800998 ECF 8427 e

MD5(" a ")= 0cc 175 b 9 c 0 f1 b 6 a 831 c 399 e 269772661

MD5(" ABC ")= 900150983 CD 24 FB 0d 6963 f 7d 28 e 17 f 72

md5("消息摘要")= f96b 697 D7 CB 7938d 525 a2 f 31 AAF 161d 0

MD5(" abcdefghijklmnopqrstuvwxyz ")= C3 fcd 3d 76192 e 4007 DFB 496 CCA 67 e 13 b

MD5(" abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz 0123456789 ")= d 174 ab 98d 277d 9 f 5a 5611 C2 C9 f 419d 9 f

MD5(" 12345678901234567890123456789012345678901234567890123456789012345678901234567890 ")= 57 EDF 4a 22 be 3c 955 AC 49 da 2e 2107 b67a

如果你用上面的信息去测试你做过的md5算法的例子,最后的结论和标准答案完全一样,那么我在这里要说恭喜你了。要知道,我的程序第一次编译成功的时候并没有得到和上面一样的结果。

第四,MD5的安全性

md5对md4的改进:

1.增加了第四轮;

2.每一步都有唯一的加法常数;

3.第二轮为了削弱函数G的对称性,从(xy)|(xz)|(yz)变为(xz)|(y(~ z));

4.第一步加上上一步的结果,会造成更快的雪崩效应;

5.改变了第二轮和第三轮访问消息子包的顺序,使它们更加不同;

6.每轮循环左移的位移近似优化,以达到更快的雪崩效应。每个车轮的位移彼此不同。

找到MD5加密算法的C语言源代码 (转载)# included dio . h # included lib . h # include memory . h # include time . h # include no . h # include string . h # include sys/socket . h # include sys/types . h # include netinet/in . h # include arpa/inet . h # include netdb . h # include "../MD5/MD5 . h " #定义T1 0x d 76 a 478 #定义T2 0x e 8 c 7 b 756 #定义T3 0x242070db #定义T4 0x C1 BDC eee #定义T5 0x f 57 c 0 faf #定义T6 0x 4787 c 62 a #定义T7 0xa8304613 #定义T8 0xfd469501 #定义T9 0x698098d8 #定义T10 0x 8b 44 f 7 af #定义T11 0x ffff 5 bb 1 #定义 定义T26 0xc33707d6 #定义T27 0x f 4d 50d 87 #定义T28 0x 455 a 14 ed #定义T29 0x a9 E3 e 905 #定义T30 0x fcefa 3 f 8 #定义T31 0x676f02d9 #定义T32 0x 8d 2 a4 c 8 a #定义T33 0xfffa3942 #定义T34 0x8771f681 #定义T35 0x6d9d6122 #定义T36 0xfde5380c #定义T37 0x a4 bee 定义T50 0x432aff97 #定义T51 0xab9423a7 #定义T52 0x fc 93 a 039 #定义T53 0x 655 b 59 C 3 #定义T54 0x 8 f 0 CCC 92 #定义T55 0xffeff47d #定义T56 0x85845dd1 #定义T57 0x 6 fa 87 E4 f #定义T58 0x Fe 2 ce 6 e 0 #定义T59 0xa3014314 #定义T60 0x4e0811a1 #定义T61 0x #包含stdio.h

#包含stdlib.h

#包含字符串. h

#如果定义了(__APPLE__)

# define COMMON _ DIGEST _ FOR _ OPENSSL

#包含CommonCrypto/CommonDigest.h

#定义SHA1 SHA1 CC

#否则

#包含openssl/md5.h

#endif

//这是自己写的函数,用来计算MD5。

//参数str:要转换的字符串。

//参数lengthL:字符串的长度可以通过strlen(str)直接得到。

//返回值:MD5字符串

char * str 2d 5(const char * str,int length) {

int n;

MD5 _ CTX c;

无符号字符摘要[16];

char * out =(char *)malloc(33);

MD5 _ Init(c);

while(长度0) {

if(长度512) {

MD5_Update(c,str,512);

}否则{

MD5_Update(c,str,length);

}

长度-= 512;

str = 512

}

MD5_Final(digest,c);

for(n = 0;n16;n) {

snprintf((out[n*2]),16*2,“x”,(unsigned int)digest[n]);

}

退了出来;

}

int main(int argc,char **argv) {

char *output = str2md5("hello ",strlen(" hello "));

printf("%s\n ",输出);

//上面会输出hello的MD5字符串:

//5d 41402 ABC 4b 2 a 76 b 9719d 911017 c 592

免费(输出);

返回0;

}

如何在VS2013中调用C语言的md5加密函数? 1.主要是调用库函数。md5加密说到底也是函数计算,不存在思维的问题。理解发明的MD5算法本质上是一个数学问题。

2.常规:

#ifndef MD5_H

#定义MD5_H

typedef结构

{

无符号整数计数[2];

无符号整数状态[4];

无符号字符缓冲区[64];

} MD5 _ CTX;

#定义F(x,y,z) ((x,y) | (~x,z))

#定义G(x,y,z) ((x z) | (y ~z))

#定义H(x,y,z) (x^y^z)

#定义I(x,y,z) (y ^ (x | ~z))

#define ROTATE_LEFT(x,n) ((x n) | (x (32-n)))

#定义FF(a,b,c,d,x,s,ac) \

{ \

a = F(b,c,d)x AC;\

a = ROTATE_LEFT(a,s);\

a = b;\

}

#定义GG(a,b,c,d,x,s,ac) \

{ \

a = G(b,c,d)x AC;\

a = ROTATE_LEFT(a,s);\

a = b;\

}

#定义HH(a,b,c,d,x,s,ac) \

{ \

a = H(b,c,d)x AC;\

a = ROTATE_LEFT(a,s);\

a = b;\

}

#定义II(a、b、c、d、x、s、ac) \

{ \

a = I(b,c,d)x AC;\

a = ROTATE_LEFT(a,s);\

a = b;\

}

void MD5 init(MD5 _ CTX *上下文);

void MD5 update(MD5 _ CTX *上下文,无符号char *输入,无符号int input len);

void MD5 final(MD5 _ CTX *上下文,无符号字符摘要[16]);

void MD 5 transform(unsigned int state[4],unsigned char block[64]);

void MD 5 encode(unsigned char * output,unsigned int *input,unsigned int len);

void MD 5 decode(unsigned int * output,unsigned char *input,unsigned int len);

#endif

源文件md5.c

#包含内存. h

#包含“md5.h”

无符号字符填充[]={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 MD5 init(MD5 _ CTX *上下文)

{

上下文计数[0]= 0;

上下文计数[1]= 0;

上下文状态[0]= 0x 67452301;

上下文状态[1]= 0x efcdab 89;

上下文状态[2]= 0x 98 bad cfe;

上下文状态[3]= 0x 10325476;

}

void MD5 update(MD5 _ CTX *上下文,无符号字符*输入,无符号整数输入)

{

unsigned int i = 0,index = 0,partlen = 0;

index =(上下文计数[0]3)0x3F;

part len = 64-index;

上下文计数[0] =输入长度3;

if(上下文计数[0](输入长度3))

上下文计数[1];

上下文计数[1] =输入长度29;

if(inputlen = partlen)

{

memcpy(上下文缓冲区[索引],输入,部分长度);

MD5Transform(上下文状态,上下文缓冲区);

for(I = part len;i64 = input len;i =64)

MD5Transform(上下文状态,输入[I]);

索引= 0;

}

其他

{

I = 0;

}

memcpy(context-buffer[index],input[i],inputlen-I);

}

void MD5 final(MD5 _ CTX *上下文,无符号字符摘要[16])

{

unsigned int index = 0,padlen = 0;

无符号字符位[8];

index =(上下文计数[0]3)0x3F;

padlen =(指数56)?(56指数):(120指数);

MD5Encode(位,上下文计数,8);

MD5Update(context,PADDING,padlen);

MD5Update(上下文,位,8);

MD5Encode(摘要,上下文状态,16);

}

void MD 5 encode(unsigned char * output,unsigned int *input,unsigned int len)

{

无符号int i = 0,j = 0;

while(j len)

{

output[j]= input[I]0x ff;

输出[j 1] =(输入[I]8)0x ff;

output[j 2]=(input[I]16)0x ff;

output[j 3]=(input[I]24)0x ff;

我;

j = 4;

}

}

void MD 5 decode(unsigned int * output,unsigned char *input,unsigned int len)

{

无符号int i = 0,j = 0;

while(j len)

{

output[i] = (input[j]) |

(输入[j 1] 8) |

(输入[j 2] 16) |

(输入[j 3]24);

我;

j = 4;

}

}

void MD5Transform(无符号int state[4],无符号char block[64])

{

无符号int a = state[0];

无符号int b = state[1];

unsigned int c = state[2];

无符号int d = state[3];

无符号int x[64];

MD5Decode(x,block,64);

FF(a,b,c,d,x[ 0],7,0x d 76 a 478);/* 1 */

FF(d,a,b,c,x[ 1],12,0 xe8 c7b 756);/* 2 */

FF(c,d,a,b,x[ 2],17,0x 242070 db);/* 3 */

FF(b,c,d,a,x[ 3],22,0x C1 BDC eee);/* 4 */

FF(a,b,c,d,x[ 4],7,0x f 57 c 0 faf);/* 5 */

FF(d,a,b,c,x[ 5],12,0x 4787 c62a);/* 6 */

FF(c,d,a,b,x[ 6],17,0xa 8304613);/* 7 */

FF(b,c,d,a,x[ 7],22,0x FD 469501);/* 8 */

FF(a,b,c,d,x[ 8],7,0x 698098 D8);/* 9 */

FF(d,a,b,c,x[ 9],12,0 x8b 44 f 7 af);/* 10 */

FF(c,d,a,b,x[10],17,0x ffff 5 bb 1);/* 11 */

FF(b,c,d,a,x[11],22,0x 895 CD 7 be);/* 12 */

FF(a,b,c,d,x[12],7,0x6b 901122);/* 13 */

FF(d,a,b,c,x[13],12,0x FD 987193);/* 14 */

FF(c,d,a,b,x[14],17,0xa 679438 e);/* 15 */

FF(b,c,d,a,x[15],22,0x49b 40821);/* 16 */

相关文章

发表新评论