【问题标题】:Salted Password Validation in PHPPHP中的盐渍密码验证
【发布时间】:2013-08-26 21:24:11
【问题描述】:

crackstation.net 上写着:

验证密码

  • 从数据库中检索用户的盐和哈希。
  • 将盐添加到给定密码并使用相同的哈希函数对其进行哈希处理。
  • 将给定密码的哈希值与数据库中的哈希值进行比较。如果它们匹配,则密码正确。否则,
    密码不正确。

但是在页面底部列出的source code 中,我无法弄清楚validate_password 函数是如何考虑盐分的。我的意思是给定密码前面的盐在哪里?

这里是有问题的函数:

function validate_password($password, $correct_hash)
{
    $params = explode(":", $correct_hash);
    if(count($params) < HASH_SECTIONS)
       return false;
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

【问题讨论】:

  • 如果您不完全了解用户安全的身份验证/盐/哈希,您应该外包给外部类来为您处理所有这些。我有时使用的一个:github.com/ircmaxell/password_compat 或我创建并证明是稳定的简单版本:github.com/DarylJG/Authentication
  • @DarylGill 当你说稳定时。这是什么意思?
  • @PeeHaa 可能是用词错误。更合适的会是可靠的
  • 问题是:它安全吗? IE。它是否经过了知道如何判断的人的审查?

标签: php security salt password-hash


【解决方案1】:

看起来Salt、Hash和interation number存储在同一个字符串中,并在函数开头分成三个字符串(在一个数组中):

$params = explode(":", $correct_hash);

值的顺序取决于常量 HASH_ALGORITHM_INDEX、HASH_SALT_INDEX 和 HASH_ITERATION_INDEX 的定义方式。

【讨论】:

  • 非常感谢。我没有意识到哈希存储在与盐相同的字符串中。现在说得通了。
【解决方案2】:

PHP 5.5 有自己的函数password_hash() 可以生成安全的 BCrypt 哈希。如上例所示,生成的字符串将包含哈希、盐和成本参数,并且长度始终为 60 个字符。这些参数稍后由函数password_verify()提取,用于验证密码。

对于早期的 PHP 版本,存在 compatibility pack‌​

【讨论】:

  • 感谢您的回答。我更多的是寻找解释来帮助我理解我发布的功能。但我也可以查看兼容性包。
  • @AdamJohns - 理解代码总是一件好事,祝你好运!
【解决方案3】:

我不完全确定上面发生了什么,所以让我稍微解释一下哈希,这是以前做过的,并且有来源,但无论如何我都会去!它曾经对我们所有人来说都是新的!

如果我们有一个函数,称它为f 并让它成为我们的散列函数,它将每个可能的输入都带到有限数量的输出中,这就是它不能反转的原因,这被称为满射功能http://en.wikipedia.org/wiki/Surjection 更多信息请参见此处。就像 f(x)=x^2 如果 f(x)=4 我们实际上不知道 x 是什么(我们碰巧知道它可以是 2 或 -2)

虽然哈希的顺序不同,但因为无限数量的(理论上,计算机无法处理所有字符串中最长的字符串,它太大了!)输入到有限数量的输出。

如果我知道这是一个密码假设,假设您的密码是P 我知道f(P)=h,并且 P 是 10,000 个值中的 1 个,包括 0000 到 9999。所以我可以做 10k 哈希(最坏的情况)并得到你的密码。

盐是确定性地应用于输入的一些随机废话,所以假设s(x) salts x,可以通过在输入的每个字母之间放置字母“k”(虽然这将是废话盐)但是这样s 的输出只取决于x,给定相同的输入我们得到相同的输出。

然后你用f(s(x)) 来获取你的哈希值,这样如果我知道哈希值但不知道盐,我必须先弄清楚你是如何加盐的,如果我知道我的盐的话必须知道你是如何应用它的,等等。

所以假设你对密码做了上面的简单盐,所以常见的“密码”变成了“pkakskskwkokrkd”,我有我的“彩虹表”(输入列表及其哈希值),我可能不会有(盐形式)在该表中,但假设我知道哈希,并且您将 ks 放在字母之间,我必须使用单词重新创建我的彩虹表,但其中包含 ks,这会占用大量内存,很多时间.....但是我可以破解你所有的密码(因为盐对所有人都是一样的)

这就是你的系统所说的“用户盐”,这样如果我用 ks 破坏系统,只有一个人的东西被破解,我必须为每个人做。

现在是一些 PHP 代码!

我建议您使用 sha512 salt,这会为任何输入提供固定的 128 个字符长(它是 PHP,它将最终存储在数据库中)输出。

$hash = hash("sha512",$data);

要对其进行加盐,您可以对其进行多次哈希处理,您可以在其之间放置一个 k,只要它对于给定的输入具有“确定性”相同。

最后它是如何工作的:

如果银行有我的密码的加盐哈希,他们不会“破坏”它,让我的密码与我输入的数字进行比较,他们会对我刚刚输入的密码进行加盐和哈希,并将值与数据库中的结果进行比较,如果哈希相同,则输入的引脚相同。

哈希可能会发生冲突,但这种情况非常罕见,“雪崩效应”已经过研究并确保在哈希算法中出现(术语?),类似的输入会产生截然不同的输出。

哈希仅适用于相等性测试。

【讨论】:

  • 感谢您抽出宝贵时间回答。但是我已经掌握了你解释的内容。我在问一个关于验证功能工作方式的具体问题。赞一个,先生。
  • 再一次,仍然是 5 票赞成 = 50,7 票反对 = -14,仍然是赢家!
  • -1: sha512 不是用来存储密码的。它已针对速度进行了优化。在现代 PHP 中,您应该使用带有 blowfisf 或 pbkdf2 的新 password apicrypt()
  • @tereško 你应该阅读前半部分,没有理由不使用sha512 我曾在密码学界看到过。这是一个极好的散列函数,没有已知漏洞现在可能有一个 API 可以做到这一点,但它不会让旧方法变得糟糕,CRC32 很糟糕,MD5 可以被认为是坏的,但 SHA 算法是健全的!
猜你喜欢
  • 2011-08-07
  • 2014-10-31
  • 2011-04-03
  • 2016-07-28
  • 2021-10-02
  • 2011-06-25
  • 1970-01-01
相关资源
最近更新 更多