3

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

例如: $2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re两者$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO都来自 hashing 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
4

2 回答 2

6

不,你不能检查这两个哈希是否属于同一个密码,除非你已经知道密码。如果可以的话,这基本上无法达到使用该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
于 2013-12-27T17:43:29.763 回答
1

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

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

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

因此,您可以简单地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;    
}
于 2013-12-27T17:40:13.357 回答