代码中的PHP哈希码主密码

时间:2014-06-06 20:17:14

标签: php security hash passwords

我正在开发一个使用LDAP服务器进行身份验证的PHP Web应用程序。但是,如果LDAP服务器出现故障或者出现其他问题,我仍然需要访问系统,我希望在代码中直接写入主密码。

此系统的上一次迭代(我没写过)只是将密码存储为明文(!)。所以:

if ($username == "dan" && $password == "32fsss") {

当然非常不安全。

所以我想解决这个问题。我在想哈希密码,所以这样做

$hashedPassword = password_hash($password);
if ($username == "dan" && $hashedPassword == "HASHPASSWORDSTOREDHERE") {

所以我会将 hash 硬编码为主密码,而不是实际密码本身。这样安全吗?我知道被盗的哈希是坏的,但它比被盗的明文密码更好。

当然,所有用户输入都将被适当地消毒。

或者:有关拥有主密码访问系统的其他想法吗?

3 个答案:

答案 0 :(得分:1)

如果它纯粹是一个只读事件而他们得到的只是哈希版本,那么它应该不是问题。话虽如此,我更喜欢使用hash()函数而不是password_hash(),但这只是我个人的偏好。

唯一的问题是,如果读取php文件并获得散列密码的攻击者有办法将其反转(即彩虹表)。在这种情况下,您的系统变得不安全。这是我hash()优于password_hash()的首选地。使用hash()。为了生成散列形式,我可以说:

$HashedMasterPassword = hash('md5', $MasterPassword . "MyMD5Salt") . hash('sha256', $MasterPassword . "MyShaSalt");

然后在我上传的代码中,我可以将上面代码($HashedMasterPassword)的输出和该代码串的硬编码。这增加了两种不同的盐,两种不同的散列函数,它降低了彩虹表攻击的可能性,因为攻击者需要发生md5 +第一次盐和sha256 +第二次盐的碰撞。这是,我敢说这个词,不可能。当然,鸽子洞效应说这是可能的,但事实并非如此,我不会为此烦恼。

所有人都说,使用password_hash()并存储该哈希是好的,如果你真的想。我个人不喜欢它。

编辑:添加实施细节

我相信基于这些评论,对于如何实施这一点存在一些混淆。假设我的主密码是thisIsMyPassword(超级秘密和超级安全,我知道)。好吧,我们需要生成硬编码的散列形式。可以通过以下方式找到硬编码的散列形式:

$MasterPassword = "thisIsMyPassword";
$HashedMasterPassword = hash('md5', $MasterPassword . "MyMD5Salt") . hash('sha256', $MasterPassword . "MyShaSalt");
echo $HashedMasterPassword;

重要提示:您不会将此内容上传到服务器。这只会用于生成哈希值,然后应该永久删除。

输出结果为:6dcfc45fba2fff44b7cfc8df7245a1b7804c88d63a82ac2ba33e0de32ab7f20c5afe2c1784e87f1bae8a4f91f1a84833

因此,在需要覆盖主密码的代码中,您输入:

$MasterHash = '6dcfc45fba2fff44b7cfc8df7245a1b7804c88d63a82ac2ba33e0de32ab7f20c5afe2c1784e87f1bae8a4f91f1a84833';
$SubmittedMasterPass = $_POST['MasterPassword'];
$HashedVersionOfSubmittedMasterPass = hash('md5', $SubmittedMasterPass . "MyMD5Salt") . hash('sha256', $SubmittedMasterPass . "MyShaSalt");
if($MasterHash !== $HashedVersionOfSubmittedMasterPass){
  die('Override Failed. Reason: Wrong Password.');
}else{
  // User has successfully logged in using the master password.
}

再次根据评论中的信息进行说明,这比仅使用SHA256更安全,因为必须找到一个强制主密码,当6dcfc45fba2fff44b7cfc8df7245a1b7附加到结尾时,会生成MyMD5Salt804c88d63a82ac2ba33e0de32ab7f20c5afe2c1784e87f1bae8a4f91f1a84833附加到它的末尾时,它也必须产生MyShaSalt。这意味着碰撞必须满足两种不同的算法,这比仅仅满足Sha256算法要困难得多。

然而,正如评论中所指出的,这需要花费几毫秒的时间来处理;因此,如果减少执行时间是您的首要任务,那么可能建议仅使用Sha256而不是使用MD5和Sha256组合。

答案 1 :(得分:0)

如果用户有权访问源代码。他们可以改变它,所以它并不重要。

答案 2 :(得分:0)

人们可以讨论这样一个"后门"是否可取,但如果你不能自己决定,有两种方法可以保护这种硬编码密码。仅存储散列肯定比明文密码好得多,因为每个对代码具有读访问权限的人都可以在正在运行的系统上使用它。

第一种可能性是使用带有成本因子的慢哈希算法,例如您在示例中提出的password_hash()。如果攻击者具有对代码的读访问权限,则他必须强制使用此密码,以便在实时系统上使用它。慢速哈希算法会阻止暴力破解,而MD5和其他函数的速度太快(8 Giga MD5 per second)。缺点是验证密码时应用程序会变慢。

第二种可能性是一个非常强大的密码。选择足够长的随机组合,例如使用密码管理器生成70个字符并将其用作主密钥。即使像SHA256这样的快速算法也不适合强制执行,而且你的密钥不受字典攻击的影响,甚至不需要腌制。