比较PHP中密码的哈希值

时间:2014-02-16 22:41:12

标签: php mysql hash password-encryption

作为学习php的一部分,我想尝试一个注册和登录页面,但是,我正在关注如何存储密码的site使用MySQLI而我没有使用它:

哈希密码

$password1 = 'hello123';
// A higher "cost" is more secure but consumes more processing power
$cost = 10;

// Create a random salt
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');

// Prefix information about the hash so PHP knows how to verify it later.
// "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter.
$salt = sprintf("$2a$%02d$", $cost) . $salt;

// Value:
// $2a$10$eImiTXuWVxfM37uY4JANjQ==

// Hash the password with the salt
$hash = crypt($password1, $salt);

我坚持要检索密码,但这是网站的代码:

$username = 'Admin';
$password = 'gf45_gdf#4hg';

$sth = $dbh->prepare('
  SELECT
    hash
  FROM users
  WHERE
    username = :username
  LIMIT 1
  ');

$sth->bindParam(':username', $username);

$sth->execute();

$user = $sth->fetch(PDO::FETCH_OBJ);

// Hashing the password with its hash as the salt returns the same hash
if ( crypt($password, $user->hash) === $user->hash ) {
  // Ok!
}

从我所看到的,他在数据库中获取用户密码的哈希值,并将使用哈希和检查传递的密码与数据库中的密码进行比较。

我一直在尝试这个,但结果哈希与原始哈希不一样:

$pwdtocheck = 'hello123';

// no call do DB yet, doing this on the same page after hashing, the $hash is the same as above
$pwdhash = crypt($pwdtocheck, $hash);

// if I echo $pwdhash it's never exactly the same as the $hash.
if ( $pwdhash === $hash) {
  echo "same pwd";
}

3 个答案:

答案 0 :(得分:2)

我无法在代码中看到实际问题,也许您的数据库字段小于60个字符,或者您正在比较不同的密码。在每种情况下,都有一种更简单,更安全的哈希密码方法,只需使用新功能password_hash()password_verify()。早期的PHP版本也存在compatibility pack

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

答案 1 :(得分:1)

编辑:

我现在看到,当您比较密码时, 使用盐。在你的行中:

$pwdhash = crypt($pwdtocheck, $hash);

$hash变量之前加上了盐,因为crypt()会自动为您执行此操作。 crypt()将从$hash中提取盐,因为它根据所使用的算法知道盐的预期长度。 See the documentation

我将在下面保留我原来的答案,以及那些寻找类似答案的人。

结束编辑

密码对您来说并不相同,因为当您最初散列密码以放入数据库时​​使用salt,但是在检查数据库时您没有使用密码。

保存密码时应使用相同的salt字符串,就像在登录时检查用户密码一样。通常,您将为每个密码随机生成salt字符串(正如您所做的那样),然后将salt字符串与散列密码(在同一列或其自己的列中)一起保存到数据库中,以便您可以使用相同的在登录时检查用户密码的盐。

请参阅https://crackstation.net/hashing-security.htm#salt以供参考。

答案 2 :(得分:0)

我无法访问您引用的文章,但我想:

你需要检查使用salt作为salt而不是hash。

crypt($pwdtocheck, $user->salt) == $user->hash

应该有效