打开'portable_hashes'。 我注意到无论出于何种原因,它产生的哈希值并不总是相同 - 但是当通过'CheckPassword'传递时总是返回有效值。我也注意到'PHP_VERSION'用于生成哈希 - 这两个结合起来让我担心......便携式是多么便携?我可以在服务器,Linux,Windows,64位,32位等之间移动哈希值(保存在用户数据库中) - 并且仍然可以验证它们吗?我需要做些什么来使密码不再验证?
我问的原因是因为我在我的框架中使用phpass作为密码,这将为我的几个网站提供支持,其中许多网站目前拥有数千名用户 - 而且有些情况我不得不移动它们到不同的服务器,当然升级PHP。我也可以将其中的一个或两个从Apache切换到lighthttpd或类似的东西。毋庸置疑,我非常偏执,有一天我会有一个支持噩梦,除了通过电子邮件向每个人发送新密码之外,我无法以任何其他方式修复它(这听起来真的不安全)。
如果密码有可能变得无效 - 我需要采取哪些步骤来制作自己的密码哈希生成器?我已经使用了16字节的随机盐(每用户),除此之外唯一的另一个问题就是拉伸 - 对吗?
答案 0 :(得分:8)
根据PHP版本的不同,您不需要打开便携式哈希。在PHP 5.3及更高版本上,如果系统上没有它,PHP会提供自己的bcrypt实现。 如果所有服务器都具有PHP 5.3及更高版本,我强烈建议关闭便携式哈希。 PHPass“portables hashes”存在,因为根据安装的PHP版本,bcrypt可能不可用。
也就是说,PHPass可移植哈希确实将盐存储在哈希中。这就是为什么每次使用相同密码的运行都不同。
此外,PHPass在生成这些哈希 * 期间使用PHP_VERSION
来检查该版本可用的md5()
函数是否支持$rawMode
参数。如果没有,pack()
用于将十六进制数据转换为二进制(请注意,这比使用$rawMode
慢得多,这就是分支的原因)。
同样,如果所有服务器都运行PHP 5.3及更高版本,我强烈建议关闭便携模式,让PHPass使用bcrypt
。由于PHP 5.3+在系统不可用时提供了自己的实现,因此可以跨操作系统检查哈希值。即使您关闭便携模式,PHPass仍然足够智能,以正确的方式检查您的旧哈希。
我和你一样,在我的框架中跨多个站点使用PHPass。由于我关闭了便携模式,我设置了登录脚本以逐步重新哈希在登录时不使用bcrypt的密码。
*第131行
编辑:有关更多说明,请参阅生成便携式模式中的哈希(简化,不使用PHPass中的实际变量,但准确)。请注意,PHPass使用自己的base64编码版本。
$final = '$P$'
$final .= encode64_int($rounds)
(来自构造函数,PHP 5+上的最小值为5,其他3个)
$final .= genSalt()
(Salt为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
答案 1 :(得分:1)
我可以看到PHP_VERSION
的唯一用途就在这一行:
$output .= $this->itoa64[min($this->iteration_count_log2 +
((PHP_VERSION >= '5') ? 5 : 3), 30)];
现在,所有这一切都是确定最大迭代次数。它是gensalt_private
生成盐的方法。所以这只会在存储新密码和生成盐时发生。所以以前生成的所有盐都是100%便携的。所以根本就没有真正的可移植性问题......
就其他人而言,只要您使用的是最新版本的PHP(5.0+),就我所知,您应该没有任何可移植性问题(因为{{1}函数内置)...