Java、JavaScript、Oracle、MySQL中实现的MD5加密算法分享
MD5,全称为MessageDigestAlgorithm5(消息摘要算法第五版).详情请参考维基百科:MD5
MD5加密后是一个字节数组,但我们一般是取其十六进制的字符串表示法,当然,十六进制数字符串是区分大小写,在mysql数据库,Java,和JavaScript语言中,一般是使用小写的字符串来表示,而在Oracle数据库官方提供的包中,返回的是大写字符串,这算是一个坑,如果你想要执行多次md5,可能需要转换为小写.
相关的代码如下:
1.Java版MD5
MD5Util.java
packagecom.cncounter.util.common;
importjava.security.MessageDigest;
importjava.security.NoSuchAlgorithmException;
/**
*Java消息摘要算法MD5工具类,其实其他摘要算法的实现也类似
*/
publicclassMD5Util{
/**
*对文本执行md5摘要加密,此算法与mysql,JavaScript生成的md5摘要进行过一致性对比.
*@paramplainText
*@return返回值中的字母为小写
*/
publicstaticStringmd5(StringplainText){
if(null==plainText){
plainText="";
}
StringMD5Str="";
try{
//JDK6支持以下6种消息摘要算法,不区分大小写
//md5,sha(sha-1),md2,sha-256,sha-384,sha-512
MessageDigestmd=MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byteb[]=md.digest();
inti;
StringBuilderbuilder=newStringBuilder(32);
for(intoffset=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(NoSuchAlgorithmExceptione){
e.printStackTrace();
}
returnMD5Str;
}
//一个简版测试
publicstaticvoidmain(String[]args){
Stringm1=md5("1");
Stringm2=md5(m1);
/*输出为
*m1=c4ca4238a0b923820dcc509a6f75849b
*m2=28c8edde3d61a0411511d3b1866f0636
*/
System.out.println("m1="+m1);
System.out.println("m2="+m2);
}
}
2.MySQL版MD5
MySQL直接支持md5函数调用
selectmd5('1')asm1,md5(md5('1'))asm2;
执行结果为:
MariaDB[(none)]>selectmd5('1')asm1,md5(md5('1'))asm2;
+----------------------------------+----------------------------------+
|m1|m2|
+----------------------------------+----------------------------------+
|c4ca4238a0b923820dcc509a6f75849b|28c8edde3d61a0411511d3b1866f0636|
+----------------------------------+----------------------------------+
1rowinset(0.00sec)
3.JavaScript版MD5函数
md5.js代码如下:
/*!JavaScript的MD5实现*/
//括号表达式,(xxxxx)是用来将内部的语句、表达式的结果作为一个结果.
//常见的是将json字符串用eval解析时,需要eval("("+jsonstr+")");
//()内部定义了一个空间,里面定义的变量不会污染到全局空间,很适合做lib
//(functionUMD(对象/函数名name,上下文this,函数/对象的定义))返回一个匿名函数
//因为第一个括号内的结果是一个函数,而函数可以这样调用:(function(形参){})(实参);
//这种匿名函数被浏览器解析后会自动执行一次.
(functionUMD(name,context,definition){
if(typeofmodule!=="undefined"&&module.exports){
//如果module存在,并且module.exports存在,则将赋值结果赋给它
//可以不用管
module.exports=definition();
}elseif(typeofdefine==="function"&&define.amd){
//如果define这个函数存在,应该是另一个基础类库,则使用define
//可以不用管
define(definition);
}else{
//简单一点,可以看成:调用传入的definition函数,将返回的对象绑定到全局空间
//当然,根据传入的上下文不同,也可以绑定到其他对象下面,成为一个属性方法.
context[name]=definition(name,context);
}
}
)("md5",this,functionDEF(name,context){"usestrict";
//上面的usestrict表示严格语法模式,有错误就拒绝执行.
//而普通的JS,是解释执行,不执行的地方,有些错误也不影响其他代码的执行
//作为类库,使用严格模式是很有必要的.严格模式声明必须放到一个namespace空间的最起始处.
//
varold_public_api=(context||{})[name];
//最后要返回的对象/函数.
functionmd5_func(text){
returnhex_md5(text);
};
//下面一堆是具体的算法...可以先不用管
/////////////////////////////////////////////////////
//计算MD5
varhexcase=0;
functionhex_md5(a){
if(a=="")
returna;
returnrstr2hex(rstr_md5(str2rstr_utf8(a)))
};
functionhex_hmac_md5(a,b){
returnrstr2hex(rstr_hmac_md5(str2rstr_utf8(a),str2rstr_utf8(b)))
};
functionmd5_vm_test(){
returnhex_md5("abc").toLowerCase()=="900150983cd24fb0d6963f7d28e17f72"
};
functionrstr_md5(a){
returnbinl2rstr(binl_md5(rstr2binl(a),a.length*8))
};
functionrstr_hmac_md5(c,f){
vare=rstr2binl(c);
if(e.length>16){
e=binl_md5(e,c.length*8)
}
vara=Array(16),d=Array(16);
for(varb=0;b<16;b++){
a[b]=e[b]^909522486;
d[b]=e[b]^1549556828
}
varg=binl_md5(a.concat(rstr2binl(f)),512+f.length*8);
returnbinl2rstr(binl_md5(d.concat(g),512+128))
};
functionrstr2hex(c){
try{hexcase
}catch(g){
hexcase=0
}
varf=hexcase?"0123456789ABCDEF":"0123456789abcdef";
varb="";
vara;
for(vard=0;d<c.length;d++){
a=c.charCodeAt(d);
b+=f.charAt((a>>>4)&15)+f.charAt(a&15)
}
returnb
};
functionstr2rstr_utf8(c){
varb="";
vard=-1;
vara,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))
}
}
}
}
}
returnb
};
functionrstr2binl(b){
vara=Array(b.length>>2);
for(varc=0;c<a.length;c++){
a[c]=0
}
for(varc=0;c<b.length*8;c+=8){
a[c>>5]|=(b.charCodeAt(c/8)&255)<<(c%32)
}
returna
};
functionbinl2rstr(b){
vara="";
for(varc=0;c<b.length*32;c+=8){
a+=String.fromCharCode((b[c>>5]>>>(c%32))&255)
}
returna
};
functionbinl_md5(p,k){
p[k>>5]|=128<<((k)%32);
p[(((k+64)>>>9)<<4)+14]=k;
varo=1732584193;
varn=-271733879;
varm=-1732584194;
varl=271733878;
for(varg=0;g<p.length;g+=16){
varj=o;
varh=n;
varf=m;
vare=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)
}
returnArray(o,n,m,l)
};
functionmd5_cmn(h,e,d,c,g,f){
returnsafe_add(bit_rol(safe_add(safe_add(e,h),safe_add(c,f)),g),d)
};
functionmd5_ff(g,f,k,j,e,i,h){
returnmd5_cmn((f&k)|((~f)&j),g,f,e,i,h)
};
functionmd5_gg(g,f,k,j,e,i,h){
returnmd5_cmn((f&j)|(k&(~j)),g,f,e,i,h)
};
functionmd5_hh(g,f,k,j,e,i,h){
returnmd5_cmn(f^k^j,g,f,e,i,h)
};
functionmd5_ii(g,f,k,j,e,i,h){
returnmd5_cmn(k^(f|(~j)),g,f,e,i,h)
};
functionsafe_add(a,d){
varc=(a&65535)+(d&65535);
varb=(a>>16)+(d>>16)+(c>>16);
return(b<<16)|(c&65535)
};
functionbit_rol(a,b){
return(a<<b)|(a>>>(32-b))
};
/////////////////////////////////////////////////////
//避免全局命名空间冲突
md5_func.noConflict=functionpublicAPI$noConflict(){
if(context){
//将那个name还原回原来的对象
context[name]=old_public_api;
}
//返回自身,由调用的代码自己持有,保存,或赋值给某个变量
returnmd5_func;
};
//返回的对象,会被绑定到MD5之类的名字上,在外部就引用了此对象,
//因为闭包特性,可以利用到闭包内部方法和内部对象。lib一般都是利用这种闭包特性,维护私有的属性、对象,
//对外只暴露一些方法(API),也就是function,外面只能调用这些API,方便内部进行逻辑控制,降低依赖.
returnmd5_func;
})
测试结果:
md5("1");
"c4ca4238a0b923820dcc509a6f75849b"
md5(md5("1"))
"28c8edde3d61a0411511d3b1866f0636"
4.Oracle数据库版MD5
注意:为了与在其他环境下的MD5方法一致,需要转换为小写
需要创建一个存储函数:
CREATEORREPLACEFUNCTIONMD5(passwdINVARCHAR2)RETURNVARCHAR2IS retvalvarchar2(32); BEGIN retval:=Lower(utl_raw.cast_to_raw( DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING=>passwd)) ); RETURNretval; END;
测试结果:
SQL>selectMD5('1')asm1,MD5(md5('1'))asm2fromdual
2;
M1
---------------------------------------
M2
---------------------------------------
c4ca4238a0b923820dcc509a6f75849b
28c8edde3d61a0411511d3b1866f0636
PS:这里再为大家提供2款MD5加密工具,感兴趣的朋友可以参考一下:
MD5在线加密工具:
http://tools.jb51.net/password/CreateMD5Password
在线MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160加密工具:
http://tools.jb51.net/password/hash_md5_sha