zoukankan      html  css  js  c++  java
  • 【Java】聊聊常用的摘要算法,比如MD5

    摘要算法的特性

    • 摘要算法的目的的将信息进行简单地摘要,将任意长的信息摘要成固定长的信息。比如MD5,将任意长的信息摘要成128位的摘要。
    • 不可逆的,将报文摘要成一段信息后,无法通过摘要信息还原会报文。
    • 冲突性。一份报文跟其他报文的摘要信息有可能是一致的,即冲突的。一般来说,摘要算法会设计得冲突性尽量小。

    常用的摘要算法有:MD5、SHA(Secure Hash Algorithm)等。下面介绍MD5。

    MD5

    MD,全文是Message Digest,即信息摘要的意思,是常用的信息摘要算法。

    它是一种不可逆的算法,也就是说,假如将一个信息MD5摘要成一串代码,将不能通过这串代码还原回原来的信息。

    使用的场景

    出于这种特性,MD5常用来校验密码是否正确、校验下载文件是否完整无损。

    -> 校验密码是否正确:将用户注册的密码MD5摘要后储存起来,待用户登录时将用户录入的密码MD5摘要,对比两次摘要后的信息是否相等,相等即密码正确。(这里如果加盐会更好,见后面章节)

    -> 校验下载文件是否完整无损:我们常下载开源文件资源包时,可以看到网站上提供的该资源包的MD5(比如下载POI,如图一),下载文件完毕后,可通过自己的程序或直接去一些网站上计算其MD5码,如果与官网上提供的一致,则表示文件完整无损。(图二第3行日志可见,以下程序计算的MD5码与图一的官网截图一致)

    直接进行MD5是否足够,为什么要加盐

    如图一可见,123456的MD5码为e10adc3949ba59abbe56e057f20f883e。一般来说,MD5摘要的结果是128位的摘要信息,然后每4位用一个16进制字符表示,所有,MD5摘要的结果一般显示为32位的16进制。

    如果你的系统用MD5摘要,并且无加盐,还经常使用123456为测试密码,对这一串MD5码一定很熟悉。这一些MD5码就静静地躺在DB中待校验。

    如果数据库被暴露(比如拖库),坏人得到了这些MD5码,就可以通过常用密码与其MD5码的映射关系,轻而易举地翻译出大多数密码。

    所以,一般来说,我们需要对原始密码进行加盐,所谓加盐,就是按照一定规则扰乱原有字符串,然后再进行MD5摘要。这个规则,自己定义,并且一定保密。

    调用Spring工具类获取MD5码

    目前Spring应用广泛,我们就直接使用Spring的api获取MD5码了。

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>3.2.15.RELEASE</version>
    </dependency>
    View Code
    package com.nicchagil.md5study;
    
    import org.springframework.util.DigestUtils;
    
    public class MD5UtilBySpring {
        
        /**
         * 使用MD5作信息摘要,并以十六进制表示
         */
        public static String md5(byte[] bytes) {
            return DigestUtils.md5DigestAsHex(bytes);
        }
    
        /**
         * 使用MD5作信息摘要,并以十六进制表示
         */
        public static String md5(String s) {
            if (s == null || s.length() == 0) {
                return null;
            }
            return MD5UtilBySpring.md5(s.getBytes());
        }
        
    }
    View Code
    package com.nicchagil.md5study;
    
    public class Salter {
        
        public static final String PREFIX = "HOW";
        public static final String FILLING = "ARE";
        public static final Integer FILLING_INDEX = 5;
        public static final String POSTFIX = "YOU!";
        
        public static String salt(String source) {
            if (source == null || source.length() == 0) {
                return null;
            }
            
            StringBuffer sb = new StringBuffer(source);
            if (sb.length() > FILLING_INDEX) {
                sb.insert(FILLING_INDEX, FILLING);
            }
            
            return sb.insert(0, PREFIX).append(POSTFIX).toString();
        }
    
    }
    View Code
    package com.nicchagil.md5study;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    
    import org.junit.Test;
    
    public class HowToUse {
        
        @Test
        public void test() throws Exception {
            String source = "123456";
            String md5Hex = MD5UtilBySpring.md5(source);
            System.out.println(source + "'s hex md5 -> " + md5Hex);
        }
        
        @Test
        public void test2() throws Exception {
            File file = new File("d:/poi-bin-3.13-20150929.tar.gz");
            
            FileInputStream fis = null;
            ByteArrayOutputStream baos = null;
            try {
                fis = new FileInputStream(file);
                baos = new ByteArrayOutputStream();
                
                byte[] bytes = new byte[1024];
                int size = 0;
                while ((size = fis.read(bytes)) != -1) {
                    if (size == 1024) {
                        baos.write(bytes);
                    } else {
                        baos.write(bytes, 0, size);
                    }
                }
                
                byte[] resultBytes = baos.toByteArray();
                System.out.println("size -> " + resultBytes.length);
                String md5Hex = MD5UtilBySpring.md5(resultBytes);
                System.out.println("Hex md5 -> " + md5Hex);
            } finally {
                if (fis != null) {
                    fis.close();
                }
                if (baos != null) {
                    baos.close();
                }
            }
        }
        
        @Test
        public void test3() throws Exception {
            String source = "123456";
            String saltSource = Salter.salt(source);
            String md5 = MD5UtilBySpring.md5(saltSource);
            System.out.println(source + " salt -> " + saltSource + " MD5 -> " + md5);
            
            source = "12345";
            saltSource = Salter.salt(source);
            md5 = MD5UtilBySpring.md5(saltSource);
            System.out.println(source + " salt -> " + saltSource + " MD5 -> " + md5);
            
            source = "1234";
            saltSource = Salter.salt(source);
            md5 = MD5UtilBySpring.md5(saltSource);
            System.out.println(source + " salt -> " + saltSource + " MD5 -> " + md5);
        }
        
    }
    View Code

    图一

    图二

  • 相关阅读:
    LeetCode 453 Minimum Moves to Equal Array Elements
    LeetCode 112 Path Sum
    LeetCode 437 Path Sum III
    LeetCode 263 Ugly Number
    Solutions and Summay for Linked List Naive and Easy Questions
    AWS–Sysops notes
    Linked List
    All About Linked List
    datatable fix error–Invalid JSON response
    [转]反编译c#的相关问题
  • 原文地址:https://www.cnblogs.com/nick-huang/p/5067764.html
Copyright © 2011-2022 走看看