在几台服务器之间使用phpass有多安全?

时间:2011-01-25 01:36:06

标签: php security authentication hash phpass

打开'portable_hashes'。 我注意到无论出于何种原因,它产生的哈希值并不总是相同 - 但是当通过'CheckPassword'传递时总是返回有效值。我也注意到'PHP_VERSION'用于生成哈希 - 这两个结合起来让我担心......便携式是多么便携?我可以在服务器,Linux,Windows,64位,32位等之间移动哈希值(保存在用户数据库中) - 并且仍然可以验证它们吗?我需要做些什么来使密码不再验证?

我问的原因是因为我在我的框架中使用phpass作为密码,这将为我的几个网站提供支持,其中许多网站目前拥有数千名用户 - 而且有些情况我不得不移动它们到不同的服务器,当然升级PHP。我也可以将其中的一个或两个从Apache切换到lighthttpd或类似的东西。毋庸置疑,我非常偏执,有一天我会有一个支持噩梦,除了通过电子邮件向每个人发送新密码之外,我无法以任何其他方式修复它(这听起来真的不安全)。

如果密码有可能变得无效 - 我需要采取哪些步骤来制作自己的密码哈希生成器?我已经使用了16字节的随机盐(每用户),除此之外唯一的另一个问题就是拉伸 - 对吗?

2 个答案:

答案 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编码版本。

  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)

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

    $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}函数内置)...