zoukankan      html  css  js  c++  java
  • 哈希算法

    哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。

    哈希算法最重要的特点就是:

    • 相同的输入一定得到相同的输出;
    • 不同的输入大概率得到不同的输出。

    哈希算法的目的就是为了验证原始数据是否被篡改。

    Java字符串的hashCode()就是一个哈希算法,它的输入是任意字符串,输出是固定的4字节int整数:

    "hello".hashCode(); // 0x5e918d2
    "hello, java".hashCode(); // 0x7a9d88e8
    "hello, bob".hashCode(); // 0xa0dbae2f

    哈希碰撞

    哈希碰撞是指,两个不同的输入得到了相同的输出:

    "AaAaAa".hashCode(); // 0x7460e8c0
    "BBAaBB".hashCode(); // 0x7460e8c0

    常用的哈希算法有:

    算法输出长度(位)输出长度(字节)
    MD5 128 bits 16 bytes
    SHA-1 160 bits 20 bytes
    RipeMD-160 160 bits 20 bytes
    SHA-256 256 bits 32 bytes
    SHA-512 512 bits 64 bytes

     

     

     

     

     

     

     

    根据碰撞概率,哈希算法的输出长度越长,就越难产生碰撞,也就越安全。

    Java标准库提供了常用的哈希算法,并且有一套统一的接口。

    MD5

    我们以MD5算法为例,看看如何对输入计算哈希:

    复制代码
    import java.math.BigInteger;
    import java.security.MessageDigest;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            // 创建一个MessageDigest实例:
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 反复调用update输入数据:
            md.update("Hello".getBytes("UTF-8"));
            md.update("World".getBytes("UTF-8"));
            byte[] result = md.digest(); // 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6
            System.out.println(new BigInteger(1, result).toString(16));
        }
    }
    复制代码

    使用MessageDigest时,我们首先根据哈希算法获取一个MessageDigest实例,然后,反复调用update(byte[])输入数据。当输入结束后,调用digest()方法获得byte[]数组表示的摘要,最后,把它转换为十六进制的字符串。

     

    哈希算法的用途

    因为相同的输入永远会得到相同的输出,因此,如果输入被修改了,得到的输出就会不同。

    例子:

    1、对比文件与原始文件一致性

    2、存储用户口令(密码)

    想要拿到用户的原始口令,必须用暴力穷举的方法,一个口令一个口令地试,直到某个口令计算的MD5恰好等于指定值。

    还要注意防止彩虹表(预先计算好的常用口令和它们的MD5的对照表)攻击。

    采取措施来抵御彩虹表攻击,方法是对每个口令额外添加随机数,这个方法称之为加盐(salt):

    digest = md5(salt+inputPassword)

    加盐的目的在于使黑客的彩虹表失效,即使用户使用常用口令,也无法从MD5反推原始口令。

    SHA-1

    SHA-1也是一种哈希算法,它的输出是160 bits,即20字节。SHA-1是由美国国家安全局开发的,SHA算法实际上是一个系列,包括SHA-0(已废弃)、SHA-1、SHA-256、SHA-512等。

    在Java中使用SHA-1,和MD5完全一样,只需要把算法名称改为"SHA-1"

    复制代码
    import java.math.BigInteger;
    import java.security.MessageDigest;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            // 创建一个MessageDigest实例:
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            // 反复调用update输入数据:
            md.update("Hello".getBytes("UTF-8"));
            md.update("World".getBytes("UTF-8"));
            byte[] result = md.digest(); // 20 bytes: db8ac1c259eb89d4a131b253bacfca5f319d54f2
            System.out.println(new BigInteger(1, result).toString(16));
        }
    }
    复制代码

    类似的,计算SHA-256,我们需要传入名称"SHA-256",计算SHA-512,我们需要传入名称"SHA-512"。Java标准库支持的所有哈希算法可以在这里查到。

  • 相关阅读:
    Quartz2.0以上版本的单机和集群
    Mysql的Haproxy反向代理和负载均衡
    spring AOP原理解析
    Restful接口调用方法超详细总结
    mysql数据库主从同步
    数据备份的OSS接口
    读取properties配置文件的方法
    算法学习——堆排序(二叉树排序)
    回溯算法的实现
    冒泡排序
  • 原文地址:https://www.cnblogs.com/hsiaochinchin/p/14013268.html
Copyright © 2011-2022 走看看