MD5,全称为 Message Digest Algorithm 5(消息摘要算法第五版).
MD5加密后是一个字节数组, 但我们一般是取其十六进制的字符串表示法,当然,十六进制数字符串是区分大小写,在 mysql数据库,Java,和JavaScript语言中,一般是使用小写的字符串来表示, 而在 Oracle数据库官方提供的包中,返回的是大写字符串,这算是一个坑,如果你想要执行多次 md5,可能需要转换为小写.
相关的代码如下:
1. Java版MD5
MD5Util.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
|
package com.cncounter.util.common; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Java消息摘要算法 MD5 工具类,其实其他摘要算法的实现也类似 */ public class MD5Util { /** * 对文本执行 md5 摘要加密, 此算法与 mysql,JavaScript生成的md5摘要进行过一致性对比. * @param plainText * @return 返回值中的字母为小写 */ public static String md5(String plainText) { if ( null == plainText) { plainText = "" ; } String MD5Str = "" ; try { // JDK 6 支持以下6种消息摘要算法,不区分大小写 // md5,sha(sha-1),md2,sha-256,sha-384,sha-512 MessageDigest md = MessageDigest.getInstance( "MD5" ); md.update(plainText.getBytes()); byte b[] = md.digest(); int i; StringBuilder builder = new StringBuilder( 32 ); for ( int offset = 0 ; offset < b.length; offset++) { i = b[offset]; if (i < 0 ) i += 256 ; if (i < 16 ) builder.append( "0" ); builder.append(Integer.toHexString(i)); } MD5Str = builder.toString(); // LogUtil.println("result: " + buf.toString());// 32位的加密 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return MD5Str; } // 一个简版测试 public static void main(String[] args) { String m1 = md5( "1" ); String m2 = md5(m1); /* 输出为 * m1=c4ca4238a0b923820dcc509a6f75849b * m2=28c8edde3d61a0411511d3b1866f0636 */ System.out.println( "m1=" +m1); System.out.println( "m2=" +m2); } } |
2. MySQL版MD5
MySQL直接支持 md5函数调用
1
|
select md5( '1' ) as m1, md5(md5( '1' )) as m2; |
执行结果为:
1
2
3
4
5
6
7
|
MariaDB [(none)]> select md5('1') as m1, md5(md5('1')) as m2; +----------------------------------+----------------------------------+ | m1 | m2 | +----------------------------------+----------------------------------+ | c4ca4238a0b923820dcc509a6f75849b | 28c8edde3d61a0411511d3b1866f0636 | +----------------------------------+----------------------------------+ 1 row in set (0.00 sec) |
3. JavaScript 版MD5函数
md5.js 代码如下:
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
/*! JavaScript 的 MD5 实现 */ // 括号表达式, (xxxxx) 是用来将内部的语句、表达式的结果作为一个结果. // 常见的是将json字符串用 eval 解析时,需要 eval("(" +jsonstr+ ")"); // () 内部定义了一个空间, 里面定义的变量不会污染到全局空间,很适合做lib // (function UMD(对象/函数名name, 上下文this, 函数/对象的定义)) 返回一个匿名函数 // 因为第一个括号内 的结果是一个函数,而函数可以这样调用: (function(形参){})(实参); // 这种匿名函数被浏览器解析后会自动执行一次. (function UMD(name, context, definition) { if ( typeof module !== "undefined" && module.exports) { // 如果 module 存在,并且module.exports存在,则将赋值结果赋给 它 // 可以不用管 module.exports = definition(); } else if ( typeof define === "function" && define.amd) { // 如果 define 这个函数存在,应该是另一个基础类库,则使用define // 可以不用管 define(definition); } else { // 简单一点,可以看成: 调用传入的definition函数,将返回的对象绑定到全局空间 // 当然,根据传入的上下文不同,也可以绑定到其他对象下面,成为一个属性方法. context[name] = definition(name, context); } } )( "md5" , this , function DEF(name, context) { "use strict" ; // 上面的 use strict 表示严格语法模式,有错误就拒绝执行. // 而普通的JS,是解释执行,不执行的地方,有些错误也不影响其他代码的执行 // 作为类库,使用严格模式是很有必要的.严格模式声明必须放到一个namespace空间的最起始处. // var old_public_api = (context || {})[name]; // 最后要返回的对象/函数. function md5_func(text) { return hex_md5(text); }; // 下面一堆是具体的算法... 可以先不用管 ///////////////////////////////////////////////////// //计算MD5 var hexcase = 0 ; function hex_md5(a) { if (a == "" ) return a; return rstr2hex(rstr_md5(str2rstr_utf8(a))) }; function hex_hmac_md5(a, b) { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(a), str2rstr_utf8(b))) }; function md5_vm_test() { return hex_md5( "abc" ).toLowerCase() == "900150983cd24fb0d6963f7d28e17f72" }; function rstr_md5(a) { return binl2rstr(binl_md5(rstr2binl(a), a.length * 8 )) }; function rstr_hmac_md5(c, f) { var e = rstr2binl(c); if (e.length > 16 ) { e = binl_md5(e, c.length * 8 ) } var a = Array( 16 ), d = Array( 16 ); for (var b = 0 ; b < 16 ; b++) { a[b] = e[b] ^ 909522486 ; d[b] = e[b] ^ 1549556828 } var g = binl_md5(a.concat(rstr2binl(f)), 512 + f.length * 8 ); return binl2rstr(binl_md5(d.concat(g), 512 + 128 )) }; function rstr2hex(c) { try { hexcase } catch (g) { hexcase = 0 } var f = hexcase ? "0123456789ABCDEF" : "0123456789abcdef" ; var b = "" ; var a; for (var d = 0 ; d < c.length; d++) { a = c.charCodeAt(d); b += f.charAt((a >>> 4 ) & 15 ) + f.charAt(a & 15 ) } return b }; function str2rstr_utf8(c) { var b = "" ; var d = - 1 ; var a, e; while (++d < c.length) { a = c.charCodeAt(d); e = d + 1 < c.length ? c.charCodeAt(d + 1 ) : 0 ; if ( 55296 <= a && a <= 56319 && 56320 <= e && e <= 57343 ) { a = 65536 + ((a & 1023 ) << 10 ) + (e & 1023 ); d++ } if (a <= 127 ) { b += String.fromCharCode(a) } else { if (a <= 2047 ) { b += String.fromCharCode( 192 | ((a >>> 6 ) & 31 ), 128 | (a & 63 )) } else { if (a <= 65535 ) { b += String.fromCharCode( 224 | ((a >>> 12 ) & 15 ), 128 | ((a >>> 6 ) & 63 ), 128 | (a & 63 )) } else { if (a <= 2097151 ) { b += String.fromCharCode( 240 | ((a >>> 18 ) & 7 ), 128 | ((a >>> 12 ) & 63 ), 128 | ((a >>> 6 ) & 63 ), 128 | (a & 63 )) } } } } } return b }; function rstr2binl(b) { var a = Array(b.length >> 2 ); for (var c = 0 ; c < a.length; c++) { a[c] = 0 } for (var c = 0 ; c < b.length * 8 ; c += 8 ) { a[c >> 5 ] |= (b.charCodeAt(c / 8 ) & 255 ) << (c % 32 ) } return a }; function binl2rstr(b) { var a = "" ; for (var c = 0 ; c < b.length * 32 ; c += 8 ) { a += String.fromCharCode((b[c >> 5 ] >>> (c % 32 )) & 255 ) } return a }; function binl_md5(p, k) { p[k >> 5 ] |= 128 << ((k) % 32 ); p[(((k + 64 ) >>> 9 ) << 4 ) + 14 ] = k; var o = 1732584193 ; var n = - 271733879 ; var m = - 1732584194 ; var l = 271733878 ; for (var g = 0 ; g < p.length; g += 16 ) { var j = o; var h = n; var f = m; var e = l; o = md5_ff(o, n, m, l, p[g + 0 ], 7 , - 680876936 ); l = md5_ff(l, o, n, m, p[g + 1 ], 12 , - 389564586 ); m = md5_ff(m, l, o, n, p[g + 2 ], 17 , 606105819 ); n = md5_ff(n, m, l, o, p[g + 3 ], 22 , - 1044525330 ); o = md5_ff(o, n, m, l, p[g + 4 ], 7 , - 176418897 ); l = md5_ff(l, o, n, m, p[g + 5 ], 12 , 1200080426 ); m = md5_ff(m, l, o, n, p[g + 6 ], 17 , - 1473231341 ); n = md5_ff(n, m, l, o, p[g + 7 ], 22 , - 45705983 ); o = md5_ff(o, n, m, l, p[g + 8 ], 7 , 1770035416 ); l = md5_ff(l, o, n, m, p[g + 9 ], 12 , - 1958414417 ); m = md5_ff(m, l, o, n, p[g + 10 ], 17 , - 42063 ); n = md5_ff(n, m, l, o, p[g + 11 ], 22 , - 1990404162 ); o = md5_ff(o, n, m, l, p[g + 12 ], 7 , 1804603682 ); l = md5_ff(l, o, n, m, p[g + 13 ], 12 , - 40341101 ); m = md5_ff(m, l, o, n, p[g + 14 ], 17 , - 1502002290 ); n = md5_ff(n, m, l, o, p[g + 15 ], 22 , 1236535329 ); o = md5_gg(o, n, m, l, p[g + 1 ], 5 , - 165796510 ); l = md5_gg(l, o, n, m, p[g + 6 ], 9 , - 1069501632 ); m = md5_gg(m, l, o, n, p[g + 11 ], 14 , 643717713 ); n = md5_gg(n, m, l, o, p[g + 0 ], 20 , - 373897302 ); o = md5_gg(o, n, m, l, p[g + 5 ], 5 , - 701558691 ); l = md5_gg(l, o, n, m, p[g + 10 ], 9 , 38016083 ); m = md5_gg(m, l, o, n, p[g + 15 ], 14 , - 660478335 ); n = md5_gg(n, m, l, o, p[g + 4 ], 20 , - 405537848 ); o = md5_gg(o, n, m, l, p[g + 9 ], 5 , 568446438 ); l = md5_gg(l, o, n, m, p[g + 14 ], 9 , - 1019803690 ); m = md5_gg(m, l, o, n, p[g + 3 ], 14 , - 187363961 ); n = md5_gg(n, m, l, o, p[g + 8 ], 20 , 1163531501 ); o = md5_gg(o, n, m, l, p[g + 13 ], 5 , - 1444681467 ); l = md5_gg(l, o, n, m, p[g + 2 ], 9 , - 51403784 ); m = md5_gg(m, l, o, n, p[g + 7 ], 14 , 1735328473 ); n = md5_gg(n, m, l, o, p[g + 12 ], 20 , - 1926607734 ); o = md5_hh(o, n, m, l, p[g + 5 ], 4 , - 378558 ); l = md5_hh(l, o, n, m, p[g + 8 ], 11 , - 2022574463 ); m = md5_hh(m, l, o, n, p[g + 11 ], 16 , 1839030562 ); n = md5_hh(n, m, l, o, p[g + 14 ], 23 , - 35309556 ); o = md5_hh(o, n, m, l, p[g + 1 ], 4 , - 1530992060 ); l = md5_hh(l, o, n, m, p[g + 4 ], 11 , 1272893353 ); m = md5_hh(m, l, o, n, p[g + 7 ], 16 , - 155497632 ); n = md5_hh(n, m, l, o, p[g + 10 ], 23 , - 1094730640 ); o = md5_hh(o, n, m, l, p[g + 13 ], 4 , 681279174 ); l = md5_hh(l, o, n, m, p[g + 0 ], 11 , - 358537222 ); m = md5_hh(m, l, o, n, p[g + 3 ], 16 , - 722521979 ); n = md5_hh(n, m, l, o, p[g + 6 ], 23 , 76029189 ); o = md5_hh(o, n, m, l, p[g + 9 ], 4 , - 640364487 ); l = md5_hh(l, o, n, m, p[g + 12 ], 11 , - 421815835 ); m = md5_hh(m, l, o, n, p[g + 15 ], 16 , 530742520 ); n = md5_hh(n, m, l, o, p[g + 2 ], 23 , - 995338651 ); o = md5_ii(o, n, m, l, p[g + 0 ], 6 , - 198630844 ); l = md5_ii(l, o, n, m, p[g + 7 ], 10 , 1126891415 ); m = md5_ii(m, l, o, n, p[g + 14 ], 15 , - 1416354905 ); n = md5_ii(n, m, l, o, p[g + 5 ], 21 , - 57434055 ); o = md5_ii(o, n, m, l, p[g + 12 ], 6 , 1700485571 ); l = md5_ii(l, o, n, m, p[g + 3 ], 10 , - 1894986606 ); m = md5_ii(m, l, o, n, p[g + 10 ], 15 , - 1051523 ); n = md5_ii(n, m, l, o, p[g + 1 ], 21 , - 2054922799 ); o = md5_ii(o, n, m, l, p[g + 8 ], 6 , 1873313359 ); l = md5_ii(l, o, n, m, p[g + 15 ], 10 , - 30611744 ); m = md5_ii(m, l, o, n, p[g + 6 ], 15 , - 1560198380 ); n = md5_ii(n, m, l, o, p[g + 13 ], 21 , 1309151649 ); o = md5_ii(o, n, m, l, p[g + 4 ], 6 , - 145523070 ); l = md5_ii(l, o, n, m, p[g + 11 ], 10 , - 1120210379 ); m = md5_ii(m, l, o, n, p[g + 2 ], 15 , 718787259 ); n = md5_ii(n, m, l, o, p[g + 9 ], 21 , - 343485551 ); o = safe_add(o, j); n = safe_add(n, h); m = safe_add(m, f); l = safe_add(l, e) } return Array(o, n, m, l) }; function md5_cmn(h, e, d, c, g, f) { return safe_add(bit_rol(safe_add(safe_add(e, h), safe_add(c, f)), g), d) }; function md5_ff(g, f, k, j, e, i, h) { return md5_cmn((f & k) | ((~f) & j), g, f, e, i, h) }; function md5_gg(g, f, k, j, e, i, h) { return md5_cmn((f & j) | (k & (~j)), g, f, e, i, h) }; function md5_hh(g, f, k, j, e, i, h) { return md5_cmn(f ^ k ^ j, g, f, e, i, h) }; function md5_ii(g, f, k, j, e, i, h) { return md5_cmn(k ^ (f | (~j)), g, f, e, i, h) }; function safe_add(a, d) { var c = (a & 65535 ) + (d & 65535 ); var b = (a >> 16 ) + (d >> 16 ) + (c >> 16 ); return (b << 16 ) | (c & 65535 ) }; function bit_rol(a, b) { return (a << b) | (a >>> ( 32 - b)) }; ///////////////////////////////////////////////////// // 避免全局命名空间冲突 md5_func.noConflict = function publicAPI$noConflict() { if (context) { // 将那个 name还原回原来的对象 context[name] = old_public_api; } // 返回自身,由调用的代码自己持有,保存,或赋值给某个变量 return md5_func; }; // 返回的对象,会被绑定到 MD5 之类的名字上,在外部就引用了此对象, // 因为闭包特性,可以利用到闭包内部方法和内部对象。 lib一般都是利用这种闭包特性,维护私有的属性、对象, // 对外只暴露一些方法(API),也就是 function, 外面只能调用这些API,方便内部进行逻辑控制,降低依赖. return md5_func; }) |
测试结果:
1
2
3
4
|
md5("1"); "c4ca4238a0b923820dcc509a6f75849b" md5(md5("1")) "28c8edde3d61a0411511d3b1866f0636" |
4. Oracle 数据库版MD5
注意: 为了与在其他环境下的MD5方法一致,需要转换为小写
需要创建一个存储函数:
1
2
3
4
5
6
7
8
|
CREATE OR REPLACE FUNCTION MD5(passwd IN VARCHAR2) RETURN VARCHAR2 IS retval varchar2(32); BEGIN retval := Lower (utl_raw.cast_to_raw( DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => passwd)) ); RETURN retval; END ; |
测试结果:
1
2
3
4
5
6
7
8
9
|
SQL> select MD5('1') as m1, MD5(md5('1')) as m2 from dual 2 ; M1 --------------------------------------- M2 --------------------------------------- c4ca4238a0b923820dcc509a6f75849b 28c8edde3d61a0411511d3b1866f0636 |