哈希算法
哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
哈希算法最重要的特点就是:
- 相同的输入一定得到相同的输出;
- 不同的输入大概率得到不同的输出。
哈希碰撞
哈希碰撞是指,两个不同的输入得到了相同的输出: ``` “AaAaAa”.hashCode(); // 0x7460e8c0 “BBAaBB”.hashCode(); // 0x7460e8c0
hash算法碰撞不可避免,碰撞率的高低关系到哈希算法的安全性。<br />常用的哈希算法有:
|
算法
| 输出长度(位)
| 输出长度(字节)
|
| --- | --- | --- |
|
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中使用哈希算法
// 创建一个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[]数组表示的摘要,最后,把它转换为十六进制的字符串。
### 加盐
在使用Hash算法时,要注意防止彩虹表攻击。彩虹表即当用户输入的字符是一些常见的口令(例如:123456,hello123),这些都是预先计算好的口令,并且已经有口令和它对应的转换结果的一张表即彩虹表。<br />如果用户使用了常用口令,黑客从MD5一下就能反查到原始口令。<br />为防止这种情况,我们可以对每一个口令添加额外的随机数,这个方法称之为加盐<br />`digest = md5(salt+inputPassword)`
## 第三方哈希算法和加密算法库
我们知道,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));
```