PHP password_hash检查两个哈希值

时间:2013-12-27 17:37:20

标签: php encryption passwords password-hash php-password-hash

如果我使用password_hash函数创建了两个密码哈希值,如何判断它们是否来自相同的基本密码?我知道每次使用不同的盐。我没有明文。

例如: $2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO都来自哈希test。如果将这两个哈希值作为参数给出,我该如何编写一个返回true的函数?

这可能吗?

所以:

<?php
function check_hashes($hash1, $hash2) {
(some code)
}
echo strval(check_hashes('$2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re', '$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO'));
echo strval(check_hashes('$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO', '$2y$10$LoUOu3kt7zm1YZI1PtAsD.yzWF0b9jqOaAH64lK51VtgqRJZBgtO6'));
?>

输出:

TRUE
FALSE

2 个答案:

答案 0 :(得分:4)

不,除非您已经知道密码,否则无法检查这两个哈希值是否属于同一密码。如果可以,这基本上无法使用password_hash函数。

如果您知道密码,可以使用password_verify方法验证密码:

$res1 = "$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO";
$res2 = "$2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re";
var_dump(password_verify("test", $res1)); // returns true
var_dump(password_verify("test", $res2)); // returns true

因此,正如您所看到的,两个哈希都会为您true提供password_verify()方法,因此,您无需检查这两个哈希值是否属于同一密码。并且,如果这样做,上面的逻辑可用于构造这样的函数:

function belongs_to_password() {
  $args = func_get_args();
  $str  = array_shift($args);
  foreach ($args as $hash) {
    if (!password_verify($str, $hash)) return false;
  }
  return true;
}

上述函数可用于检查传递给此函数的哈希值是否全部用于相同的密码。并且,可以像这样使用:

$res1 = "$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO";
$res2 = "$2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re";
var_dump(belong_to_password("test", $res1, $res2)); // returns true

答案 1 :(得分:1)

有关salt和hash方法的信息被编码到哈希中。这允许password_verify()在没有盐的单独知识的情况下工作(即,您不需要将盐存储在某个数据库中)。

请注意pasword_verify()文档中的此部分:

  

请注意,password_hash()返回算法,cost和salt作为返回哈希的一部分。因此,验证哈希所需的所有信息都包含在其中。这允许验证函数验证散列,而无需为salt或算法信息单独存储。

因此,您只需针对两个哈希值运行password_verify()

$hash1_verified = password_verify('test', $hash1);
$hash2_verified = password_verify('test', $hash2);

如果这两个都返回true,则它们都是test的哈希值。

用于将基本单词与任意大小的哈希数组进行比较以验证来自相同基本单词的所有哈希值的函数可能如下所示:

function hash_base_matches_all_hashes($base, $hash_array) {
    for($i = 0; $i < count($hash_array); $i++) {
        if (false === password_verify($base, $hash_array[$i]) {
            return false;
        }
    }
    return true;    
}