美文网首页
1.2 MD系列算法

1.2 MD系列算法

作者: saillen | 来源:发表于2018-11-28 17:38 被阅读0次

    信息摘要算法 - MD系列算法

    MD系列算法是信息摘要三大算法中的一种,全称:Message Digest算法,按照规范版本分为MD2、MD4、MD5三种算法,目前最常用的是MD5版本算法。

    MD家族发展历史

    • 1989年,RSA发明人开发了MD2算法,其主要思路:
      • 1.对信息进行补位,信息的字节长度为16的倍数;
      • 2.以一个16位的校验和,追加到信息末尾;
      • 3.根据新的信息产生一个128位的散列值,得出MD2值;
    • 1990年,在MD2基础上发展出MD4算法:
      • 1.和MD2一样,仍然对信息进行补位,但是补位时要添加448个字节,变为512的倍数;
      • 2.仍对信息做散列,获取一个128位的散列值,得出MD4值;
      • MD4的算法影响很大,比如MD5、SHA-1、Ripe-MD系列都是从MD4基础上衍生出来的;
    • 1991年,MD4的创始人开发出MD5算法:
      • MD5算法是MD算法中最成熟的算法;
      • MD5算法最终也是产生一个128位的散列码;
      • MD5效率比MD4慢,但是安全性更高;
      • 随着目前计算资源的提升,MD5算法已经被攻破,有很多破译软件进行暴力破解,而且破解速度不断提升;
      • 但是MD5算法对于安全性要求不是很高的场景下,仍然广泛流行;

    MD系列算法产生128位的结果,也就是16字节;
    要注意:加解密算法针对的输入输出都是字节(本质是是二进制位),所以结果要转换为16进制/可打印字符串来存储/传输;

    应用场景

    信息摘要算法是不可逆的,所以信息摘要场景主要被用来验证信息的完整性,防止信息被篡改,主要场景如下:

    • 验签:对要发送的数据做MD5(一般加salt)MD5值和数据一同发送,接收方接受数据后做同样的MD5计算,比较MD5值是否一致;
    • 敏感信息存储:如用户密码存储上,弱加密场景下存储MD5值,此类场景建议针对每个用户生成一个随机的salt,然后将 MD5(passport + salt)结果值存储到DB中;
    • Spring Security中使用MD5算法进行的机密加解密;

    MD5算法在线破解:http://www.dmd5.com

    Java中算法实现

    算法供应商选择

    选择算法供应商很大程度决定了API接口的使用方式,Java的加解密供应商主要有三个:Sun,Bouncy Castle和Commons Codec:

    • Sun:提供MD2MD5算法支持,接口比较简单,唯一麻烦的地方是没有提供byte[]转16进制字符串的方法;
    • Bouncy Castle:添加了对MD4算法的支持,使用JAVA SPI方式接入到系统,或者调用算法供应商的API,提供了十六进制转换方法;
    • Commons Codec:对Sun的Api的封装,支持多种形式参数,支持16进制转换、字符串转换的友好API,一般优先推荐;

    MessageDigest类

    在Java中,MD系列算法的API封装在MessageDigest类中,该类采用策略模式设计,其算法的具体实现通过JAVA SPI机制注册进去,内部做透明的选择。Java本身自JDK 1.6开始提供MD2MD5算法的支持,使用起来很简单。唯一有点麻烦的地方是:JDK的 API 返回的数据都是 byte[],想要转换为字符串,还需要调用一个转换为16进制(或转换为字符串,eg:Base64)的方法,这个方法可以使用HexBin方法或者其他工具,也不复杂。

    MD4算法 : JDK没有提供MD4算法支持,需要寻找第三方支持。

    在Java中安装第三方算法包,可以通过Java的SPI机制,使用Secuirty.addProvider()方法加载第三方组件。

    下面是Java的MD5使用方式:

    public class MD5Test {
    
        public static void main(String[] args) throws NoSuchAlgorithmException {
    
            String input = "Test";
            byte[] data = input.getBytes();
            MessageDigest md = MessageDigest.getInstance("md5");
            byte[] rsBytes = md.digest(data);
            log(new String(HexBin.encode(rsBytes)));
        }
    
        private static void log(String msg) {
            System.out.println(msg);
        }
    
    }
    

    DigestInputStream类

    有时候我们需要需要以流的形式对数据进行MD计算,比如对大文件进行MD5计算,可以使用配套类DigestInputStream类,示例代码如下:

    public class MDInputStreamTest {
    
        public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
    
            // 待做消息摘要操作的原始信息,实际上我们这里应该是一个文件或者网络输入
            byte[] input = "md5".getBytes();
            // 初始化MesssageDigest对象,将使用MD5算法
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 构建DigestInputStream对象,这里用ByteArrayInputStream,实际上应该换做FileInputStream等其他流
            DigestInputStream in = new DigestInputStream(new ByteArrayInputStream(input), md);
            try {// 每次读取一段信息,计算MD5值,这里可以分次读取然后记录每次的MD5
                in.read(input, 0, input.length);
                // 获取摘要信息
                byte[] rs = in.getMessageDigest().digest();
                log(new String(HexBin.encode(rs)));
            } finally {
                in.close();
            }
    
        }
    
        private static void log(String msg) {
            System.out.println(msg);
        }
    }
    

    相关文章

      网友评论

          本文标题:1.2 MD系列算法

          本文链接:https://www.haomeiwen.com/subject/heszqqtx.html