便携式(PHPPass)密码哈希.我应该使用它们吗?

2022-01-22 00:00:00 database passwords php phpass

我正在为我的网站安装用户注册脚本 (Tank Auth).

在安装指南中说,

<块引用>

警告:默认情况下,库生成强大的系统特定不可移植的密码哈希.这意味着一旦创建,用户数据库无法转储和导出到另一台服务器.这种行为可以在配置文件中也可以更改.

这让我进退两难.将来我可能想更改服务器,但我也不想要弱密码.便携式密码散列是否存在很大风险?更重要的是,它们所说的哈希是什么意思?是字符长度吗?

解决方案

Task Auth 使用 PHPass 进行密码散列(旧版本,这不是一个好兆头;您可能想要 在您的安装中更新).PHPpass有两种模式,便携和bcrypt.

根据 PHP 版本,您不需要启用可移植哈希.在 PHP 5.3 及更高版本上,如果系统上不可用,PHP 会提供自己的 bcrypt 实现.如果您的所有服务器都安装 PHP 5.3 及更高版本,我强烈建议关闭可移植散列.存在 PHPass可移植散列"是因为,根据安装的 PHP 版本,bcrypt 可能不可用.p>

也就是说,PHPass 可移植哈希确实将盐存储在其哈希中.这就是为什么每次使用相同的密码运行都是不同的.

此外,PHPass 在生成这些哈希时使用 PHP_VERSION* 来检查该版本可用的 md5() 函数是否支持$rawMode 参数.如果没有,pack() 用于将十六进制数据转换为二进制(注意,这比简单地使用 $rawMode 慢得多,这就是分支的原因已制成).

再次,如果您的所有服务器都运行 PHP 5.3 及更高版本,我强烈建议关闭便携模式并让 PHPass 使用 bcrypt 代替.由于 PHP 5.3+ 在系统不可用时提供了自己的实现,因此您的哈希将可以跨操作系统检查.即使您确实关闭了便携模式,PHPass 仍然会足够聪明地以正确的方式检查您的旧哈希.

* 131 行

<小时>

更多解释,这里是在可移植模式下如何生成哈希(简化,不使用 PHPass 中的实际变量,但准确).请注意,PHPPass 使用自己的 base64 编码版本.

  1. $final = '$P$'

  2. $final .= encode64_int($rounds)(来自构造函数,在 PHP 5+ 上最少为 5,其他为 3)

  3. $final .= genSalt()(Salt 是 6 个字节...encode64"格式的 8 个字节).

  4. $hash = md5($salt . $password)

  5. 对于 2$rounds 次,执行 $hash = md5($hash . $password)

  6. $final = encode64($hash)

所以最终的哈希基本上是这样的:

$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0\__________/\____________________/ \  实际哈希\ $P$ 9 IQRaTwmf\_/ \______/  \            盐 \  # 轮数(不是十进制表示,9实际上是11)\ 哈希表头

I'm installing a user registration script (Tank Auth) for my website.

In the installation guide its says,

WARNING: By default the library generates strong system-specific password hashes that are not portable. It means that once created, user database cannot be dumped and exported to another server. This behavior can be changed in config-file as well.

This put me in a dilemma. In the future I may want to change servers but I don't want weak passwords either. Are portable password hashes a big risk? And more importantly, what do they mean by hashes? Is it the character length?

解决方案

Task Auth uses PHPass for password hashing (an old version, that's not a good sign; you might want to update that in your install). PHPass has two modes, portable and bcrypt.

Depending on the PHP version, you do not need to have portable hashes on. On PHP 5.3 and above, PHP supplies its own implementation of bcrypt if it isn't available on the system. If all your servers have PHP 5.3 and above, I highly recommend to turn portable hashes off. PHPass "portables hashes" exists because, depending of the version of PHP installed, bcrypt might not be available.

That said, PHPass portable hashes does store the salt in its hash. That's why every run on the same password is different.

Also, PHPass uses PHP_VERSION during the generation of those hashes* to check if the md5() function available with that version supports the $rawMode parameter. If it doesn't, pack() is use to transform the hexadecimal data into binary (note that this is considerably slower then simply using $rawMode, which is why the branch is made).

Again, if all your servers are running PHP 5.3 and above, I highly recommend to turn off portable mode and let PHPass use bcrypt instead. Since PHP 5.3+ provides its own implementation when the system one isn't available, your hash will be checkable across OSes. Even if you do turn off portable mode, PHPass will still be smart enough to check your old hashes the proper way.

* Line 131


EDIT: For more explanation, here is how hashes in portable mode are generated (simplified, does not use actual variables found in PHPass, but accurate). Note that PHPass uses their own version of base64 encoding.

  1. $final = '$P$'

  2. $final .= encode64_int($rounds) (from constructor, minimum is 5 on PHP 5+, 3 other)

  3. $final .= genSalt() (Salt is 6 bytes... 8 bytes in "encode64" format).

  4. $hash = md5($salt . $password)

  5. For 2$rounds times, do $hash = md5($hash . $password)

  6. $final = encode64($hash)

So the final hash essentially is this:

$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0
\__________/\____________________/
                     
                       Actual Hash
    
       $P$   9   IQRaTwmf
        \_/      \______/
                    
                      Salt
                 
                  # Rounds (not decimal representation, 9 is actually 11)
             
               Hash Header

相关文章