正文
现实中,由于不少网站使用了“快函数”来处理口令,因此数据库泄露后,大量口令被还原也就在所难免了。
增加成本
虽然 Hash 函数单次执行很快,但我们可以反复执行大量次数,这样总体耗时就变长了。例如:
functionslow_sha256(x)
for i = 0 to 100000
x = sha256(x)
end
return xend
在密码学中,这种方式叫做
拉伸
。现实中有不少方案,例如 PBKDF2 —— 它没有重头设计一种新算法,而是对现有的函数进行封装,从而更适合用于口令处理:
functionpbkdf2(fn, ..., iter)
...
for i = 0 to iter ...
x = fn(x, ...)
...
end
...
return xend
它有一个迭代参数,用于指定反复 Hash 的次数 —— 迭代次数越多,执行时间越长,破解也就越困难。
PBKDF(Password-Based Key Derivation Function,基于口令的秘钥导出函数),顾名思义,就是输入“口令”(有规律的字串)输出“秘钥”(无规律的长串)的函数,并且计算过程会消耗一定资源。本质上也是 Hash 函数,输出结果称之 DK(derived key)。
前端拉伸
拉伸次数越多虽然越安全,但这是以消耗服务端大量计算资源为代价的!为了能在安全和性能之间折衷,通常只选择几十到几百毫秒的计算时间。
服务端的计算量如此沉重,以至于不堪重负;而如今的客户端,系统资源却普遍过剩。能否让用户来分担一些计算量?
听起来似乎不可行。毕竟前端意味着公开,将密码相关的算法公开,不会产生安全问题吗。
先来回顾下,传统网站是如何处理口令的 —— 前端通常什么都不做,仅仅用于提交,口令都是由后端处理的:
现在,我们尝试对前端进行改造 —— 当用户在注册、登录等页面中提交时,
不再发送原始口令,而是口令的 DK
:
后端,则不做任何改动。(当然这会影响已有账号的使用,这里暂时先不考虑,假设这是个新网站)
这样,
即使用户的口令很简单,但相应的 DK 却仍是个毫无意义的长串
。通过 DK 的 Hash 值,是极难还原出 DK 的。(在本文开头就提到过了)
当然,攻击者更感兴趣的不是 DK,而是口令。这倒是可以破解的 —— 只需将前后端算法结合,形成一个新函数:
F(