BCrypt是由Niels Provos和David Mazières设计的密码哈希函数,他是基于Blowfish密码而来的,并于1999年在USENIX上提出。
除了加盐来抵御rainbow table 攻击之外,bcrypt的一个非常重要的特征就是自适应性,可以保证加密的速度在一个特定的范围内,即使计算机的运算能力非常高,可以通过增加迭代次数的方式,使得加密速度变慢,从而可以抵御暴力搜索攻击。
Bcrypt可以简单理解为它内部自己实现了随机加盐处理。使用Bcrypt,每次加密后的密文是不一样的。
对一个密码,Bcrypt每次生成的hash都不一样,那么它是如何进行校验的?
- 虽然对同一个密码,每次生成的hash不一样,但是hash中包含了salt(hash产生过程:先随机生成salt,salt跟password进行hash);
- 在下次校验时,从hash中取出salt,salt跟password进行hash;得到的结果跟保存在DB中的hash进行比对。
在Spring Security 中 内置了Bcrypt加密算法,构建也很简单,代码如下:
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
生成的加密字符串格式如下:
$2b$[cost]$[22 character salt][31 character hash]
$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
\__/\/ \____________________/\_____________________________/
Alg Cost Salt Hash
上面例子中,$2a$ 表示的hash算法的唯一标志。这里表示的是Bcrypt算法。
10 表示的是代价因子,这里是2的10次方,也就是1024轮。
N9qo8uLOickgx2ZMRZoMye 是16个字节(128bits)的salt经过base64编码得到的22长度的字符。
最后的IjZAgcfl7p92ldGxad68LJZdL17lhWy是24个字节(192bits)的hash,经过bash64的编码得到的31长度的字符。