MD5算法原理及其实现
1、 什么是MD5?
MD5(单项散列算法)全名MessageDigest Algorithm 5 ,中文名为消息摘要算法第五版,通过特定的hash散列算法,讲文本信息转换成简短的信息摘要(压缩+加密+hash算法),是绝对不可逆的。
2、 MD5的安全性
[MD5的两个基本属性]
1)两个不同的报文难以生成相同的摘要
2)难以对制定的摘要生成一个报文,而可以由改报文反推算出改指定的摘要
简而言之:从不同报文生成不同摘要,不能从摘要推算出报文(不可逆)
所以,如果是安全级别一般的系统要求,可以用MD5进行加密,而且MD5的使用不需要支付任何版权费用,但是,实际上如果把用户的密码MD5处理后再存储到数据库,其实是很不安全的。因为用户的密码是比较短的,而且很多用户的密码都使用生日,手机号码,身份证号码,电话号码等等。或者使用常用的一些吉利的数字,或者某个英文单词。如果我把常用的密码先MD5处理,把数据存储起来,然后再跟你的MD5结果匹配,这时我就有可能得到明文。比如某个MD5破解网站http://www.cmd5.com/default.aspx 就可以根据密文推出相应的原文.
3、 MD5的代码实现
1)简单实现
/**利用MD5进行加密
* @param str 待加密的字符串
* @return 加密后的字符串
* @throws NoSuchAlgorithmException 没有这种产生消息摘要的算法
* @throws UnsupportedEncodingException
*/
public String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException{
//确定计算方法
MessageDigest md5=MessageDigest.getInstance("MD5");
BASE64Encoder base64en = new BASE64Encoder();
//加密后的字符串
String newstr=base64en.encode(md5.digest(str.getBytes("utf-8")));
return newstr;
}
2)进阶实现
public String MD5(String s){
try{
//将字符串转为byte数组
byte[]b=s.getBytes();
//获取MessageDigest对象,申明使用MD5算法进行加密(还有SHA算法)
MessageDigestmd=MessageDigest.getInstance("MD5");
//输入报文
md.update(b);
//生成摘要
byte[] bytes=md.digest();
//返回16进制字符串,用于储存在数据库中
returnbyte2str(bytes);
}catch(Exception exception){
exception.printStackTrace();
return null;
}
}
/* 把字节数组转为16进制字符串 */
public String byte2str(byte[] b){
char[]hexNumsStr={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
intlen=b.length;
char[] result=newchar[len*2];
int k=0;
for(int i=0;i<len;i++){
//b[i]>>>4 不考虑符号(正负数)向右移4位
//b[i]&0xf 与0xf进行按位与
//0xf二进制为:1111
result[k++]=hexNumsStr[b[i]>>>4&0xf];
result[k++]=hexNumsStr[b[i]&0xf];
}
return new String(result);
}
步骤及知识点整理
1)MessageDigest对象提供了信息摘要算法,如MD5算法或者SHA算法.在初始化MessageDigest的使用,要申明使用什么算法,如:MessageDigest md5=MessageDigest.getInstance(“MD5”);
2)有了MessageDigest之后,通过update(byte[]input)方法,提供报文,因为该方法不支持String类型,但是支持byte[]类型(字节数组),所以把传入的String类型的参数转为byte[]类型(一般传入的为 密码 这个字段),如:byte[] b=s.getBytes();
3)传入报文之后,用digest()方法生成摘要,digest()返回的是byte[]类型。
PS: 1>digest()方法执行之前,update()可以执行多次,执行多次的效果等于把这多次的str.getBytes[]的str拼接成一个String类型的字符串,经过getBytes()之后使用update()
例如
2>digest()方法执行完之后,MessageDigest就被重新设定为初始状态,需要重新提供报文.
MessageDigest md5 =MessageDigest.getInstance("MD5");//申明使用MD5算法
md5.update("a".getBytes());//
System.out.println("md5(a)="+byte2str(md5.digest()));
md5.update("bc".getBytes());
System.out.println("md5(bc)="+byte2str(md5.digest()));
md5.update("a".getBytes());
md5.update("bc".getBytes());
System.out.println("md5(abc)="+byte2str(md5.digest()));
4)有了digest()方法的byte[]类型的结果之后,一般都要把字符数组转为16进制的字符串数组存入,然后再数据库
更多内容请关注微信公众号“外里科技”