算法学习-MD5

算法学习-MD5

0x01 摘要

本文简要介绍MD5算法概念,并会提供一些小例子加深理解和印象。

0x02 MD5是什么

MD5是输入不定长度信息,输出固定长度128-bits。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。

MD5全名为Message-Digest Algorithm 5,它是一种信息摘要算法。

MD5主要通过采集文件的信息摘要来对数据进行加密,文件可以获得一个唯一的MD5值。我们可以通过文件的MD5值来校验文件正确性。

MD5是输入不定长度信息,输出固定长度128-bits的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。

MD5不可逆的原因是其是一种散列函数,使用的是hash算法,在计算过程中原文的部分信息是丢失了的。

一个MD5码理论上可能对应无数多个原文,因为MD5是有限多个,而原文可以是无数多个。比如主流使用的MD5将任意长度的字节串映射为一个128bit的大整数。也就是一共有2^128种可能,大概是3.4*10^38,这个数字是有限多个的,但可以被用来加密的原文则会有无穷多个。

不过需要注意的一点是,尽量这是一个理论上的有限对无限,不过问题是这个无限在现实生活中并不完全成立,因为一方面现实中原文的长度往往是有限的(以常用的密码为例,一般人都在20位以内),另一方面目前想要发现两段原文对应同一个MD5(专业的说这叫杂凑冲撞)值非常困难。因此从某种意义上来说,在一定范围内想构建MD5值与原文的一一对应关系是完全有可能的。所以对于MD5目前最有效的攻击方式就是彩虹表,具体可以通过谷歌了解。

MD5相当于超损压缩。

0x03 MD5算法详解

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

详细过程请参考:
MD5算法原理及其实现
MD5算法解析

0x04 例子

public class MD5Test
{
    /**
     * 模拟DigestUtils.md5Hex方法
     * @param content
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String getMD5(String content) throws NoSuchAlgorithmException {
        // 获得MD5摘要算法的 MessageDigest 对象
        MessageDigest mdInst = MessageDigest.getInstance("MD5");
        // 使用指定的字节更新摘要
        mdInst.update(content.getBytes());
        // 获得密文
        byte[] md = mdInst.digest();
        StringBuilder sb = new StringBuilder();
        // 把密文转换成十六进制的字符串形式
        for (byte b:md) {
            sb.append(Integer.toHexString(b&0xff));
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        try {
            System.out.println("DigestUtils.md5Hex = "+DigestUtils.md5Hex("chengc"));
            System.out.println("MD5Test.getMD5 = "+ MD5Test.getMD5("chengc"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}

0x05 MD5用途

  1. 防篡改
  • 发送方和接收方比对数据MD5
  • 文件下载时公开MD5,用户下载后核对MD5,可以防止不法分串改文件嵌入木马
  • SVN中用到了MD5来检测文件是否在CheckOut后被修改过
  1. 隐藏原文
    在数据库存储密码的时候进行MD5加密,用户登录时将输入的密码计算MD5进行匹配。就算数据库泄露,也无法知道用户的密码原文。
  2. 数字签名
    这需要一个第三方认证机构。例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构只需对此文件重新产生摘要信息,然后跟记录在册的摘要信息进行比对,相同的话,就证明是A写的了。这就是所谓的“数字签名”。

0x06 MD5不足

现在看来,MD5已经较老,散列长度通常为128位,随着计算机运算能力提高,找到“碰撞”是可能的。因此,在安全要求高的场合不使用MD5。

2004年,王小云教授证明MD5数字签名算法可以产生碰撞。2007年,Marc Stevens,Arjen K. Lenstra和Benne de Weger进一步指出通过伪造软件签名,可重复性攻击MD5算法。研究者使用前缀碰撞法(chosen-prefix collision),使程序前端包含恶意程序,利用后面的空间添上垃圾代码凑出同样的MD5 Hash值。2007年,荷兰埃因霍芬技术大学科学家成功把2个可执行文件进行了MD5碰撞,使得这两个运行结果不同的程序被计算出同一个MD5。2008年12月科研人员通过MD5碰撞成功生成了伪造的SSL证书,这使得在https协议中服务器可以伪造一些根CA的签名。

MD5被攻破后,在Crypto2008上, Rivest提出了MD6算法,该算法的Block size为512 bytes(MD5的Block Size是512 bits), Chaining value长度为1024 bits, 算法增加了并行 机制,适合于多核CPU。 在安全性上,Rivest宣称该算法能够抵抗截至目前已知的所有的 攻击(包括差分攻击)。

0xFF 参考文档

MD5值算法原理

你可能感兴趣的:(MD5)