PHP中的Salted密码验证


Salted Password Validation in PHP

在crackstation.net上声明:

验证密码

  • 从数据库中检索用户的salt和hash
  • 将salt预先设置为给定的密码,并使用相同的哈希函数对其进行哈希
  • 将给定密码的哈希与数据库中的哈希进行比较。如果它们匹配,则密码是正确的。否则,
    密码不正确

然而,在页面底部列出的源代码中,我不知道validate_password函数是如何考虑salt的。我的意思是,给定密码的salt在哪里?

以下是有问题的函数:

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
        )
    );
}

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

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

值的顺序取决于如何定义常数HASH_ALGORITHM_INDEX、HASH_SALT_INDEX和HASH_ITERATION_ININDEX。

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

对于早期的PHP版本,存在一个兼容性包‌​.

我不完全确定上面发生了什么,所以让我解释一下哈希,这以前已经做过了,而且有来源,但无论如何我都会尝试的!这对我们所有人来说都是新鲜事!

如果我们有一个函数,称它为f,并将其作为我们的哈希函数,它将所有可能的输入都转化为有限数量的输出,这就是为什么它不能反转,这被称为满射函数http://en.wikipedia.org/wiki/Surjection请参阅此处了解更多信息。像f(x)=x^2一样,如果f(x)=4,我们实际上不知道x是什么(我们碰巧知道它可以是2或-2)

不过,散列的顺序不同,因为无限多个(理论上,计算机无法处理所有字符串中最长的一个,它太大了!)输入到有限数量的输出。

如果我知道这是一个引脚编号,假设你的引脚编号是P,我知道f(P)=h,p是10000个值中的1,包括0000到9999。所以我可以做10k散列(最坏的情况)然后得到你的徽章。

盐是一些随机的垃圾,它决定性地应用于输入,所以假设s(x)盐x,它可以通过在输入的每个字母之间放置字母"k"来实现(尽管这将是一个垃圾盐),但这样s的输出只取决于x,给定相同的输入,我们得到相同的输出。

然后你做f(s(x))来得到你的哈希,这样,如果我知道哈希,但不知道盐,我必须先弄清楚你是如何腌制的,如果我真的知道盐,那么我必须知道你是如何使用它的,等等。

所以假设你对密码做了上面的简单salt,所以常见的"密码"变成了"pkakskskwkokrkkd",我有我的"彩虹表"(输入及其哈希值的列表),我可能不会在那个表中有(salt形式),但假设我知道哈希,你把ks放在字母之间,我必须用单词重新创建我的彩虹表,但其中有ks,这需要大量的记忆和时间。。。。。但是我可以破解你所有的密码(因为盐对所有人来说都是一样的)

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

现在获取一些PHP代码!

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

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

要对其进行加盐处理,您可以对其进行多次散列,您可以在它之间加一个k,只要它对于给定的输入是"确定性的"。

最后它的工作原理:

如果银行有我的密码加盐散列,他们不会"破坏"它,为了让我的密码与我输入的密码进行比较,他们对我刚刚输入的密码加上盐并散列,然后将值与数据库中的结果进行比较,如果散列相同,则输入的密码也相同。

哈希可以发生碰撞,但这是非常罕见的,"雪崩效应"被研究并确保存在于哈希算法中(术语?),类似的输入会产生截然不同的输出。

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