0

我正在使用本教程来帮助我在创建帐户时对用户密码进行加盐和哈希处理,然后在用户输入密码登录时将这些密码带回并进行比较。

在这篇文章中,他们有两个我想调用的函数。

create_hash()

validate_hash()

随后,我自己创建了另一个函数来分解结果,这样我就可以从整个函数中去掉加盐的字符串。

function explode_hash($password) {
    return substr( $password, strrpos( $password, ':' ) + 1);
} 

所以当我在数据库中插入数据时,它看起来像这样

INSERT INTO `users` (`id`, `email`, `passwd`, `passwdhash`)
VALUES
(1,'email@email.com','sha256:1000:mvhkKCAoLgCHb2/Ie0muPIRH0YISriOr:+Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS','+Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS'); 

请注意,最后一列包含第三列中字符串的最后一部分。

所以最后一步是登录时用户将输入他们的电子邮件和密码,我的系统将从数据库中获取哈希(基于电子邮件)并通过名为的函数运行它

validate_hash()

但结果总是错误的。

有人会花几分钟时间查看这些步骤并尝试了解我无法进行正确比较的原因吗?

4

4 回答 4

4

PHP 5.5 将有自己的函数password_hash()和 password_verify() 准备好,以简化生成 BCrypt 哈希。它们的工作方式与您提出的功能非常相似。我建议使用这个优秀的 api,或者它是早期 PHP 版本的兼容包。用法非常简单:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

正如您已经看到的,盐包含在生成的哈希值中,可以从那里提取以验证密码。上面的函数会自动从哈希值中提取这些信息(盐和成本因子),不需要单独存储盐。

于 2013-06-20T10:45:24.420 回答
2

我快速浏览了您发布的教程。用法应该非常简单。你不应该需要做任何爆炸或任何事情:

  1. 将您从用户那里获得的密码放入 create_hash($password) 并将该函数的结果存储在您的数据库中。没有爆炸,什么都没有。
  2. 当用户没有登录并为您提供密码时,只需调用 validate_password($user_password, $password_from_database) 如果函数返回 true 则让用户进入,否则拒绝进入。

这些函数为你完成了所有的分裂和爆炸,你不需要关心这些。

于 2013-06-20T13:38:12.320 回答
2

我不知道您的问题到底是什么,但是如果您想分解并验证哈希,这非常简单。

$str = 'sha256:1000:mvhkKCAoLgCHb2/Ie0muPIRH0YISriOr:+Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS'; //str from database
$params = explode(':', $str);
print_r($params);

它会打印

 Array ( [0] => sha256 [1] => 1000 [2] => mvhkKCAoLgCHb2/Ie0muPIRH0YISriOr [3] => +Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS )

现在您可以检查 $params[1] 以获取算法和其他参数以获取正确的值并使用正确的散列函数。

用盐散列看起来像

hash_function('string_to_be_hashed' + 'unique random salt');

我不知道为什么你的 mysql 查询中有 2 个哈希而不是一个。如果您希望哈希被加盐,函数应该返回 1 个哈希而不是 2。

于 2013-06-20T10:45:23.530 回答
-1

编辑:不要使用这种功能,评论中的解释

我会留下这个答案,因为我已经看过很多这种方法的例子,但从未见过解释为什么这是错误的方法。感谢 ircmaxell 指出这一点

原帖

我目前使用这些函数来散列和检查我的密码

function createPassHash($uname, $pass){
    $salt = hash('sha256', uniqid(mt_rand(), true) . 'yourPersonalStringHere' . strtolower($uname));
    $hash = $salt . $pass;
    for ( $i = 0; $i < 100000; $i ++ ) {
        $hash = hash('sha256', $hash);
    }
    $hash = $salt . $hash;  
    return $hash;
}
function checkPassHash($input, $stored){
    $salt = substr($stored, 0, 64);
    $hash = $salt . $input;
    for ( $i = 0; $i < 100000; $i ++ ) {
        $hash = hash('sha256', $hash);
    }
    $hash = $salt . $hash;
    if ( $hash == $stored ) {
        return true;
    }
    else{
        return false;
    }
}

这通过使用随机数、秘密字符串和作为盐一起散列的用户名来增加额外的熵。还建议盐至少与哈希一样长,这也可以确保。

于 2013-06-20T11:07:23.130 回答