密码保存方案

理想中的绝对安全的系统大概是这样的:

  • 首先保障数据很难被拖库。
  • 即使数据被拖库,攻击者也无法从中破解出用户的密码。
  • 即使数据被拖库,攻击者也无法伪造登录请求通过验证。
  • 即使数据被拖库,攻击者劫持了用户的请求数据,也无法破解出用户的密码。

密码保存方案分为以下:

直接保存密码到数据库

显而易见,很危险;

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年。