PHP中的Django密码


Django password in PHP

我有一个问题,因为我有一个数据库的用户和他们的密码是安全的Django (pbkdf2)。所以'123'看起来像这样:

pbkdf2_sha256$20000$MflWfLXbejfO$tNrjk42YE9ZXkg7IvXY5fikbC+H52Ipd2mf7m0azttk=

现在我需要在PHP项目中使用这些密码,我不知道如何比较它们

pbkdf2_sha256$20000$MflWfLXbejfO$tNrjk42YE9ZXkg7IvXY5fikbC+H52Ipd2mf7m0azttk=

让我们来分析一下。$为分离器:

  • pbkdf2_sh256表示PBKDF2-SHA256,即hash_pbkf2('sha256', ...)
  • 20000为迭代计数
  • MflWfLXbejfO是盐
  • tNrjk42YE9ZXkg7IvXY5fikbC+H52Ipd2mf7m0azttk=可能是哈希值。

这是从PHP验证哈希所需的所有信息。你只需要:

  1. hash_pbkdf2()从用户
  2. 提供的密码生成新的哈希
  3. hash_equals()将生成的散列与存储的散列进行比较

这个函数应该可以工作(PHP 7+):

/**
 * Verify a Django password (PBKDF2-SHA256)
 *
 * @ref http://stackoverflow.com/a/39311299/2224584
 * @param string $password   The password provided by the user
 * @param string $djangoHash The hash stored in the Django app
 * @return bool
 * @throws Exception
 */
function django_password_verify(string $password, string $djangoHash): bool
{
    $pieces = explode('$', $djangoHash);
    if (count($pieces) !== 4) {
        throw new Exception("Illegal hash format");
    }
    list($header, $iter, $salt, $hash) = $pieces;
    // Get the hash algorithm used:
    if (preg_match('#^pbkdf2_([a-z0-9A-Z]+)$#', $header, $m)) {
        $algo = $m[1];
    } else {
        throw new Exception(sprintf("Bad header (%s)", $header));
    }
    if (!in_array($algo, hash_algos())) {
        throw new Exception(sprintf("Illegal hash algorithm (%s)", $algo));
    }
    $calc = hash_pbkdf2(
        $algo,
        $password,
        $salt,
        (int) $iter,
        32,
        true
    );
    return hash_equals($calc, base64_decode($hash));
}

演示:https://3v4l.org/WbTpW

如果你需要旧的PHP 5支持,从函数定义中删除string前缀和: bool将使其在PHP 5.6中工作。我不建议尝试为5.6之前的PHP版本添加向后兼容性;如果你发现自己处于这种情况,你应该更新你的服务器软件。