为什么MD5会被弃用?

一、MD5的前世今生

实际上,MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。也就是说,在他之前,还有 MD4 算法,而 MD4 是麻省理工学院教授Ronald Rivest于1990年设计的一种信息摘要算法。它是一种用来测试信息完整性的密码散列函数的实行。其摘要长度为128位,一般128位长的MD4散列被表示为32位的十六进制数字。

当时设计出来 MD4之后,就出现了两个不服气的人,非要证明这个玩意是不对的,关键是,这两个人还真的成功了,一个是Den boer 另外一个Bosselaers 这两个大哥,伙同一拨人,还真的找到了 MD4 的漏洞,找到MD4完整版本中的冲突(这个冲突实际上是一种漏洞,它将导致对不同的内容进行加密却可能得到相同的加密后结果)。毫无疑问,MD4就此被淘汰掉了。

而李维斯特肯定也不服气呀,于是在1992年的时候,李维斯特向互联网工程任务组(IETF)提交了一份重要文件,描述了 MD5 这种算法的原理。由于这种算法的公开性和安全性,在90年代被广泛使用在各种程序语言中,用以确保资料传递无误等。而之后,这个 MD5 可谓是影响深远,当时据说 Den boer 另外一个Bosselaers 这两个大哥 又开始挑刺,发现了MD5算法中的假冲突(pseudo-collisions),但除此之外就没有其他被发现的加密后结果了。所以也就没有后续内容了,于是在之后的时间里,MD5 就开始被大众广泛认知了,一直持续了四五年的时间。

在 1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如 SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。所以,在之后,MD5 陆陆续续的退出历史舞台,虽然退出了历史舞台,但是,影响还是在的,至今也有 MD5 加密方式的存在,不信大家可以巴拉一下自己的项目,看看有没有关于这个 MD5 的代码存在呢?

二、什么是MD5?

MD5码是以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

1、MD5流程图

大家看一下百度百科上面给出的流程图:

为什么MD5会被弃用?插图

其实总的来说,MD5 就是对一个不变的数据进行加密,而加密之后的字符串也是不变的,只要对元数据哪怕做一个简单的字符修改,那么通过 MD5 加密之后的密码数据,都会对应的做出改变,就相当于是一个人的 “指纹”。

2、MD5实现代码

Java实现 MD5 那真的是太简单了,实例代码如下:

public class MD5 {
    /**
    * @param text明文
    * @param key密钥
    * @return 密文
    */    // 带秘钥加密
    public static String md5(String text, String key) throws Exception {
        // 加密后的字符串
        String md5str = DigestUtils.md5Hex(text + key);
        System.out.println("MD5加密后的字符串为:" + md5str);
        return md5str;
    }

    // 不带秘钥加密
    public static String md52(String text) throws Exception {
        // 加密后的字符串
        String md5str = DigestUtils.md5Hex(text);
        System.out.println("MD52加密后的字符串为:" + md5str + "t长度:" + md5str.length());
        return md5str;
    }

    /**
    * MD5验证方法
    * 
    * @param text明文
    * @param key密钥
    * @param md5密文
    */    // 根据传入的密钥进行验证
    public static boolean verify(String text, String key, String md5) throws Exception {
        String md5str = md5(text, key);
        if (md5str.equalsIgnoreCase(md5)) {
            System.out.println("MD5验证通过");
            return true;
        }
        return false;
    }
}

三、MD5为什么被弃用了

既然我们上面都说了 MD5 算是比较强大的了,为什么现在 MD5 会被大家弃用了呢?

一条信息的安全性取决于任何信息摘要函数的目标是产生看起来是随机的摘要。要被认为是加密安全的,哈希函数应该满足两个要求:

  • 1. 攻击者不可能生成一个与特定的哈希值相匹配的信息。
  • 2. 攻击者不可能创建两个产生相同哈希值的消息。

根据IETF,MD5哈希值不再被认为是加密安全的方法,不应该被用于加密认证。

2011年,IETF发布了RFC6151——MD5消息摘要和HMAC-MD5算法的最新安全考虑,其中引用了一些最近针对MD5哈希值的攻击。它提到了一个在标准笔记本上一分钟或更短的时间内产生哈希碰撞的攻击,以及另一个在2.6千兆赫的奔腾4系统上仅用10秒就能产生碰撞的攻击。因此,IETF建议,新的协议设计根本不应该使用MD5,最近针对该算法的研究抨击到:在需要抗碰撞的应用中取消MD5的使用,如数字签名。

这样,就导致了当信息哈希代码无意中被重复时,它有可能造成信息碰撞。MD5的哈希代码串也被限制在128位。这使得它们比后来的其他哈希码算法更容易被破解。所以,当人们发现这个算法不太合适的时候,就开始弃用了这个算法,慢慢的就衍生出了其他的相对于MD5 更加安全的算法了。而当时验证最早的却不是2011年,而是2004年通过我国的王晓云教授等学者的工作,md5已经被证明可以进行碰撞攻击。也就是说,攻击者可以产生两个应用程序,内容不一样,但是哈希值完全一样。这就导致了在大家的眼中,MD5 已经算是不够安全的数据了,所以,MD5 就逐渐的被大家所淘汰,使用的情况也就不是那么多了。

四、为什么说MD5是不可逆的?

我们就简单的用A乘以B,一定会得到一个固定的结果C。比如说A(188923010)和B(172389945)。但是如果只是给你一个结果C,你知道C是由那几个因式计算出来的结果吗?我相信你也猜不出来。所以, 只能从一个方向推导结果,不能从结果反过来逆向推导,就叫单向函数不可逆, 即Md5算法不可逆。更不用说,通过MD5的复杂算法来进行计算以后得到的固定长度值了。但是也有很多人说的比较官方,就像百度上的一些大哥生活的:

MD5不可逆的原因是由于它是一种散列函数(也叫哈希函数,哈希函数又称散列函数,杂凑函数,它是一个单向密码体制,即从明文到密文的不可逆映射,只有加密过程没有解密过程,哈希函数可以将任意长度的输入经过变化后得到固定长度的输出,这个固定长度的输出称为原消息的散列或消息映射。理想的哈希函数可以针对不同的输入得到不同的输出,如果存在两个不同的消息得到了相同的哈希值,那我们称这是一个碰撞),使用的是hash算法,在计算过程中原文的部分信息是丢失了的。一个MD5理论上是可以对应多个原文的,因为MD5是有限多个而原文是无限多个的。

发表评论