在 PHP 5.5 中生成密码哈希并设置成本选项

2022-01-22 00:00:00 passwords php php-password-hash bcrypt

我知道 PHP 5.5 处于 alpha 阶段,但我正在制作的这个类只是提前制作,以通过使用 function_exists() 来利用它的散列功能.

I know PHP 5.5 is in alpha but this class I am making is just being made in advance to utilize it's hashing feature by using function_exists().

我查看了 password_hash 文档.第三个参数是 $options,它目前支持两个选项,'salt' 和 'cost'.

I checked out the password_hash documentation. The 3rd argument is for $options which currently supports two options, 'salt' and 'cost'.

它声明如下:

cost,表示应该使用的算法成本.例子这些值可以在 crypt() 页面上找到.

cost, which denotes the algorithmic cost that should be used. Examples of these values can be found on the crypt() page.

当我进入 crypt() 页面时,它给出的文档是:

When I go to the crypt() page the documentation it gives is:

使用盐的 Blowfish 散列如下:$2a$"、$2x$"或$2y$",a两位数的成本参数$"和字母表中的 22 位数字./0-9A-Za-z".在盐中使用超出此范围的字符将导致 crypt() 返回一个长度为零的字符串.两位数的成本参数是迭代次数的以 2 为底的对数底层基于 Blowfish 的散列算法,必须在范围内04-31,超出此范围的值将导致 crypt() 失败.版本5.3.7之前的PHP只支持$2a$"作为salt前缀:PHP 5.3.7引入了新的前缀来修复 Blowfish 的安全漏洞执行.请参阅 » 本文档以获取完整的详细信息安全修复,但总而言之,开发人员只针对 PHP5.3.7 及更高版本应优先使用$2y$"而不是$2a$".

Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 digits from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail. Versions of PHP before 5.3.7 only support "$2a$" as the salt prefix: PHP 5.3.7 introduced the new prefixes to fix a security weakness in the Blowfish implementation. Please refer to » this document for full details of the security fix, but to summarise, developers targeting only PHP 5.3.7 and later should use "$2y$" in preference to "$2a$".

我似乎无法理解这一点.它说 PHP 5.3.7 和更高版本应该使用 $2y$,但是我用什么成本值来获得那个,它是最好的选择吗?他们提供的示例使用了 7 的值,但根据上述它可以上升到 31,使用 say 4 和 say 31 有什么区别?

I can't seem to get my head wrapped around this. It says PHP 5.3.7 and later should use $2y$, but what cost value do I use to get that one and is it the best value to choose? The example they provide uses a value of 7, but according to the above it can go up to 31, what difference does it make to use say 4 opposed to say 31?

推荐答案

函数 password_hash() 只是函数 crypt() 的包装,应该使更容易正确使用它.它负责生成安全的随机盐,并提供良好的默认值.

The function password_hash() is just a wrapper around the function crypt(), and shall make it easier to use it correctly. It takes care of the generation of a safe random salt, and provides good default values.

使用此功能最简单的方法是:

The easiest way to use this function will be:

$hash = password_hash($password, PASSWORD_DEFAULT);

这意味着,该函数将使用 BCrypt(算法 2y)对密码进行哈希处理,生成随机盐,并使用默认成本(目前为 10).这些都是很好的默认值,特别是我会不生成你自己的盐,在那里很容易出错.

That means, the function will hash the password with BCrypt (algorithm 2y), generates a random salt, and uses the default cost (at the moment this is 10). These are good default values, particularly i would not generate the salt of your own, it is easy to make mistakes there.

如果你想改变成本参数,你可以这样做:

Should you want to change the cost parameter, you can do it like that:

$hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 11]);

将cost参数增加1,计算哈希值所需的时间加倍.成本参数是迭代次数的对数(以 2 为底),即:

Increasing the cost parameter by 1, doubles the needed time to calculate the hash value. The cost parameter is the logarithm (base-2) of the iteration count, that means:

$iterations = 2 ^ $cost;

我错过了重点,您想生成自己的课程.对于 PHP 5.3.7 及更高版本,存在 兼容包,来自制作 password_hash() 函数的同一作者.您可以直接使用此代码,也可以查看精心设计的实现.对于 5.3.7 之前的 PHP 版本,不支持 crypt2y,即识别 unicode 的 BCrypt 算法.您可以改为使用 2a,这是早期 PHP 版本的最佳替代方案.我做了一个 example 有很多评论,也许你想要一个也看看吧.

I missed the point, that you want to generate your own class. For PHP version 5.3.7 and later, there exists a compatibility pack, from the same author that made the password_hash() function. You can either use this code directly, or look at the well crafted implementation. For PHP versions before 5.3.7 there is no support for crypt with 2y, the unicode aware BCrypt algorithm. You can instead use 2a, which is the best alternative for earlier PHP versions. I did an example with a lot of comments, maybe you want to have a look at it too.

附:password_hash() 中正确使用了表达式salt"和cost factor",但 crypt() 函数将 salt 这个词用于所有 crypt 参数,这有点误导.

P.S. The expressions "salt" and "cost factor" are used correctly in password_hash(), the crypt() function though, uses the word salt for all crypt parameters together, that's a bit misleading.

相关文章