Pro*_*irl 9 php security passwords bcrypt
我看到一个建议,即轮数的数量应该($currentYear - 2000)
考虑到摩尔定律,因此2013年将是13
轮次,因此2^13
总迭代次数.当然,你需要考虑你自己的硬件,以确保它不会花太长时间(我看到1 second
建议用"检查密码/哈希"的"安全",并且在我当前的硬件上有13个回合落在那个标记上).
对于社交网络类型的网站来说这听起来合理吗?或者,我是否会通过使用将自己设置为非常慢的密码检查($currentYear - 2000)
?
另外,你如何处理从一年到下一年的轮数改变?不会改变轮数改变哈希值,因此不允许你在2014年检查哈希,因为支票将使用额外一轮?您是否必须每年重新计算每一个哈希值,或者它将如何正常工作?
irc*_*ell 16
首先,我质疑该建议(根据年份调整成本).成本应基于硬件的速度,而不是当前日期.如果您从现在到2015年之间不升级服务器,则没有理由增加成本.你所做的只是缓慢已经很慢的过程.
话虽如此,我也质疑大多数用法的1秒建议.如果你正在处理高度敏感的信息,1秒(或者更长)是可以的.但对于普通网站,我通常建议0.25到0.5秒.在某些情况下,你可以降低,但我不会没有充分的理由.
现在,问题本身.使用crypt()
或时password_hash()
,迭代计数以返回哈希格式存储.事实上,盐也是如此.因此,计算哈希所需的所有信息都包含在其中!
如果你没有使用这些API中的任何一个(或者我维护的polyfill:password-compat),那么我真的不得不怀疑你为什么不这样做.不要发明自己的密码加密.不要使用使用本机哈希(如phpass)的库,除非您有充分的理由(出于某些政府合规性原因,或与PHP <= 5.2的兼容性).
通常认为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;
}
Run Code Online (Sandbox Code Playgroud)
请阅读RFC for password_hash()以获取有关它的更多信息(我从大量来源收集数据,并在RFC中包含参考).
犯罪分子不会因为您没有升级服务器而停止升级他们的破解箱.您需要随着时间的推移增加工作参数以阻止脱机攻击.
排序真实.嗯,是的,但是忽略了我上面谈论的内容.
散列函数的成本参数是时间 - 努力权衡.您需要花些时间为每个哈希添加额外的工作量.在相同的硬件上,花更多的时间会产生更多的工作.产生更多工作的另一种方法是获得更快的硬件.
但建议是测试当前硬件上的哈希函数,并使其成为合理的硬件.如果0.5秒是您今天可以承受的最大值,除非您升级服务器硬件,如何增加成本来帮助您?简而言之,它不会因为你将打破你已经确定的最大时间限制很重要.
因此,除非您已经生成弱哈希,否则无法在不增加服务器功能的情况下增加工作参数.
另外,请查看有关该主题的答案
当您使用bcrypt时,轮数是生成的哈希的一部分:
crypt ( 'Password', '$2a$04$thisshallbemysalt' );
Run Code Online (Sandbox Code Playgroud)
会产生类似的结果
$2a$04$thisshallbemysalt.rAnd0ml0ok1ngch4rsh3re
Run Code Online (Sandbox Code Playgroud)
2a
在第一个$符号代表bcrypt algorithem之后,接下来04
代表轮数 - 所以通过查看哈希,你可以看到完成创建它的轮次数.
因此,当您确定是时候提高轮数时,您可以检查用户登录时生成存储哈希时使用的轮数 - 如果不是您当前的轮数,则在那里重新哈希密码然后,并将其保存为新的哈希(在检查他们的密码是否与现有哈希匹配之后,当然;-))