更新密码哈希方法,原来的方法是不是偏了?
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() 函数代替它,有几个问题:
- 我很想知道在上述方法中,前几行是向散列添加任何值还是在调用 md5 后它是否被完全否定?
- 注意到盐是定义的系统范围常量(对所有用户都相同),我可能也应该放弃它。让
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_ 函数正确设置)
我知道 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() 函数代替它,有几个问题:
- 我很想知道在上述方法中,前几行是向散列添加任何值还是在调用 md5 后它是否被完全否定?
- 注意到盐是定义的系统范围常量(对所有用户都相同),我可能也应该放弃它。让
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_ 函数正确设置)