MD5算法原理及其实现

1、  什么是MD5?
MD5(单项散列算法)
全名MessageDigest Algorithm 5 ,中文名为消息摘要算法第五版,通过特定的hash散列算法,讲文本信息转换成简短的信息摘要(压缩+加密+hash算法),是绝对不可逆的。

2、  MD5的安全性
[MD5的两个基本属性]
1)两个不同的报文难以生成相同的摘要
2)难以对制定的摘要生成一个报文,而可以由改报文反推算出改指定的摘要
简而言之:从不同报文生成不同摘要,不能从摘要推算出报文(不可逆)
所以,如果是安全级别一般的系统要求,可以用MD5进行加密,而且MD5的使用不需要支付任何版权费用,但是,实际上如果把用户的密码MD5处理后再存储到数据库,其实是很不安全的。因为用户的密码是比较短的,而且很多用户的密码都使用生日,手机号码,身份证号码,电话号码等等。或者使用常用的一些吉利的数字,或者某个英文单词。如果我把常用的密码先MD5处理,把数据存储起来,然后再跟你的MD5结果匹配,这时我就有可能得到明文。

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进制的字符串数组存入,然后再数据库