使用 PHP 5.5 的password_hash和password_verify功能

2022-08-30 13:52:15

假设我想为用户存储密码,这是否是使用PHP 5.5的功能(或PHP 5.3.7 +的此版本:https://github.com/ircmaxell/password_compat)执行此操作的正确方法?password_hash()

$options = array("cost" => 10, "salt" => uniqid());
$hash = password_hash($password, PASSWORD_BCRYPT, $options);

然后我会做:

mysql_query("INSERT INTO users(username,password, salt) VALUES($username, $hash, " . $options['salt']);

插入到数据库中。

然后验证:

$row = mysql_fetch_assoc(mysql_query("SELECT salt FROM users WHERE id=$userid"));
$salt = $row["salt"];
$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10, "salt" => $salt));

if (password_verify($password, $hash) {
    // Verified
}

答案 1

暂时忽略数据库语句的问题,我将回答有关 .password_hash

简而言之,不,这不是你如何做到的。您不想单独存储盐,您应该同时存储哈希和盐,然后使用两者来验证密码。 返回一个同时包含两者的字符串。password_hash

该函数返回一个同时包含哈希和 salt 的字符串。所以:password_hash

$hashAndSalt = password_hash($password, PASSWORD_BCRYPT);
// Insert $hashAndSalt into database against user

然后验证:

// Fetch hash+salt from database, place in $hashAndSalt variable
// and then to verify $password:
if (password_verify($password, $hashAndSalt)) {
   // Verified
}

此外,正如评论所建议的那样,如果您对安全性感兴趣,则可能需要查看(在PHP5.5中已弃用),以及有关SQL注入的这篇文章:http://php.net/manual/en/security.database.sql-injection.phpmysqliext/mysql


答案 2

不建议使用自己的盐,从 PHP 7 开始,它的使用已被弃用。为了理解为什么,作者分享了这些想法(链接已失效)password_hash

有一件事对我来说已经变得非常清楚:盐的选择是危险的。我还没有看到盐选项的单一用法甚至不错。每种用法的范围从坏的(传递mt_rand()输出)到危险的(静态字符串)到疯狂的(将密码作为自己的盐传递)。

我得出的结论是,我认为我们不应该允许用户指定盐。

他甚至在SO聊天中发表了这条评论,指出通过自己的盐是多么糟糕。


推荐