PHP .crypt() 对于不同的字符串和盐,结果相同


PHP .crypt() results identical for different strings and salts

因为我使用的是旧版本的PHP,所以我必须使用.crypt()。我正在测试一些密码验证,服务器正在验证错误的密码是否正确。然后我决定进行最基本的测试,但我仍然有这个问题:

<?php
echo crypt("cryptcryptcrypt","salt");
echo "<br>";
echo crypt("cryptcryptcrypta","salta");
?>

– 结果是:

saRyxun8Pn/K6
saRyxun8Pn/K6

为什么会这样?


出于测试目的,我正在使用PhpFiddle,所以您可能会在回答时发现这很有用...

引用

文档:

基于 DES 的标准 crypt() 返回 salt 作为输出的前两个字符。它也只使用 str 的前八个字符,因此以相同的八个字符开头的较长字符串将生成相同的结果(当使用相同的盐时)。

您提供的盐只有 4 或 5 个字符长,这使得 crypt 使用基于 DES 的标准算法。因此,仅使用密码的前 9 个字符,并且仅使用盐的前两个字符。因此,您的哈希值是相等的。你真的应该更新你的PHP版本,这样你就可以使用现代的password_hash函数。如果无法做到这一点,请尝试使用与 PHP 版本 3 及更高版本兼容的 http://www.openwall.com/phpass/。如果这是不可能的,请继续阅读...

您需要以正确的格式将盐传递给 crypt 函数。从文档中的示例来看:

if (CRYPT_BLOWFISH == 1) {
    echo 'Blowfish:     ' . crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$') . "'n";
}
if (CRYPT_SHA256 == 1) {
    echo 'SHA-256:      ' . crypt('rasmuslerdorf', '$5$rounds=5000$usesomesillystringforsalt$') . "'n";
}
if (CRYPT_SHA512 == 1) {
    echo 'SHA-512:      ' . crypt('rasmuslerdorf', '$6$rounds=5000$usesomesillystringforsalt$') . "'n";
}

哈希的开头定义要使用的算法。您还需要确保为每个用户使用随机的唯一盐。