使用 salt 进行 PHP/MYSQLi 密码验证的问题


Issue with PHP/MYSQLi Password validation using salt

我在获取存储在 mysql 中的密码以匹配使用 salt 的登录密码时遇到问题。

这是我创建密码的代码:

        $hash = hash('sha256', $password);
        function createSalt()
        {
        $text = md5(uniqid(rand(), true));
            return substr($text, 0, 3);
        }
        $salt = createSalt();
        $password = hash('sha256', $salt . $hash);

这是我登录页面中的代码:

        $userData = $result->fetch_array(MYSQL_ASSOC);
        $hash = hash('sha256', $password);
        $password = hash('sha256', $userData['salt'] . $hash);
        //$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) ); 
        if($password != $userData['Password']) // Incorrect password. So, redirect to login_form again.

在 mysql 中创建密码时没有错误(该字段填充为 即 0d02a88c1e1057a64df6b3fed4c6ad64e228313b803e9f9b36...

登录名创建类似以下内容:51839f9a15dac1f26825f4cd5d2ecf7ae83ea88d440415b04fb6ae41c3a0566f

只是不确定问题出在哪里。提前感谢,我对PHP很陌生。

首先,这里有一些令人困惑的变量命名 - 你用$password来表示明文密码和盐和散列表示。这使得阅读代码变得更加困难。

其次,让我们将您的代码视为一系列状态,以找出它们可能出错的地方:

  1. 密码输入。在这两种情况下传递相同的字符串吗?您是否注意空格和大写?使用调试器进行验证。如果明文密码不是逐字节相同的,则初始 sha256 哈希此时应显示差异。
  2. 盐的生成/回收。您是否逐字节保存/检索了完全相同的盐?同样,注意空格/大写,并检查数据库是否未静默截断或更改字符串的编码。
  3. 在字符串连接
  4. 之后但在第二个 sha256 哈希操作之前比较字符串。根据定义,由于最终输出不同,因此您的明文密码或盐不是逐字节相同的。这将帮助您判断其中一个还是两个都是罪魁祸首。

使用函数 password_hash() 让您的生活更轻松,更安全地存储您的密码。

SHA-* 算法不适合散列密码,因为它们太快了。函数 password_hash() 不仅会计算出更适合的 BCrypt 哈希,还会负责生成安全盐,并且您不必在单独的数据库字段中存储/检索盐(它将成为结果哈希值的一部分)。

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