根据 PHP 版本,您不需要启用可移植哈希。在 PHP 5.3 及更高版本上,如果系统上不可用,PHP 会提供自己的 bcrypt 实现。如果你所有的服务器都有 PHP 5.3 及更高版本,我强烈建议关闭便携式哈希。PHPass“便携式哈希”之所以存在,是因为根据安装的 PHP 版本,bcrypt 可能不可用。
也就是说,PHPass 可移植哈希确实将盐存储在其哈希中。这就是为什么每次使用相同的密码运行都是不同的。
此外,PHPassPHP_VERSION
在生成这些哈希时使用*来检查md5()
该版本可用的函数是否支持该$rawMode
参数。如果没有,pack()
则用于将十六进制数据转换为二进制(请注意,这比简单地使用要慢得多$rawMode
,这就是创建分支的原因)。
同样,如果您的所有服务器都运行 PHP 5.3 及更高版本,我强烈建议关闭便携模式并让 PHPass 使用bcrypt
。由于 PHP 5.3+ 在系统不可用时提供了自己的实现,因此您的哈希将可以跨操作系统检查。即使您确实关闭了便携模式,PHPass 仍然会足够聪明地以正确的方式检查您的旧哈希值。
我和你的情况一样,在我的框架中跨多个站点使用 PHPass。由于我关闭了便携模式,我已将我的登录脚本设置为逐步重新散列未在登录时使用 bcrypt 的密码。
* 第 131 行
编辑:更多解释,这里是如何生成可移植模式的哈希(简化,不使用 PHPass 中的实际变量,但准确)。请注意,PHPPass 使用他们自己的 base64 编码版本。
$final = '$P$'
$final .= encode64_int($rounds)
(来自构造函数,PHP 5+ 上的最小值为 5,其他为 3)
$final .= genSalt()
(盐是 6 个字节......“encode64”格式的 8 个字节)。
$hash = md5($salt . $password)
2
$rounds
有时,做$hash = md5($hash . $password)
$final = encode64($hash)
所以最终的哈希基本上是这样的:
$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0
\__________/\____________________/
\ \
\ \ Actual Hash
\
\ $P$ 9 IQRaTwmf
\_/ \ \______/
\ \ \
\ \ \ Salt
\ \
\ \ # Rounds (not decimal representation, 9 is actually 11)
\
\ Hash Header