Feb 27, 2017
采用MD5或SHA-2家族的不可逆哈希函数混淆密码,由于它们被设计用来快速的计算数据的摘要值,通常是不可靠的。随着计算机性能的提高和GPU并行运算优化等手段可以越来越快的计算,降低了暴力破解的难度。
BCrypt是一种专门的密码散列函数,在1999年首次发布,各种语言都已有相应实现。它通过引入一个工作因子(work factor)以对抗摩尔定律,随着计算能力的提高,也可以相应的加大这个因子提高暴破成本。而且由于计算时间较慢和难以让GPU有效的计算,可以使安全级别大大提高。因此被称为A Future-Adaptable Password Scheme 。
加密字符串一般类似于$2a$10$7QDYxuYJBCEKu1q8IMHYg.3lq6OTiA5seEjtnYGOccsC0MkLtvJrS
,可以分为四个部分
$<id>$<cost>$<salt><digest>
<id>
表示哈希算法和格式, 一到两个字符<cost>
04 ~ 31, 工作因子,要重复迭代2**cost
次,两个字符<salt>
128位表示的盐,使用特殊的Base64编码为22个字符<digest>
最终的结果值,184位编码为31个字符3(美元符号) + 1 or 2 + 2 + 22 + 34 = 59 or 60
所以总长比较固定,数据库可以采用CHAR(60)
,且无需其他字段存储盐
示例中用到的BCrypt由Spring Security
提供
publicclassPasswordHashTest{privatefinalStringplainPasswd="1234@abcd";@TestpublicvoidnormalTest(){Stringhash1=BCrypt.hashpw(plainPasswd,BCrypt.gensalt());Assert.assertTrue(BCrypt.checkpw(plainPasswd,hash1));}@TestpublicvoidstrongerTest(){// 通常这个测试会跑比较久,计算能力过剩可改为BCrypt.gensalt(31)Stringhash2=BCrypt.hashpw(plainPasswd,BCrypt.gensalt(14));Assert.assertTrue(BCrypt.checkpw(plainPasswd,hash2));}}