为什么PHP crypt()函数为两个不同的字符串返回相同的东西?

时间:2014-01-02 03:05:37

标签: php mysql password-protection

我正在使用PHP的crypt函数进行密码哈希/加密,但我不认为我做得对,因为“nathan12”和“nathan123”都允许我在我的系统上登录我的帐户(实际密码为“nathan123”,因此“nathan12”或其他任何内容应允许我登录)。

以下是我的系统在用户注册时所执行的操作:

[...]

$salt = uniqid(mt_rand(), true);
$password = crypt($password, $salt); // '$password' is the inputted password

$insertUserStmt = $mysqli->prepare("INSERT INTO users (name, 
username, 
password, 
password_salt, 
email, 
created) VALUES (?, ?, ?, ?, ?, ?)");

$insertUserStmt->bind_param("sssssi", $name, $username, $password, $salt, $email, time());

$insertUserStmt->execute();

[...]

它将散列/加密密码($password)与$salt一起插入数据库。

当有人尝试登录时,会执行以下操作以检查用户是否输入了他们输入的用户名的正确密码:

[...]

// $password_salt is from DB; $password is inputted password
$password_crypt = crypt($password, $password_salt); 

// $login_password is from DB
if($password_crypt == $login_password) { 

[...]

我可能没有正确使用crypt函数,但根据PHP文档,第一个参数是字符串(密码),第二个是盐。

3 个答案:

答案 0 :(得分:4)

  

标准的基于DES的crypt() [...]仅使用str的前八个字符,因此以相同的八个字符开头的较长字符串将生成相同的结果(当相同时)使用盐)。

source

使用以$<algo>$开头的salt来使用DES之外的其他内容。有关详细信息,请参阅crypt()文档。

答案 1 :(得分:2)

你应该使用password_hash()而不是crypt,原因你提到:“我可能甚至没有正确使用crypt功能”。你说你从DB那里得到了盐...这听起来不安全。使用password_hash(),您可以让PHP以安全的方式为您处理salting。

有关优势原因的详细信息: http://www.sitepoint.com/hashing-passwords-php-5-5-password-hashing-api/

答案 2 :(得分:2)

您应该使用密码盐来加密密码。

您可以在配置文件中存储随机字符串。

$config['passwordKey'] = 'asjdfa783#H$Khjsdfhas78a734J%JSDGK2348235hxmfdA';

加密时将其附加到$salt。这样,如果数据库遭到入侵,而您的文件系统没有受到攻击,则攻击者无法解密您的数据库密码哈希值。这对于使用相同的登录信息保护其他站点上的用户信息至关重要。


要对密码进行哈希处理,password_hash是一个专门用于密码哈希的简单crypt()包装器! (source

$password = password_hash($password, PASSWORD_BCRYPT, array(
    'cost' => 60,
    'salt' => $salt . $config['passwordKey']
));