【问题标题】:PHP password_hash Check Two HashesPHP password_hash 检查两个哈希
【发布时间】:2013-12-27 17:37:20
【问题描述】:

如果我使用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

【问题讨论】:

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


【解决方案1】:

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

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

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

【讨论】:

  • 对不起,我想我不是很清楚。我的意思是如果我不知道 test 是基本字符串。仅给定两个哈希值,是否仍然可以判断它们是否来自同一个基数?
  • @735Tesla:是的,我明白了,正如我在回答中所说,你需要知道你的基本字符串。
  • @Stoic 谢谢。知道盐是哈希的第一位的函数,有没有比暴力强制他们更快的方法来计算?
  • @735Tesla:除非你知道base string,否则我怀疑除了蛮力之外的任何东西都会帮助你。我怀疑,即使可以!
【解决方案2】:

有关盐和哈希方法的信息被编码到哈希中。这允许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;    
}

【讨论】:

  • 对不起,我想我不是很清楚。我的意思是如果我不知道 test 是基本字符串。仅给定两个哈希值,是否仍然可以判断它们是否来自同一个基数?
  • @735Tesla 不知道基本字符串是不可能进行测试的。这就是单向哈希的目的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-03
  • 1970-01-01
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多