哈希算法

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

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

    哈希碰撞

    哈希碰撞是指,两个不同的输入得到了相同的输出: ``` “AaAaAa”.hashCode(); // 0x7460e8c0 “BBAaBB”.hashCode(); // 0x7460e8c0
  1. hash算法碰撞不可避免,碰撞率的高低关系到哈希算法的安全性。<br />常用的哈希算法有:
  2. |
  3. 算法
  4. | 输出长度(位)
  5. | 输出长度(字节)
  6. |
  7. | --- | --- | --- |
  8. |
  9. MD5
  10. | 128 bits
  11. | 16 bytes
  12. |
  13. |
  14. SHA-1
  15. | 160 bits
  16. | 20 bytes
  17. |
  18. |
  19. RipeMD-160
  20. | 160 bits
  21. | 20 bytes
  22. |
  23. |
  24. SHA-256
  25. | 256 bits
  26. | 32 bytes
  27. |
  28. |
  29. SHA-512
  30. | 512 bits
  31. | 64 bytes
  32. |
  33. ### 在Java中使用哈希算法

// 创建一个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));

  1. 使用`MessageDigest`时,我们首先根据哈希算法获取一个`MessageDigest`实例,然后,反复调用`update(byte[])`输入数据。当输入结束后,调用`digest()`方法获得byte[]数组表示的摘要,最后,把它转换为十六进制的字符串。
  2. ### 加盐
  3. 在使用Hash算法时,要注意防止彩虹表攻击。彩虹表即当用户输入的字符是一些常见的口令(例如:123456hello123),这些都是预先计算好的口令,并且已经有口令和它对应的转换结果的一张表即彩虹表。<br />如果用户使用了常用口令,黑客从MD5一下就能反查到原始口令。<br />为防止这种情况,我们可以对每一个口令添加额外的随机数,这个方法称之为加盐<br />`digest = md5(salt+inputPassword)`
  4. ## 第三方哈希算法和加密算法库
  5. 我们知道,Java标准库提供了一系列常用的哈希算法。<br />但如果我们要用的某种算法,Java标准库没有提供怎么办?<br />方法一:自己写一个,难度很大;<br />方法二:找一个现成的第三方库,直接使用。<br />[BouncyCastle](https://www.bouncycastle.org/)就是一个提供了很多哈希算法和加密算法的第三方库。它提供了Java标准库没有的一些算法,例如,RipeMD160哈希算法。<br />用法:首先,我们必须把BouncyCastle提供的jar包放到classpath中。Java标准库的`java.security`包提供了一种标准机制,允许第三方提供商无缝接入。我们要使用BouncyCastle提供的RipeMD160算法,需要先把BouncyCastle注册一下:

// 注册BouncyCastle: Security.addProvider(new BouncyCastleProvider()); // 按名称正常调用: MessageDigest md = MessageDigest.getInstance(“RipeMD160”); md.update(“HelloWorld”.getBytes(“UTF-8”)); byte[] result = md.digest(); System.out.println(new BigInteger(1, result).toString(16));

```