盐(Salt)的基本原则:
注意:有些人可能会将每个用户都不同的字段(uid、手机号之类的)来作为盐。很明显这是不规范的,几乎违背了上面三条盐的生成规则。 在实际项目中,盐不一定要加在最前面或最后面,也可以插在中间,或者分开插入,还可以使用倒序,等等,进行灵活调整
示例: 生成一个16位的随机盐
import java.security.SecureRandom;
public class MethodTest{
@Test
public void toRText() {
byte[] values = new byte[16];
System.out.println(Arrays.toString(values));
SecureRandom random = new SecureRandom();
random.nextBytes(values);
System.out.println(Arrays.toString(values));
// System.out.println(Base64.toBase64String(values));
//需要导入cn.hutool依赖
System.out.println(HexUtil.encodeHexStr(values));
}
}
传统的无加盐的加密方式很容易被彩虹表破解;当然,如果你盐加的不够也是一样的,从数学角度来讲,使用固定盐和没加盐几乎无异。
彩虹表就是穷举密码和对应摘要的一个表.。有了这个表,就可以通过遍历的方式破解密码
最早的MD5或SHA-1方式:
md5(md5(password) + salt)
现在大部分的加盐加密都将MD5或SHA-1替换为了更为安全的哈希函数:SHA-256或者SHA-512:
sha512(sha512(password) + salt)
上面的加盐方式都需要将盐值另外·储存,而是BCrypt则是通过加密密码得到,这样每个密码的盐值也是不同的:
bcrypt(sha512(password), salt)
//或者
bcrypt(sha512(password), salt, cost)
使用BCrypt加盐的方式一方面不用另外储存盐值了,另一方面可以大大拖慢破译者的破译速度; 由于BCrypt是采用慢哈希算法,一个明文映射多个密文,所以跟SHA比起来要慢的多(比如加密同一串字符,SHA可能只需要1微妙,而BCrypt可能需要0.1秒); 通过调整 cost 参数,可以调整该函数慢到什么程度。假设让 BCrypt 计算一次需要 0.5 秒,遍历 6 位的简单密码,需要的时间为:((26 * 2 + 10)^6) / 10 秒,约 900 年。 一般来说,SHA加盐的方式就已经很安全了,除非涉及绝密信息,并且可以牺牲一定性能时,才有必要考虑 BCrypt 加密
做了这么多操作主要还是为了下面两点:
前面做了那么多铺垫,现在正式进入正题。
先来看下BCrypt生成的密文
说明:
示例:
@Test
public void BCryptTest() {
//{加密
//原文
String password = "123456";
//BCrypt.hashpw(加密原文, BCrypt.gensalt( cost(加密强度)默认为10,推荐设为12 ));
String hashPw = BCrypt.hashpw(password, BCrypt.gensalt());
// String hashPw = BCrypt.hashpw(password, BCrypt.gensalt(12));
System.out.println(hashPw);
//{验证
//原文
String newPassword = "123456";
// String hashNPw = BCrypt.hashpw(newPassword, BCrypt.gensalt(12));
//验证
boolean checkpw = BCrypt.checkpw(newPassword, hashPw);
if (checkpw) {
System.out.println("验证成功");
} else {
System.out.println("验证失败");
}
}
BCrypt包可在多个依赖中引入:
<!--Bcrypt包依赖1 选择任一即可-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.10</version>
<scope>compile</scope>
</dependency>
<!--Bcrypt包依赖2 选择任一即可
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
-->
<!--Bcrypt包依赖3 选择任一即可
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.5.1</version>
</dependency>
-->
BCrypt官网
大公司是如何使用BCrypt配合加密使用的呢?
分享一篇Dropbox公司发布的博文: How Dropbox securely stores your passwords 总结一下: