password_verify二进制数据是否安全?

时间:2018-06-15 00:19:12

标签: php passwords

这是代码,结果看起来非常有趣:

简单版本:

$str1 = hex2bin('71f6f2170242774f6252191ff08b6d50e8762d49b46fe105d7bed9a563156971806f6f34dccdff148366a79830c4529a5052a7db6c7034577e5fe4912a7960e95b4f40c20015');
$str2 = hex2bin('71f6f2170242774f6252191ff08b6d50e8762d49b46fe105d7bed9a563156971806f6f34dccdff148366a79830c4529a5052a7db6c7034577e5fe4912a7960e95b4f40c2');
$hash = password_hash($str1, PASSWORD_DEFAULT);

var_dump(password_verify($str2, $hash)); // export: bool(true)

更复杂的版本:

$pass = 0;
$fail = 0;
for ($i = 0; $i < 20; $i++) {
    $password_org = random_bytes(70);

    $hash = password_hash($password_org, PASSWORD_DEFAULT);

    $password = substr($password_org, 0, 68);

    if (password_verify($password, $hash)) {
        var_dump([bin2hex($password_org), bin2hex($password)]);
        $pass++;
    } else {
        $fail++;
    }
}
echo "Pass: $pass\nFail: $fail\n";

结果总是显示一些失败,一些通过。 我找不到http://php.net/manual/en/function.password-verify.php的答案,任何人都有任何想法?

2 个答案:

答案 0 :(得分:1)

这是因为random_bytes或hex2bin会生成意外的中断字符(\ 0),当您将其传递给password_hash时,实际密码会被截断,为此,当您使用substr时,有时会使用真实密码(由中断字符截断) )更短。

如果使用bin2hex函数$password_org = bin2hex(random_bytes(70));进行换行,则总是失败。

答案 1 :(得分:0)

在@Clemen的帮助下,我找到了答案,password_verify无法正常处理\ 00~ \ 20。解决它(我不知道它是否理想,可能是一个不好的做法):

更改自:

$password_org = random_bytes(70);

$password_org = preg_replace_callback('/[\x00-\x20]/', function($str) {
    return hex2bin(dechex(random_int(33, 255)));
}, random_bytes(70));