MD5 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)
-
MD5
- 中文名
- 消息摘要算法
- 外文名
- Message Digest Algorithm MD5
- 别 称
- 摘要算法
- 提出时间
- 1991年
- 应用学科
- 信息技术,计算机科学
- 适用领域范围
- 软件下载站、论坛数据库、系统文件安全
发展历史
MD2
MD4
![](http://h.hiphotos.baidu.com/baike/s%3D220/sign=ed3ad55aa8d3fd1f3209a538004f25ce/aa18972bd40735fa897c08cd9e510fb30f240831.jpg)
强算法的安全性,Rivest在1990年又开发出MD4算法。MD4算法同样需要填补信息以确保信息的比特位长度减去448后能被512整除(信息比特位长度mod 512 = 448)。然后,一个以64位二进制表示的信息的最初长度被添加进来。信息被处理成512位damg?rd/merkle迭代结构的区块,而且每个区块要通过三个不同步骤的处理。Den boer和Bosselaers以及其他人很快的发现了攻击MD4版本中第一步和第三步的漏洞。Dobbertin向大家演示了如何利用一部普通的个人电脑在几分钟内找到MD4完整版本中的冲突(这个冲突实际上是一种漏洞,它将导致对不同的内容进行加密却可能得到相同的加密后结果)。毫无疑问,MD4就此被淘汰掉了。
MD5
MD5应用
一致性验证
![](http://d.hiphotos.baidu.com/baike/s%3D220/sign=f1a9cd4d6b63f624185d3e01b745eb32/caef76094b36acaf2d6bd0887cd98d1001e99c3e.jpg)
典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。比如,在Unix下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如:
![](http://h.hiphotos.baidu.com/baike/s%3D220/sign=42817f93912397ddd2799f066983b216/2cf5e0fe9925bc317bd947ec5edf8db1cb137039.jpg)
数字签名
安全访问认证
算法原理
原理
![](http://h.hiphotos.baidu.com/baike/s%3D220/sign=42817f93912397ddd2799f066983b216/2cf5e0fe9925bc317bd947ec5edf8db1cb137039.jpg)
表示第i个分组,每次的运算都由前一轮的128位结果值和第i块512bit值进行运算。
![](http://e.hiphotos.baidu.com/baike/s%3D220/sign=0d21201058ee3d6d26c680c973176d41/c75c10385343fbf2ee0d9594b17eca8065388f67.jpg)
MD5加密字符串实例
C++实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#include<iostream> #include<string> using namespace std; #define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位 #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 A 0x67452301 #define B 0xefcdab89 #define C 0x98badcfe #define D 0x10325476 //strBaye的长度 unsigned int strlength; //A,B,C,D的临时变量 unsigned int atemp; unsigned int btemp; unsigned int ctemp; unsigned int dtemp; //常量ti unsigned int(abs(sin(i+1))*(2pow32)) const unsigned int k[]={ 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee, 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8, 0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193, 0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51, 0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8, 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905, 0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681, 0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60, 0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05, 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244, 0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92, 0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314, 0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391}; //向左位移数 const unsigned int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7, 12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10, 15,21,6,10,15,21,6,10,15,21,6,10,15,21}; const char str16[]= "0123456789abcdef" ; void mainLoop(unsigned int M[]) { unsigned int f,g; unsigned int a=atemp; unsigned int b=btemp; unsigned int c=ctemp; unsigned int d=dtemp; for (unsigned int i = 0; i < 64; i++) { if (i<16){ f=F(b,c,d); g=i; } else if (i<32) { f=G(b,c,d); g=(5*i+1)%16; } else if (i<48){ f=H(b,c,d); g=(3*i+5)%16; } else { f=I(b,c,d); g=(7*i)%16; } unsigned int tmp=d; d=c; c=b; b=b+shift((a+f+k[i]+M[g]),s[i]); a=tmp; } atemp=a+atemp; btemp=b+btemp; ctemp=c+ctemp; dtemp=d+dtemp; } /* *填充函数 *处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64) *填充方式为先加一个1,其它位补零 *最后加上64位的原来长度 */ unsigned int * add(string str) { unsigned int num=((str.length()+8)/64)+1; //以512位,64个字节为一组 unsigned int *strByte= new unsigned int [num*16]; //64/4=16,所以有16个整数 strlength=num*16; for (unsigned int i = 0; i < num*16; i++) strByte[i]=0; for (unsigned int i=0; i <str.length(); i++) { strByte[i>>2]|=(str[i])<<((i%4)*8); //一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息 } strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8); //尾部添加1 一个unsigned int保存4个字符信息,所以用128左移 /* *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位 */ strByte[num*16-2]=str.length()*8; return strByte; } string changeHex( int a) { int b; string str1; string str= "" ; for ( int i=0;i<4;i++) { str1= "" ; b=((a>>i*8)%(1<<8))&0xff; //逆序处理每个字节 for ( int j = 0; j < 2; j++) { str1.insert(0,1,str16[b%16]); b=b/16; } str+=str1; } return str; } string getMD5(string source) { atemp=A; //初始化 btemp=B; ctemp=C; dtemp=D; unsigned int *strByte=add(source); for (unsigned int i=0;i<strlength/16;i++) { unsigned int num[16]; for (unsigned int j=0;j<16;j++) num[j]=strByte[i*16+j]; mainLoop(num); } return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp)); } unsigned int main() { string ss; // cin>>ss; string s=getMD5( "abc" ); cout<<s; return 0; } |
JAVA实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
public class MD5{ /* *四个链接变量 */ private final int A= 0x67452301 ; private final int B= 0xefcdab89 ; private final int C= 0x98badcfe ; private final int D= 0x10325476 ; /* *ABCD的临时变量 */ private int Atemp,Btemp,Ctemp,Dtemp; /* *常量ti *公式:floor(abs(sin(i+1))×(2pow32) */ private final int K[]={ 0xd76aa478 , 0xe8c7b756 , 0x242070db , 0xc1bdceee , 0xf57c0faf , 0x4787c62a , 0xa8304613 , 0xfd469501 , 0x698098d8 , 0x8b44f7af , 0xffff5bb1 , 0x895cd7be , 0x6b901122 , 0xfd987193 , 0xa679438e , 0x49b40821 , 0xf61e2562 , 0xc040b340 , 0x265e5a51 , 0xe9b6c7aa , 0xd62f105d , 0x02441453 , 0xd8a1e681 , 0xe7d3fbc8 , 0x21e1cde6 , 0xc33707d6 , 0xf4d50d87 , 0x455a14ed , 0xa9e3e905 , 0xfcefa3f8 , 0x676f02d9 , 0x8d2a4c8a , 0xfffa3942 , 0x8771f681 , 0x6d9d6122 , 0xfde5380c , 0xa4beea44 , 0x4bdecfa9 , 0xf6bb4b60 , 0xbebfbc70 , 0x289b7ec6 , 0xeaa127fa , 0xd4ef3085 , 0x04881d05 , 0xd9d4d039 , 0xe6db99e5 , 0x1fa27cf8 , 0xc4ac5665 , 0xf4292244 , 0x432aff97 , 0xab9423a7 , 0xfc93a039 , 0x655b59c3 , 0x8f0ccc92 , 0xffeff47d , 0x85845dd1 , 0x6fa87e4f , 0xfe2ce6e0 , 0xa3014314 , 0x4e0811a1 , 0xf7537e82 , 0xbd3af235 , 0x2ad7d2bb , 0xeb86d391 }; /* *向左位移数,计算方法未知 */ private final int s[]={ 7 , 12 , 17 , 22 , 7 , 12 , 17 , 22 , 7 , 12 , 17 , 22 , 7 , 12 , 17 , 22 , 5 , 9 , 14 , 20 , 5 , 9 , 14 , 20 , 5 , 9 , 14 , 20 , 5 , 9 , 14 , 20 , 4 , 11 , 16 , 23 , 4 , 11 , 16 , 23 , 4 , 11 , 16 , 23 , 4 , 11 , 16 , 23 , 6 , 10 , 15 , 21 , 6 , 10 , 15 , 21 , 6 , 10 , 15 , 21 , 6 , 10 , 15 , 21 }; /* *初始化函数 */ private void init(){ Atemp=A; Btemp=B; Ctemp=C; Dtemp=D; } /* *移动一定位数 */ private int shift( int a, int s){ return (a<<s)|(a>>>( 32 -s)); //右移的时候,高位一定要补零,而不是补充符号位 } /* *主循环 */ private void MainLoop( int M[]){ int F,g; int a=Atemp; int b=Btemp; int c=Ctemp; int d=Dtemp; for ( int i = 0 ; i < 64 ; i ++){ if (i< 16 ){ F=(b&c)|((~b)&d); g=i; } else if (i< 32 ){ F=(d&b)|((~d)&c); g=( 5 *i+ 1 )% 16 ; } else if (i< 48 ){ F=b^c^d; g=( 3 *i+ 5 )% 16 ; } else { F=c^(b|(~d)); g=( 7 *i)% 16 ; } int tmp=d; d=c; c=b; b=b+shift(a+F+K[i]+M[g],s[i]); a=tmp; } Atemp=a+Atemp; Btemp=b+Btemp; Ctemp=c+Ctemp; Dtemp=d+Dtemp; } /* *填充函数 *处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64) *填充方式为先加一个0,其它位补零 *最后加上64位的原来长度 */ private int [] add(String str){ int num=((str.length()+ 8 )/ 64 )+ 1 ; //以512位,64个字节为一组 int strByte[]= new int [num* 16 ]; //64/4=16,所以有16个整数 for ( int i= 0 ;i<num* 16 ;i++){ //全部初始化0 strByte[i]= 0 ; } int i; for (i= 0 ;i<str.length();i++){ strByte[i>> 2 ]|=str.charAt(i)<<((i% 4 )* 8 ); //一个整数存储四个字节,小端序 } strByte[i>> 2 ]|= 0x80 <<((i% 4 )* 8 ); //尾部添加1 /* *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位 */ strByte[num* 16 - 2 ]=str.length()* 8 ; return strByte; } /* *调用函数 */ public String getMD5(String source){ init(); int strByte[]=add(source); for ( int i= 0 ;i<strByte.length/ 16 ;i++){ int num[]= new int [ 16 ]; for ( int j= 0 ;j< 16 ;j++){ num[j]=strByte[i* 16 +j]; } MainLoop(num); } return changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp); } /* *整数变成16进制字符串 */ private String changeHex( int a){ String str= "" ; for ( int i= 0 ;i< 4 ;i++){ str+=String.format( "%2s" , Integer.toHexString(((a>>i* 8 )%( 1 << 8 ))& 0xff )).replace( ' ' , '0' ); } return str; } /* *单例 */ private static MD5 instance; public static MD5 getInstance(){ if (instance== null ){ instance= new MD5(); } return instance; } private MD5(){}; public static void main(String[] args){ String str=MD5.getInstance().getMD5( "" ); System.out.println(str); } } |
1
|
|
VB2010实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
Imports System Imports System.Security.Cryptography Imports System.Text Module Example '哈希输入字符串并返回一个 32 字符的十六进制字符串哈希。 Function GetMd5Hash( ByVal input As String ) As String '创建新的一个 MD5CryptoServiceProvider 对象的实例。 Dim md5Hasher As New MD5CryptoServiceProvider() '输入的字符串转换为字节数组,并计算哈希。 Dim data As Byte () = md5Hasher.ComputeHash(Encoding. Default .GetBytes(input)) '创建一个新的 StringBuilder 收集的字节,并创建一个字符串。 Dim sBuilder As New StringBuilder() '通过每个字节的哈希数据和格式为十六进制字符串的每一个循环。 For i As Integer = 0 To data.Length - 1 sBuilder.Append(data(i).ToString( "x2" )) Next '返回十六进制字符串。 Return sBuilder.ToString() End Function '验证对一个字符串的哈希值。 Function VerifyMd5Hash( ByVal input As String , ByVal hash As String ) As Boolean '哈希的输入。 Dim hashOfInput As String = GetMd5Hash(input) '创建 StringComparer 的哈希进行比较。 Dim comparer As StringComparer = StringComparer.OrdinalIgnoreCase Return comparer.Compare(hashOfInput, hash) = 0 End Function Sub Main() Dim source As String = "Hello World!" Dim hash As String = GetMd5Hash(source) Console.WriteLine($ "进行MD5加密的字符串为:{source},加密的结果是:{hash}。" ) Console.WriteLine( "正在验证哈希……" ) If VerifyMd5Hash(source, hash) Then Console.WriteLine("哈希值是 相同的。") Else Console.WriteLine( "哈希值是不相同的。" ) EndIf EndSub EndModule '此代码示例产生下面的输出: '进行MD5加密的字符串为:Hello World!,加密的结果是:ed076287532e86365e841e92bfc50d8c。 '正在验证哈希…… '哈希值是相同的。 |
JavaScript实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
function md5(string) { function md5_RotateLeft(lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); } function md5_AddUnsigned(lX, lY) { var lX4, lY4, lX8, lY8, lResult; lX8 = (lX & 0x80000000); lY8 = (lY & 0x80000000); lX4 = (lX & 0x40000000); lY4 = (lY & 0x40000000); lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); if (lX4 & lY4) { return (lResult ^ 0x80000000 ^ lX8 ^ lY8); } if (lX4 | lY4) { if (lResult & 0x40000000) { return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); } else { return (lResult ^ 0x40000000 ^ lX8 ^ lY8); } } else { return (lResult ^ lX8 ^ lY8); } } function md5_F(x, y, z) { return (x & y) | ((~x) & z); } function md5_G(x, y, z) { return (x & z) | (y & (~z)); } function md5_H(x, y, z) { return (x ^ y ^ z); } function md5_I(x, y, z) { return (y ^ (x | (~z))); } function md5_FF(a, b, c, d, x, s, ac) { a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac)); return md5_AddUnsigned(md5_RotateLeft(a, s), b); }; function md5_GG(a, b, c, d, x, s, ac) { a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac)); return md5_AddUnsigned(md5_RotateLeft(a, s), b); }; function md5_HH(a, b, c, d, x, s, ac) { a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac)); return md5_AddUnsigned(md5_RotateLeft(a, s), b); }; function md5_II(a, b, c, d, x, s, ac) { a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac)); return md5_AddUnsigned(md5_RotateLeft(a, s), b); }; function md5_ConvertToWordArray(string) { var lWordCount; var lMessageLength = string.length; var lNumberOfWords_temp1 = lMessageLength + 8; var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64; var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16; var lWordArray = Array(lNumberOfWords - 1); var lBytePosition = 0; var lByteCount = 0; while (lByteCount < lMessageLength) { lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition)); lByteCount++; } lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); lWordArray[lNumberOfWords - 2] = lMessageLength << 3; lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; return lWordArray; }; function md5_WordToHex(lValue) { var WordToHexValue = "" , WordToHexValue_temp = "" , lByte, lCount; for (lCount = 0; lCount <= 3; lCount++) { lByte = (lValue >>> (lCount * 8)) & 255; WordToHexValue_temp = "0" + lByte.toString(16); WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2); } return WordToHexValue; }; function md5_Utf8Encode(string) { string = string.replace(/\r\n/g, "\n" ); var utftext = "" ; for ( var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; }; var x = Array(); var k, AA, BB, CC, DD, a, b, c, d; var S11 = 7, S12 = 12, S13 = 17, S14 = 22; var S21 = 5, S22 = 9, S23 = 14, S24 = 20; var S31 = 4, S32 = 11, S33 = 16, S34 = 23; var S41 = 6, S42 = 10, S43 = 15, S44 = 21; string = md5_Utf8Encode(string); x = md5_ConvertToWordArray(string); a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; for (k = 0; k < x.length; k += 16) { AA = a; BB = b; CC = c; DD = d; a = md5_FF(a, b, c, d, x[k + 0], S11, 0xD76AA478); d = md5_FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756); c = md5_FF(c, d, a, b, x[k + 2], S13, 0x242070DB); b = md5_FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); a = md5_FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); d = md5_FF(d, a, b, c, x[k + 5], S12, 0x4787C62A); c = md5_FF(c, d, a, b, x[k + 6], S13, 0xA8304613); b = md5_FF(b, c, d, a, x[k + 7], S14, 0xFD469501); a = md5_FF(a, b, c, d, x[k + 8], S11, 0x698098D8); d = md5_FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); c = md5_FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); b = md5_FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE); a = md5_FF(a, b, c, d, x[k + 12], S11, 0x6B901122); d = md5_FF(d, a, b, c, x[k + 13], S12, 0xFD987193); c = md5_FF(c, d, a, b, x[k + 14], S13, 0xA679438E); b = md5_FF(b, c, d, a, x[k + 15], S14, 0x49B40821); a = md5_GG(a, b, c, d, x[k + 1], S21, 0xF61E2562); d = md5_GG(d, a, b, c, x[k + 6], S22, 0xC040B340); c = md5_GG(c, d, a, b, x[k + 11], S23, 0x265E5A51); b = md5_GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); a = md5_GG(a, b, c, d, x[k + 5], S21, 0xD62F105D); d = md5_GG(d, a, b, c, x[k + 10], S22, 0x2441453); c = md5_GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681); b = md5_GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); a = md5_GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); d = md5_GG(d, a, b, c, x[k + 14], S22, 0xC33707D6); c = md5_GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87); b = md5_GG(b, c, d, a, x[k + 8], S24, 0x455A14ED); a = md5_GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905); d = md5_GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); c = md5_GG(c, d, a, b, x[k + 7], S23, 0x676F02D9); b = md5_GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); a = md5_HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942); d = md5_HH(d, a, b, c, x[k + 8], S32, 0x8771F681); c = md5_HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122); b = md5_HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C); a = md5_HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); d = md5_HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); c = md5_HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); b = md5_HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); a = md5_HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6); d = md5_HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA); c = md5_HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085); b = md5_HH(b, c, d, a, x[k + 6], S34, 0x4881D05); a = md5_HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039); d = md5_HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); c = md5_HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); b = md5_HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665); a = md5_II(a, b, c, d, x[k + 0], S41, 0xF4292244); d = md5_II(d, a, b, c, x[k + 7], S42, 0x432AFF97); c = md5_II(c, d, a, b, x[k + 14], S43, 0xAB9423A7); b = md5_II(b, c, d, a, x[k + 5], S44, 0xFC93A039); a = md5_II(a, b, c, d, x[k + 12], S41, 0x655B59C3); d = md5_II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); c = md5_II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); b = md5_II(b, c, d, a, x[k + 1], S44, 0x85845DD1); a = md5_II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); d = md5_II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); c = md5_II(c, d, a, b, x[k + 6], S43, 0xA3014314); b = md5_II(b, c, d, a, x[k + 13], S44, 0x4E0811A1); a = md5_II(a, b, c, d, x[k + 4], S41, 0xF7537E82); d = md5_II(d, a, b, c, x[k + 11], S42, 0xBD3AF235); c = md5_II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); b = md5_II(b, c, d, a, x[k + 9], S44, 0xEB86D391); a = md5_AddUnsigned(a, AA); b = md5_AddUnsigned(b, BB); c = md5_AddUnsigned(c, CC); d = md5_AddUnsigned(d, DD); } return (md5_WordToHex(a) + md5_WordToHex(b) + md5_WordToHex(c) + md5_WordToHex(d)).toLowerCase(); } |
伪代码实现
弱点
![](http://f.hiphotos.baidu.com/baike/s%3D220/sign=3a1cfde7a9ec8a13101a50e2c7039157/5ab5c9ea15ce36d3b8095a383af33a87e950b1ad.jpg)
MD5破解工程权威网站是为了公开征集专门针对MD5的攻击而设立的,网站于2004年8月17日宣布:“中国研究人员发现了完整MD5算法的碰撞;Wang,Feng,Lai,Yu公布了MD5、MD4、HAVAL-128、RIPEMD-128几个 Hash函数的碰撞。这是近年来密码学领域最具实质性的研究进展。使用他们的技术,在数个小时内就可以找到MD5碰撞。……由于这个里程碑式的发现,MD5CRK项目将在随后48小时内结束”。
- TRUE - 原始 16 字符二进制格式
- FALSE - 默认。32 字符十六进制数
- 参考资料
-
- 1.How To Find Weak Input Differences For MD5 Collision Attacks .International Association for Cryptologic Research.2009年[引用日期2012-10-28]
- 2.哈希加密算法 MD5 - aTool在线工具 .aTool在线工具[引用日期2013-12-16]
- 3.维基 .维基[引用日期2013-02-3]
- 4.PHP MD5函数 .w3cschool.2014-02-2[引用日期2014-03-2]
MD5 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)的更多相关文章
- iOS 开发 Message Digest Algorithm 5(MD5加密)
MD5的全称是Message Digest Algorithm 5(消息摘要算法第五版),是计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.在90年代初由MIT Laboratory ...
- js MD5加密与 java MD5加密不一致
因为该项目会部署到多台机器,所以需要用字符生成唯一的MD5,但是js生成的MD5和java生成的MD5不一致.经过博主查阅资料发现java生成MD5用的是utf-8的编码,而且js用的是2进制.那我就 ...
- 转:MD5(Message-Digest Algorithm 一种哈希算法)
什么是MD5算法 MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位元(16位元组)的散列值(hash val ...
- password学4——Java 加密解密之消息摘要算法(MD5 SHA MAC)
Java 加密解密之消息摘要算法(MD5 SHA MAC) 消息摘要 消息摘要(Message Digest)又称为数字摘要(Digital Digest). 它是一个唯一相应一个消息或文本的固定长度 ...
- java学习-MD5消息摘要算法
md5 属于hash算法一类,是不可逆的消息摘要算法.与对称加密和非对称加密算法不一样,不需要加密密钥. 注意: md5不是加密算法,只是将数据进行散列计算后生成一个唯一值的算法,没有加密密钥也没有解 ...
- MD5消息摘要算法
Message Digest 5(消息摘要算法)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护. MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩" ...
- 第三章 消息摘要算法--MD5
注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第6章“验证数据完整性--消息摘要算法” 3.1.消息摘要算法:防止消息在传递过程中被篡改. 原理:任何消息经过消息摘要算法后 ...
- md5.digest()与md5.hexdigest()之间的区别及转换
举给例子 md5 = hashlib.md5('adsf') md5.digest() //返回: '\x05\xc1*(s48l\x94\x13\x1a\xb8\xaa\x00\xd0\x8a' # ...
- MD5工具类,提供字符串MD5加密、文件MD5值获取(校验)功能
MD5工具类,提供字符串MD5加密(校验).文件MD5值获取(校验)功能 : package com.yzu.utils; import java.io.File; import java.io.Fi ...
随机推荐
- 客户端禁用cookies后session是否还起效果
设置session和cookies的代码(webform1.aspx) if (txtName.Text == "wlzcool") { Session["uid&quo ...
- HTML5 文件异步上传 — h5uploader.js
原文地址:http://imziv.com/blog/article/read.htm?id=62 之前写过一篇H5异步文件上传的文章, 但是很多朋友看着我的这个教程还是出现很多问题,文章写的不是很好 ...
- error C3872: "0xa0": 此字符不允许在标识符中使用
整理:这是因为直接复制代码的问题.0xa0是十六进制数,换成十进制就是160,表示汉字的开始. 解决办法:在报错的代码行检查两边的空格,用英文输入法的空格替换掉. 万恶的网络,万恶的word,这些无厘 ...
- 记录我开始学习 Git的路程
工作半年多了,总觉得没学到什么东西,于是乎找了个Git学习一下,感觉还蛮厉害的样子.为此记录下我的路程 2015,11,26 更新 前面的路都挺艰难的,在官网下载msysgit网速几乎为0(心情千万只 ...
- Linq之Lambda表达式初步认识
目录 写在前面 匿名方法 一个例子 Lambda 定义 一个例子 总结 参考文章 写在前面 元旦三天在家闲着无事,就看了看Linq的相关内容,也准备系统的学习一下,作为学习Linq的前奏,还是先得说说 ...
- EntityFramework_MVC4中EF5 新手入门教程之七 ---7.通过 Entity Framework 处理并发
在以前的两个教程你对关联数据进行了操作.本教程展示如何处理并发性.您将创建工作与各Department实体的 web 页和页,编辑和删除Department实体将处理并发错误.下面的插图显示索引和删除 ...
- EntityFramework_MVC4中EF5 新手入门教程之六 ---6.通过 Entity Framework 更新关联数据
在前面的教程中,您将显示相关的数据 :在本教程中,您会更新相关的数据.对于大多数的关系,这个目标是可以通过更新相应的外键字段来达到的.对于多对多关系,实体框架并不直接,暴露联接表,因此您必须显式添加和 ...
- 每天一个linux命令(47):traceroute命令
通过traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径.当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不一 ...
- 每天一个linux命令(22):chgrp命令
在 lunix系统里,文件或目录的权限的掌控以拥有者及所诉群组来管理.可以使用chgrp指令取变更文件与目录所属群组,这种方式采用群组名称或群组识别 码都可以.Chgrp命令就是change grou ...
- Daily Scrum – 1/18
Meeting Minutes 完成了User Course, 与 Tips 的设计; 修复了一系列Bug; 完成了夜间模式: Burndown Progress part 组员 今日工作 Time ...