【问题标题】:PHP Blowfish crypt returning different hashPHP Blowfish crypt 返回不同的哈希值
【发布时间】:2015-11-14 10:11:20
【问题描述】:

我对下面的代码有疑问。它是从here 中提取的,并稍作修改以包含验证,并在提交适当的表单并通过验证时触发。问题在于密码的散列。

哈希密码与数据库中的密码不匹配,即使密码本身和 salt 相同。我检查了 $hashed_pa​​ssword 变量与写入数据库的内容。他们完美匹配。在登录端,salt匹配,但是当使用相同的密码时,salt后面的部分不一样?结果如下所示:

$2a$05$Bj79bEbmWG9GeMbBAIXID.zMtNecb3B5qWkiGZrSccWcefQG7IXUy $2a$05$Bj79bEbmWG9GeMbBAIXID.6qNLDcZ21XAKoSOIriqTxlAUjjTygoy

您的用户名或密码有问题。

除非我遗漏了一些明显的东西,否则我唯一能想到的是在注册时使用了与登录不同的算法,但我不确定如何确认或更正。非常感谢任何帮助。

<?php

$password = mysql_real_escape_string($_POST['password']);
$username = mysql_real_escape_string($_POST['username']);

//This string tells crypt to use blowfish for 5 rounds.
$Blowfish_Pre = '$2a$05$';
$Blowfish_End = '$';

// // PHP code you need to register a user
if($_SERVER['REQUEST_METHOD'] == "POST" && isset($_POST['register'])) {
    global $valid;
    user_reg_validate($con, $_POST['username'], $_POST['email'], $_POST['password'], $_POST    ['password2']);
    if ($valid != false) {
        // Blowfish accepts these characters for salts.
        $Allowed_Chars =     'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
        $Chars_Len = 63;

        // 18 would be secure as well.
        $Salt_Length = 21;
        $mysql_date = date( 'Y-m-d' );

        $salt = "";
        for($i=0; $i<$Salt_Length; $i++) {
            $salt .= $Allowed_Chars[mt_rand(0,$Chars_Len)];
        }

        $bcrypt_salt = $Blowfish_Pre . $salt . $Blowfish_End;
        $hashed_password = crypt($password, $bcrypt_salt);

        $sql = "INSERT INTO login (username, salt, password) VALUES ('$username', '$salt', '$hashed_password')";
        mysqli_query($con, $sql) or die( mysql_error() );
    }
}

if($_SERVER['REQUEST_METHOD'] == "POST" && isset($_POST['login'])) {
    global $valid;
    user_login_validate($con, $_POST['username'], $_POST['password']);
    if($valid != false) {
        // Now to verify a user’s password
        $sql = "SELECT salt, password FROM login WHERE username='$username'";
        $result = mysqli_query($con, $sql) or die( mysql_error() );
        $row = mysqli_fetch_assoc($result);
        $hashed_pass = crypt($password, $Blowfish_Pre . $row['salt'] . $Blowfish_End);
        echo $hashed_pass . "</br>";
        echo $row['password'] . "</br>";
        if ($hashed_pass == $row['password']) {
            echo 'Password verified!';
        } else {
            echo 'There was a problem with your user name or password.';
        }
    }
}
?>

【问题讨论】:

  • 您的盐和方法似乎正确,您能验证密码是否匹配吗?我还想指出,您的盐生成在密码学上并不强,请使用 openssl_random_pseudo_bytes 或 mcrypt_create_iv
  • @Halcyon 让我走上了正确的道路。我最终在我的表单中有一个错误标记的字段,我不得不对验证功能进行一些更改以反映这一点。它正在工作。我要去研究你提到的盐发生器。谢谢!

标签: php hash passwords blowfish crypt


【解决方案1】:

您可以免费使用,只需使用功能password_hash()。此函数将生成一个加密安全的盐并将其作为散列值的一部分,因此不需要单独的数据库字段。它还使用$2y 签名并为成本参数添加合理的默认值(5 非常低)。

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

// 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);

另外请注意,您的代码不受 SQL 注入保护。尽快切换到准备好的语句,编写代码将比构建查询更容易,并且 MYSQLI 和 PDO 都支持它。这个answer 可以给你一个开始。

【讨论】:

  • 是的,很好的建议!不幸的是,我仍然回到 PHP 5.3,而且我认为直到 5.5 才支持它。我需要升级,但我不确定它是否会在 apache 2.2 上运行。所有这些都在 wamp 上,所以我可能应该更新整个事情。关于prepared statements,我看到的所有示例都涉及我理解的oop,但尚未在项目中实现。我还在学习...
  • @user2530671 - 没问题,对于 PHP 5.3.7 及更高版本,存在一个 compatibility pack,来自创建 password_hash() 函数的同一作者。对于 5.3.7 之前的 PHP 版本,不支持 crypt() 和 2y,即 unicode 安全的 BCrypt 算法。可以将其替换为 2a,这是早期 PHP 版本的最佳替代方案。
猜你喜欢
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
  • 2020-06-01
  • 1970-01-01
  • 2011-01-14
  • 2012-08-13
  • 1970-01-01
  • 2013-10-18
相关资源
最近更新 更多