前开发人员使用PHP hash()
函数与SHA256算法存储密码哈希值。为了提高系统的安全性,我想开始使用crypt()
与Blowfish算法(不幸的是,我们没有PHP 5.5,因此password_hash()
不可用)。
由于SHA256是一种不可逆的哈希算法,是否有一种方法可以开始使用crypt()
与盐密码,而不要求每个人重置他们的密码?
那么您应该使用兼容性库。当你升级到5.5的时候会更方便。
重新哈希而不要求用户输入密码…那么,您可以等到下次用户登录时,然后使用password
扩展的password_verify()
功能。如果它失败了,那么你可以回到旧的SHA256哈希。如果SHA256哈希匹配,那么你可以使用password_hash()
重新哈希密码,并将其保存在旧哈希的位置:
if (password_verify($password, $hash)) {
// Matches...
} elseif (hash('sha256', $password) == $hash) {
// Matches...
$newHash = password_hash($password);
// Save $newHash in the old hash's place
} else {
die('Invalid password...');
}
它是技术上可以破解很多哈希,但是有太多的问题(你不会得到所有的哈希,它很可能是不可行的,它甚至可能是不合法的,等等)。
您可能要考虑的另一种方法是哈希链:由于您无法逆转SHA256,只需将新的哈希函数定义为crypt(sha256($passwd))
。由于您可能已经在文件中为所有密码设置了sha256($passwd)
,因此可以使用适当的salt对每个密码设置crypt()
以更新现有的散列(而不必等待用户登录)。
这是一个可能的解决方案:
在用户表中添加一列,表示对用户密码使用了哪种散列方法。在登录时,您将知道用户的密码,因为他刚刚输入了密码,因此,一旦传递了当前哈希,就从密码中创建一个新的has并更新标志列
这假设你在互联网上传递自由文本密码,除非你使用SSL,否则你不应该这样做。
或者,如果您在发送密码之前在客户端上散列,则更新客户端软件以处理两种散列算法并同时发送。使用您的标志来确定要检查的内容。
在这两种情况下,一旦所有(或大多数)用户都切换了,就删除旧的哈希,并将此问题强加给剩余的用户。
我假设您从未存储明文用户帐户密码,因为这确实是一件很糟糕的事情。因此,您不再拥有创建新密码摘要所需的数据。
我想你会需要每个人更新他们的密码。
可能有其他更快更有效的方法来做到这一点,但如果您想在不影响用户的情况下做到这一点,我将这样做-
在表中添加另一个列,一个可以为True或False的基本标志。默认为false。然后实现以下伪代码:
if(flag=true)
{
use crypt() and authenticate user
}
else
{
use hash() and authenticate user
use crypt() on the provided password (once authenticated)
update the record to put the new password into the table
set flag=true
}
本质上它检查密码是否更新,如果没有更新则更新。一旦用户完成了转换,您最终可以取消此功能。但由于它几乎没有增加负载,我建议保留它!
这有点迂回,但它将有最少的工作,为您的用户做,它将在后台运行,没有给他们任何指示发生!
我建议使用一个标记字段来注释哪些用户先前已被散列,然后对现有的散列进行加密。对于任何在身份验证时标记字段为true的人来说,它变成了一个两步的过程,对密码进行散列,然后加密以进行匹配检查。
当他们更新密码时,您将把标记字段设置为false。
是的,您需要做的是添加一个额外的列来存储crypt()
输出。当一个用户登录,并且他们的密码成功地hash()es
到您在数据库中拥有的密码时,您现在可以crypt()
该密码,并从数据库中删除旧的hash
。
这只在用户登录时起作用,所以你会有一段时间,有些用户在使用旧系统,有些用户在使用新系统。