• java单向加密算法小结(2)--MD5哈希算法


      上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符串(消息摘要).

    简单了解

      MD5(Message Digest Algorithm 5),翻译过来是消息摘要算法第五版,按照惯例,我们推理可能也有MD2,MD3这样名字的历史版本..

      即使完全不了解这个算法的原理,我们也可以从命名中看出一些眉道,所谓摘要,就是一个简短的概括,像我写过的毕业论文,上来第一部分就是摘要,它对后面长篇大论的文章做了一个简短有力的概括,其实MD5的作用也有点这样的味道,我们来看一段关于描述MD5算法作用的文字:

      MD5的作用是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数),它主要用于确保数据传输的完整性和一致性.

      假设A要给远方的B发送一个文本文件,有100万字,当B收到文件的时候,该怎么知道这个文件在传过来的途中有没有被篡改呢,要是有人中途截断并篡改了文件内容那就不太妙了,这时候MD5就派上用场了,不管多大的文件,通过MD5加密之后都会得到一个定长的字符串,一般是32位,这时候A先对文件用MD5加密一下,得到的一串密文顺便也传给B,当B收到后文件,同样对文件用MD5加密一下,看看得到的密文是否和A传过来的一致,如果一致,说明这个文件是安全的.这样就确保了数据传输的完整性.

      事实上,我们从网络上下载文件的时候,有时候下载的文件后面都有一段MD5的密文,比如 MD5(e8027a87676ea48b3a3c9b0a4d8d87a0),作用和上面我举得例子类似(我觉得是这样....).

      MD5是一种公开的不可逆的算法,意味着是没有办法直接破解密文得到源数据信息的,md5可以对一个对一个任意大小的文件进行哈希运算,得到一个唯一的32位字符串.

      简单了解了MD5的功能,就可以直接看代码了.

    java代码实现MD5

    package com.wang.encryption;
    import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
    import java.security.MessageDigest;
    /**
     * @author yogo.wang
     * @date 2016/11/04-下午1:02.
     */
    public class MD5Test {
        public static String md5Encode(String msg) throws Exception{
    
            byte[] msgBytes = msg.getBytes("utf-8");
            /**
             * 声明使用Md5算法,获得MessaDigest对象
             */
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            /**
             * 使用指定的字节更新摘要
             */
            md5.update(msgBytes);
            /**
             * 完成哈希计算,获得密文
             */
            byte[] digest = md5.digest();
            /**
             * 以上两行代码等同于 byte[] digest = md5.digest(msgBytes);
             */
            return bytesToHexString(digest);
        }
        /**
         * 将byte数组转化为16进制字符串形式
         * @param bys
         * @return
         */
        public static String byteArr2hexString(byte[] bys){
            StringBuffer hexVal=new StringBuffer();
            int val=0;
            for (int i = 0; i < bys.length; i++) {
                //将byte转化为int  如果byte是一个负数就必须要和16进制的0xff做一次与运算
                val=((int)bys[i]) & 0xff;
                if(val<16){
                    hexVal.append("0");
                }
                hexVal.append(Integer.toHexString(val));
            }
    
            return hexVal.toString();
    
        }
    
        public static void main(String[] args) throws Exception {
            String msg="helloworld";
            String result=md5Encode(msg);
            String result1=md5Encode(msg);
            System.out.println(result);
            System.out.println(result1);
        }
    
    }

    运行代码,得到的输出结果如下:

    fc5e038d38a57032085441e7fe7010b0
    fc5e038d38a57032085441e7fe7010b0

      可见,对同一个字段进行加密,得到的密文总是一致的.接下来看一下MD5实现的原理和应用.

    MD5实现原理及应用  

      我看了一些网上的朋友自己实现的md5哈希的代码,只能说半知半解,这里贴一下,网络上的一些实现的步骤介绍(随便看看就好).

    MD5算法的原理主要分为以下几个步骤,

      1)填充:首先将输入信息的长度(bit)进行填充,使得对512求余的结果等于448。填充的方法是填充一个1和n个0。

      2)记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。

      3)装入标准的幻数:标准的幻数是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。

      4)四轮循环运算:循环的次数是分组的个数(N+1)。

      这里主要介绍一下,java中MessageDigest这个类,查看jdk的开发文档,可以看到该类位于java.security包下,文档对MessageDigest的描述如下:

    public abstract class MessageDigest

        extends MessageDigestSpi

          此 MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。

          MessageDigest 对象开始被初始化。该对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用 digest 方法之一完成哈希计算。

          对于给定数量的更新数据,digest 方法只能被调用一次。digest 被调用后,MessageDigest 对象被重新设置成其初始状态。

          实现可随意选择是否实现 Cloneable 接口。客户端应用程可以通过尝试复制和捕获 CloneNotSupportedException 测试可复制性:

     MessageDigest md = MessageDigest.getInstance("SHA");

     try {

         md.update(toChapter1);

         MessageDigest tc1 = md.clone();

         byte[] toChapter1Digest = tc1.digest();

         md.update(toChapter2);

         ...etc.

     } catch (CloneNotSupportedException cnse) {

         throw new DigestException("couldn't make digest of partial content");

     }

    注意,如果给定的实现是不可复制的,而事先已知摘要的数目,则仍然能够通过实例化几个实例计算中间摘要。

      主要方法的作用,在上面代码的注释中已经给出,这里就不在介绍了.

      MD5的应用领域主要可以分为以下几类:

    1、防止被篡改(文件完整性验证),比如我提供文件下载,为了防止不法分子在安装程序中添加木马,我可以在网站上公布由安装文件得到的MD5输出结果。

    2、防止直接看到明文(口令加密),现在很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子得到数据库的用户密码的MD5值,也无法知道用户的密码。

    3、防止抵赖(数字签名),例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。这样可以防止出现以后A不承认此事而带来的麻烦。

      虽然MD5是一种不可逆的算法,但并不意味着不可破解,大多数用户设置密码时都会使用比较有特殊意义的字段,比如生日,名字简拼,等,如果我把你的相关的信息,猜测出你可能会使用的密码,然后把他们都用MD5加密一遍,就得到很多个密文,再拿到你的密码的密文和我的密文库里一一对比,如果密文能匹配,那么你的密码本身也就不攻自破了.同样的道理,现在有很多网站有提供了一些在线的MD5值查询功能,输入MD5密码值后,如果在数据库中存在,那么可以很快获取其密码值,道理也是一样的,比如上面代码中我是对"helloworld"这个字符串进行MD5加密,理论上你只知道密文是不可能破解我的原始数据的,但事实上真的是这样吗? 来看一个网站http://pmd5.com/

              

      我输入上面代码生成的密文之后,网站一下子就破解了,原理也就很简单了.

      关于MD5更详细的文字资料,可以移步百度百科,介绍的挺详细的,值得一看. 

    相关链接

      "java加密算法小结--Base64算法"

  • 相关阅读:
    java嵌套接口
    关于继承与多态
    重看Maven技术
    npm常用命令及参数总结
    vue.js和node.js的关系
    Invalid [xxx] in servlet mapping 、 <url-pattern>的匹配规则
    Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'name' in 'field list'
    关于中文词云生成报错
    easygui安装过程
    将写好的python软件打包成程序
  • 原文地址:https://www.cnblogs.com/fingerboy/p/6032087.html
Copyright © 2020-2023  润新知