使用 PHP 5.5 的 password_hash 和 password_verify 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14992367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:19:41  来源:igfitidea点击:

Using PHP 5.5's password_hash and password_verify function

phpmysqlhashpasswordsphp-password-hash

提问by Doug Smith

Say I wanted to store a password for a user, would this be the right way to do it with PHP 5.5's password_hash()function (or this version for PHP 5.3.7+: https://github.com/ircmaxell/password_compat)?

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

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

Then I would do:

然后我会这样做:

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

To insert into database.

插入到数据库中。

Then to verify:

然后验证:

$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
}

回答by Pete

Ignoring the issues with your database statements for now, I'll answer the question regarding password_hash.

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

In short, no, that is not how you do it. You do not want to store the salt alone, you should be storing both the hash and salt, and then using both to verify the password. password_hashreturns a string containing both.

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

The password_hashfunction returns a string that contains both the hash and the salt. So:

password_hash函数返回一个包含哈希值和盐值的字符串。所以:

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

Then to verify:

然后验证:

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

Additionally, as the comments suggest, if you're interested in security you may want to look at mysqli(ext/mysqlis deprecated in PHP5.5), and also this article on SQL injection: http://php.net/manual/en/security.database.sql-injection.php

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

回答by Machavity

Using your own salt is not recommended and, as of PHP 7, its use is deprecated. To understand why, the author of password_hashshared these thoughts (link defunct)

不建议使用您自己的 salt,并且从 PHP 7 开始,不推荐使用它。为了理解原因,作者password_hash分享了这些想法(链接已失效)

One thing has become abundantly clear to me: the salt option is dangerous. I've yet to see a single usage of the salt option that has been even decent. Every usage ranges from bad (passing mt_rand() output) to dangerous (static strings) to insane (passing the password as its own salt).

I've come to the conclusion that I don't think we should allow users to specify the salt.

我已经非常清楚一件事:盐的选择是危险的。我还没有看到过一次使用salt 选项的效果还不错。每个用法范围从坏(传递 mt_rand() 输出)到危险(静态字符串)到疯狂(将密码作为自己的盐传递)。

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

He even made this comment in SO chatnoting how bad passing your own salt can be

他甚至在 SO chat 中发表了这个评论,指出传递自己的盐有多糟糕

回答by Spooky

Note this from php.net

请注意来自 php.net 的这一点

Warning

The salt option has been deprecated as of PHP 7.0.0. It is now preferred to simply use the salt that is generated by default.

警告

从 PHP 7.0.0 开始,salt 选项已被弃用。现在更喜欢简单地使用默认生成的盐。

Conclusion? Forget about salt option.

结论?忘记盐选项。

This would be quite enough password_hash('password', PASSWORD_DEFAULT)*(or _BCRYPT)

这已经足够了password_hash('password', PASSWORD_DEFAULT)*(或 _BCRYPT)

回答by Adam

You should not enter own salt, leave salt empty, function will generate good random salt.

你不应该输入自己的盐,把盐留空,函数会生成好的随机盐。

Insert into database (or file or whatever you use) whole the string returned by the function. it contains: id of algorithm, cost, salt (22 chars) and hash password.

将函数返回的整个字符串插入到数据库(或文件或您使用的任何东西)中。它包含:算法的 id、成本、salt(22 个字符)和哈希密码。

The entire string is required to use password_verify (). Salt is random and does not harm to fall into the wrong hands (with hashed password). This prevents (or very difficult) to use ready sets generated lists of passwords and hashes - rainbow tables.

使用password_verify() 需要整个字符串。Salt 是随机的,落入坏人手中不会造成伤害(使用散列密码)。这可以防止(或非常困难)使用现成的密码和哈希列表生成列表 - 彩虹表。

You should consider add cost parameter. Default (if omitted) is 10- if higher then function compute hash longer. Increasing the cost by 1, double time needed to generate a hash (and thus lengthen the time it takes to break password)

您应该考虑添加成本参数。默认(如果省略)为 10- 如果更高,则函数计算哈希更长。将成本增加 1,生成哈希所需的时间加倍(从而延长破解密码所需的时间)

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

you should set this parameter based on speed check on your server. It is recommended that the function performed 100ms+ (some prefer to make it 250 ms). Usually cost = 10 or 11 is a good choice (in 2015).

您应该根据服务器上的速度检查设置此参数。建议函数执行 100 毫秒+(有些人更喜欢将其设为 250 毫秒)。通常 cost = 10 或 11 是一个不错的选择(2015 年)。

To increase security, you might want to add to passwords a long (50-60 characters is good choice) secret string. before you use password_hash() or password_verify().

为了提高安全性,您可能希望在密码中添加一个很长的(50-60 个字符是不错的选择)秘密字符串。在使用 password_hash() 或 password_verify() 之前。

$secret_string = 'asCaahC72D2bywdu@#$@#4';
$password  = trim($_POST['user_password']) . $secret_string;
// here use password_* function

Caution Using the PASSWORD_BCRYPT for the algo parameter, will result in the password parameter being truncated to a maximum length of 72 characters.

注意 将 PASSWORD_BCRYPT 用于 algo 参数,将导致密码参数被截断为 72 个字符的最大长度。

If $password will be longer than 72 chars and you change or add 73 or 90 characters hash will not change. Optional, sticking $secret_string should be at the end (after the user's password and not before).

如果 $password 将超过 72 个字符并且您更改或添加 73 或 90 个字符,则哈希不会更改。可选,粘贴 $secret_string 应该在最后(在用户密码之后而不是之前)。