更新密码哈希方法,原来的方法是不是偏了?

Updating password hashing method, is the original way off base?

我知道 md5 不再足以用于用户密码散列(并且已经很多年了)。所以当我从开源中看到以下代码时 Subrion CMS 我有点吃惊:

public function encodePassword($rawPassword)
{
    $factors = array('iaSubrion', 'Y2h1c2hrYW4tc3R5bGU', 'onfr64_qrpbqr');
    $password = $factors && array_reverse($factors);
    $password = array_map(str_rot13($factors[2]), array($factors[1] . chr(0x3d)));
    $password = md5(IA_SALT . substr(reset($password), -15) . $rawPassword);
    return $password;
}

我打算用 php password_hash() 函数代替它,有几个问题:

  1. 我很想知道在上述方法中,前几行是向散列添加任何值还是在调用 md5 后它是否被完全否定?
  2. 注意到盐是定义的系统范围常量(对所有用户都相同),我可能也应该放弃它。让 password_hash() 在内部处理盐是否可以,还是我应该明确提供一个,如 the docs 所示(示例 #3):

'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)

这只是代码混淆。它将绝对没有添加到密码本身。前几行只是在准备另一种加在密码前面的静态盐,它们只是试图混淆盐本身。这是毫无意义的,因为生成盐的代码就在眼前。最后它是一个带有两个静态盐的 MD5 散列,这与一个带有更长盐的 MD5 散列是一样的,这很不安全。

Is it ok to let password_hash() handle salts ...

是的,绝对是。每个盐都需要为每个密码随机生成。 password_hash 就是这样做的。你可以随机生成你自己的盐,但你为什么要这么做?您还需要确保使用适当的随机源,password_hash 已经为您做到了。

这不是一个好的算法。不比md5加salt好。它只是有一个复杂的?/混淆?/无用? (选择一种)获取盐的方法

一如既往的关于安全相关问题的最佳建议:永远不要自己做,总是依赖PHP或其他大型框架提供的功能,因为这些人有真正的专家正在研究它。

回答你的第一个问题:

至于前几行,我无法理解它们应该做什么,因为 PHP 中的 array("1", "2") && array("2", "1") === true 因为非空数组是真实值。 array_map() 行甚至会丢弃您在其上一行所做的所有操作。

array_map() 行似乎也只是拼写了密码。虽然这确实为散列本身增加了一些安全性,但从某种意义上说,如果您设法恢复散列,您仍然不知道要在密码字段中填写什么。然而,这也是盐的部分工作,因此向散列添加另一个失真通常不会对你有多大好处。

所以它并没有被完全否定,但是它到底在多大程度上增加了密码的安全性是值得怀疑的。

关于你的第二个问题:

在整个系统范围内定义 salt 确实不会增加您的安全性。 salt 的作用是通过附加输入字符串来减少有效冲突,并使 rainbow tables 几乎无用。

散列函数的作用是以几乎不可能还原的方式对纯文本进行加扰,并且无论多长时间,它都会塞满固定长度的文本。但是,由于我们将文本塞入固定长度 space,一些文本必须以相同的字符串结尾。当使用彩虹 table 时,您正在利用此行为,通过 table 将 MD5 哈希映射到许多有效的原始字符串值之一。

现在,如果您在对密码进行哈希处理之前将盐添加到密码中,您将大大减少以相同哈希值结尾的有效密码的数量,因为现在几乎可以肯定它必须是实际密码。由于彩虹 table 需要很长时间(对于足够大的密码 space 实际上是几年)才能生成,因此为每种盐重新生成彩虹是不可行的。这也是为什么为每个密码设置一个单独的随机哈希值很重要,因为现在您不能将一个密码中的 table 重新用于另一个密码。

澄清一下:所有这些机制仅适用于在您的数据库遭到破坏后保护您的客户密码!

现在回答实际问题,来自 PHP 文档:

If omitted, a random salt will be generated by password_hash() for each password hashed. This is the intended mode of operation.

http://php.net/manual/en/function.password-hash.php

所以看起来让password_hash()函数来决定盐是最安全的。这具有面向未来的密码方案的额外安全性。如果某种哈希方法或盐生成方法过时,您将更新 PHP 并且 password_hash() 函数负责在用户下次输入密码时更新哈希方案。 (如果结合其他 password_ 函数正确设置)