MD5 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)
-
MD5
- 中文名
- 消息摘要算法
- 外文名
- Message Digest Algorithm MD5
- 别 称
- 摘要算法
- 提出时间
- 1991年
- 应用学科
- 信息技术,计算机科学
- 适用领域范围
- 软件下载站、论坛数据库、系统文件安全
发展历史
MD2
MD4
MD5强算法的安全性,Rivest在1990年又开发出MD4算法。MD4算法同样需要填补信息以确保信息的比特位长度减去448后能被512整除(信息比特位长度mod 512 = 448)。然后,一个以64位二进制表示的信息的最初长度被添加进来。信息被处理成512位damg?rd/merkle迭代结构的区块,而且每个区块要通过三个不同步骤的处理。Den boer和Bosselaers以及其他人很快的发现了攻击MD4版本中第一步和第三步的漏洞。Dobbertin向大家演示了如何利用一部普通的个人电脑在几分钟内找到MD4完整版本中的冲突(这个冲突实际上是一种漏洞,它将导致对不同的内容进行加密却可能得到相同的加密后结果)。毫无疑问,MD4就此被淘汰掉了。
MD5
MD5应用
一致性验证
md5典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。比如,在Unix下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如:
md5数字签名
安全访问认证
算法原理
原理

表示第i个分组,每次的运算都由前一轮的128位结果值和第i块512bit值进行运算。
MD5算法的整体流程图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 SystemImports System.Security.CryptographyImports System.TextModule 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 EndSubEndModule'此代码示例产生下面的输出:'进行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();} |
伪代码实现
弱点
MD5验证可执行文件不再可靠的消息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 ...
随机推荐
- linux内核分析 第七周
一.课堂相关 (一)预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 C代码--预处理--汇编代码--目标代码--可执行文件 预处理负责把include的文件包含进来及宏替换工作. he ...
- Asp.Net MVC 合并js或css请求
Step1:BundleConfig中注册 bundles.Add(new ScriptBundle("~/isValid").Include( "~/Scripts/ ...
- [转]MySQL5.5 my.cnf配置参考
主要配置参数转载自: http://www.linuxyw.com/a/shujuku/20130506/216.html 并稍微做了修改MyISAM部分以适应当前的环境 此配置是老男孩生产线上使用的 ...
- Android应用程序模拟手机按键
记得以前在做一个C++项目时,需要在某一步操作之后人为用代码模拟敲键盘上的回车键(Enter)效果. 出于好奇,这几天研究了一下Android中手机(或平板)上各种按键的键值.模拟方法及最终效果. 1 ...
- css动画之波纹
样式定义: #ContactAbout { height: auto; position: relative; overflow: hidden; } #sectioncontact { displa ...
- Javascript基础系列之(五)条件语句(if条件语句)
if 是flash的常用语法之一,其格式如下 if(coditon) statement1 (else statement2) 其中,coditon可以是任何表达式,甚至不比是真正的布尔值,因为Jav ...
- Nginx下Redmine配置
安装redmine依赖的所有ruby包 cd .. gem install bundler #注意是在网站根目录下执行 bundle install --without development tes ...
- “耐撕”团队 2016.03.24 站立会议
时间: 2016.03.22 17:00-17:30 18:30-19:00 成员: Z 郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), ...
- Code Hunters: Hello, world!
大家好!我们是来自MSRA联合培养班的Code Hunters小组,在未来三个月时间里我们将与殷秋丰老师一起学习高级软件工程这门课. 我们小组共有五名分别来自享誉海内外的中国科学技术大学和北京航空航天 ...
- zoj3882 博弈
我理解错题目意思,稀里糊涂A了.其实就是先手必胜. #include<stdio.h> int main() { int n; while(scanf("%d",&am ...
