Сравнение хэш-значения пароля в PHP

Как часть изучения php, я хотел попробовать зарегистрироваться на странице регистрации, однако сайт, за которым я следую за тем, как хранить пароль, использует 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!
}

Из того, что я вижу, он захватывает хэш-значение пароля для пользователя в БД и сравнивает пароль, который был передан с помощью хэша, и проверяет его с помощью БД.

Я пробовал это, но результат hash никогда не совпадает с исходным:

$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 never exactly the same as the $hash.
if ( $pwdhash === $hash) {
  echo "same pwd";
}
+1
источник поделиться
3 ответа

РЕДАКТИРОВАТЬ:

Теперь я вижу, что вы используете соль, когда сравниваете пароли. В вашей строке:

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

переменная $hash имеет добавленную соль, потому что crypt() автоматически сделает это для вас. crypt() будет извлекать соль из $hash потому что он знает ожидаемую длину соли на основе используемого алгоритма. См. Документацию.

Я сохраню свой первоначальный ответ ниже для контекста и для тех, кто ищет аналогичный ответ.

END EDIT

Пароль для вас не то же самое, потому что вы используете salt когда вы первоначально вводили пароль для ввода в свою базу данных, но вы не засовываете пароль позже, когда вы проверяете базу данных.

При сохранении пароля вы должны использовать ту же самую сольную строку, как при проверке пароля пользователя при входе в систему. Обычно вы произвольно генерируете строку соля для каждого пароля (как вы это делаете), а затем сохраняете строку солей в базе данных вместе с хешированным паролем (либо в том же столбце, либо в его собственном столбце), чтобы вы могли использовать тот же самый соль, чтобы проверить пароль пользователя при входе в систему.

См. Https://crackstation.net/hashing-security.htm#salt для справки.

+1
источник

Я не вижу реальной проблемы в вашем коде, возможно, поле вашей базы данных меньше 60 символов, или вы сравниваете разные пароли. В каждом случае проще и безопаснее использовать хэш-пароли, просто используйте новые функции password_hash() и password_verify(). Существует также пакет совместимости для более ранних версий 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);
+2
источник

Я не могу получить доступ к статье, на которую вы ссылаетесь, но я полагаю:

Вам нужно проверить соль, а не хеш.

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

должно сработать

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос