密码保存方案
理想中的绝对安全的系统大概是这样的:
- 首先保障数据很难被拖库。
- 即使数据被拖库,攻击者也无法从中破解出用户的密码。
- 即使数据被拖库,攻击者也无法伪造登录请求通过验证。
- 即使数据被拖库,攻击者劫持了用户的请求数据,也无法破解出用户的密码。
密码保存方案分为以下:
直接保存密码到数据库
显而易见,很危险;
md5加密
现在应该很少系统会直接保存用户的密码了,至少也是会计算密码的md5后保存。
md5这种不可逆的加密方法理论上已经很安全了。
但是随着彩虹表的出现,使得大量长度不够的密码可以直接从彩虹表里反推出来。
md5+加盐
只对密码进行md5加密是肯定不够的。处理方式为在用户的密码后加上一段很长的字符串。即使用户的密码很短,只要在他的短密码后面加上一段很长的字符,再计算md5 ,那反推出原始密码就变得非常困难了。加上的这段长字符,我们称为盐(Salt),通过这种方式加密的结果,我们称为加盐Hash。比如:
$$md5(md5(password) + salt)$$
SHA512+加盐
常用的哈希函数中,SHA-256、SHA-512 会比md5更安全,更难破解,出于更高安全性的考虑,这个方案中,会使用SHA-512代替md5,比如:
$$SHA512(SHA512(password) + salt)$$
通过上加盐哈希运算,即使攻击者拿到了最终结果,也很难反推出原始的密码。不能反推,但可以正着推,假设攻击者将salt值也拿到了,那么他可以枚举遍历所有6位数的简单密码,加盐哈希,计算出一个结果对照表,从而破解出简单的密码。这就是通常所说的暴力破解。
慢哈希加盐
为了应对暴力破解,我使用了加盐的慢哈希。慢哈希是指执行这个哈希函数非常慢,这样暴力破解需要枚举遍历所有可能结果时,就需要花上非常非常长的时间。比如:bcrypt就是这样一个慢哈希函数:
$$bcrypt(SHA512(password), salt, cost)$$
通过调整cost参数,可以调整该函数慢到什么程度。假设让bcrypt计算一次需要 0.5 秒,遍历6位的简单密码,需要的时间为:((26 * 2 + 10)^6) / 2 秒,约900年。