首先,我质疑该建议(根据年份调整成本)。成本应基于硬件的速度,而不是当前日期。如果您从现在到 2015 年之间不升级您的服务器,则没有理由增加成本。你所做的只是放慢一个已经很慢的过程。
话虽如此,我也质疑 1 秒对于大多数用途的建议。如果您正在处理高度敏感的信息,则 1 秒(或更长)就可以了。但对于一般的网站,我通常建议在 0.25 到 0.5 秒之间。在某些情况下,你可以降低,但我不会没有充分的理由。
现在,问题本身。使用crypt()
orpassword_hash()
时,迭代计数以返回哈希格式存储。事实上,盐也是如此。所以计算哈希所需的所有信息都包含在其中!
如果你没有使用这些 API(或我维护的 polyfill:password-compat),那么我真的想知道你为什么不使用。不要发明自己的密码加密。除非您有充分的理由(出于某些政府合规性原因,或与 PHP <= 5.2 的兼容性),否则不要使用使用本机哈希的库(如 phpass)。
一般认为 bcrypt 是当今最强的哈希格式。SCrypt 更强大,但它也存在一些问题,而且它仍然很新(而且它还没有在 PHP 核心中可用)。所以只需使用 bcrypt ...
该password_hash()
api 有一个机制让你做你所要求的:password_needs_rehash()
. 基本上,你传入散列,以及你今天使用的选项,它会告诉你是否需要重新散列:
if (password_verify($password, $hash)) {
if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 14])) {
$hash = password_hash($password);
update_password_in_database($hash);
}
$loggedin = true;
}
阅读有关 password_hash() 的 RFC 以了解有关它的更多信息(我从大量来源收集数据,并在 RFC 中包含参考资料)。
编辑 - 跟进@AnotherParker 的评论:
犯罪分子不会因为您没有升级服务器而停止升级他们的破解盒。您确实需要随着时间的推移增加工作参数以阻止离线攻击。
有点真实。嗯,是的,但错过了我上面所说的重点。
散列函数的成本参数是时间和精力的权衡。您需要花费一些时间来为每个散列增加额外的工作量。在相同的硬件上,花更多的时间会产生更多的工作。产生更多工作的另一种方法是获得更快的硬件。
但建议是在您当前的硬件上测试散列函数,并使其尽可能昂贵。如果 0.5 秒是您今天所能承受的最大值,除非您升级服务器硬件,否则增加成本对您有何帮助?简而言之,它不会因为你会打破你已经确定的最重要的时间限制。
所以你不能在不增加服务器能力的情况下增加工作参数,除非你已经产生了弱散列。
另外,请查看有关该主题的此答案