password_verify php not match
Asked Answered
S

1

2

I try to check the password with the function password_verify with the posted user password and the hash from database.

First, how I generate the password and hash:

$user_password = $this->generate_password();

private function generate_password($length = 8)
{
 $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?";
 $password = substr( str_shuffle( $chars ), 0, $length );
 return $password;
}

define("HASH_COST_FACTOR", "10");
$hash_cost_factor = (defined('HASH_COST_FACTOR') ? HASH_COST_FACTOR : null);
$user_password_hash = password_hash($user_password, PASSWORD_DEFAULT, array('cost' => $hash_cost_factor));


$sql = "INSERT INTO users (user_name, user_password_hash, user_email, user_creation_timestamp)
VALUES (:user_name, :user_password_hash, :user_email, :user_creation_timestamp)";
$query = $this->db->prepare($sql);
$query->execute(array(':user_name' => $user_name,
                      ':user_password_hash' => $user_password_hash,
                      ':user_email' => $user_email,
                      ':user_creation_timestamp' => $user_creation_timestamp));
$count =  $query->rowCount();
if ($count != 1) {
   $_SESSION["feedback_negative"][] = FEEDBACK_ACCOUNT_CREATION_FAILED;
 return false;
}

  if ($this->sendUserpassword($user_email, $user_password)) {
      $_SESSION["feedback_positive"][] = FEEDBACK_ACCOUNT_SUCCESSFULLY_CREATED;
      return true;
  } else {
      $query = $this->db->prepare("DELETE FROM users WHERE user_id = :last_inserted_id");
      $query->execute(array(':last_inserted_id' => $user_id));
      $_SESSION["feedback_negative"][] = FEEDBACK_PASSWORD_MAIL_SENDING_FAILED;
      return false;
  }
private function sendUserpassword($user_email, $user_password)
{
  $mail = new PHPMailer;

  if (EMAIL_USE_SMTP) {
      $mail->IsSMTP();
      $mail->SMTPDebug = PHPMAILER_DEBUG_MODE;
      $mail->SMTPAuth = EMAIL_SMTP_AUTH;
      if (defined(EMAIL_SMTP_ENCRYPTION)) {
          $mail->SMTPSecure = EMAIL_SMTP_ENCRYPTION;
      }
      $mail->Host = EMAIL_SMTP_HOST;
      $mail->Username = EMAIL_SMTP_USERNAME;
      $mail->Password = EMAIL_SMTP_PASSWORD;
      $mail->Port = EMAIL_SMTP_PORT;
      } else {
        $mail->IsMail();
      }

  $mail->From = EMAIL_PASSWORD_FROM_EMAIL;
  $mail->FromName = EMAIL_PASSWORD_FROM_NAME;
  $mail->AddAddress($user_email);
  $mail->Subject = EMAIL_PASSWORD_SUBJECT;
  $mail->Body = EMAIL_PASSWORD_CONTENT . '/' . $user_password;

  if($mail->Send()) {
    $_SESSION["feedback_positive"][] = FEEDBACK_PASSWORD_MAIL_SENDING_SUCCESSFUL;
    return true;
  } else {
    $_SESSION["feedback_negative"][] = FEEDBACK_PASSWORD_MAIL_SENDING_ERROR . $mail->ErrorInfo;
    return false;
  }
}

Validate on login:

if (!isset($_POST['user_name']) OR empty($_POST['user_name'])) {
  $_SESSION["feedback_negative"][] = FEEDBACK_USERNAME_FIELD_EMPTY;
  return false;
}

if (!isset($_POST['user_password']) OR empty($_POST['user_password'])) {
  $_SESSION["feedback_negative"][] = FEEDBACK_PASSWORD_FIELD_EMPTY;
  return false;
}

$sth = $this->db->prepare("SELECT user_id,
                           user_name,
                           user_email,
                           user_password_hash,
                           user_active,
                           user_account_type
                           FROM   users
                           WHERE  (user_name = :user_name OR user_email = :user_name)");

$sth->execute(array(':user_name' => $_POST['user_name'], ':provider_type' => 'DEFAULT'));
$count =  $sth->rowCount();

if ($count != 1) {
  $_SESSION["feedback_negative"][] = FEEDBACK_LOGIN_FAILED;
  return false;
}    

$result = $sth->fetch();

//check via password_verify
if (password_verify($_POST['user_password'], $result->user_password_hash)) {
  ...
  return true;
} else {
  $_SESSION["feedback_negative"][] = FEEDBACK_PASSWORD_WRONG;
  return false;
}

get always the password wrong message. I read this php password_hash and password_verify issues no match but I tested the hash string by hand to verify with literal string.

The hashstring: $2y$10$SwSq7OukPpN/QJ8YOdKgquJQ28fQbNY1Q3JdTFnoe.2VxD/D2RXBS

The password send by email: /f)1c(-JG

tested by hand:

$hash = '$2y$10$SwSq7OukPpN/QJ8YOdKgquJQ28fQbNY1Q3JdTFnoe.2VxD/D2RXBS';
$password = '/f)1c(-JG';

if (password_verify($password, $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

prints Invalid password.

Shangrila answered 13/3, 2014 at 9:34 Comment(9)
Is your database column long enough to store the entire hash untruncated?Boon
yes user_password_hash VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULLShangrila
Can you then please provide a minimal test case that shows the problem? Because the password_ functions as such are working fine, and you appear to be using them correctly. However, there are many parts which we don't see here and can't debug.Boon
I can post the hole creation process but the mvc is huge. I add the smtp sending process. Maybe the sendet password is wrong? But I dont think so, because it is the same output from generate_password.Shangrila
I'm asking precisely for a minimal example, not for everything. Try to reduce the problem yourself. If you have a multi-step process in which something goes wrong, try focussing on that one thing first and confirm that it works at all. Then expand the problem step by step to your original scope.Boon
jesus...the smtp body message added a / cause I forgot the n. So I just thought the password was "f)1c(-JG" but it was "f)1c(-JG". But you gave me the incentive...Shangrila
There you go. BTW, your password generator is insufficient. Each password is guaranteed to never contain the same letter twice. That's far from a random password and greatly helps any attacker in randomly guessing passwords, if he's aware of this restriction.Boon
okay thank you for the advice. I will create a new generator.Shangrila
Hey, I'm the author of the script you have used. Simply follow the install instruction and don't change code in the core, and everything will work fine. "password sent by mail" clearly shows that you are doing really really weird stuff. NEVER send a password via mail. The script doesn't do that and there's absolulty no reason to do so.Strawser
J
2

Your $hash variable in your test case is invalid, and doesn't correspond to password

$hash = '$2y$10$SwSq7OukPpN/QJ8YOdKgquJQ28fQbNY1Q3JdTFnoe.2VxD/D2RXBS';
$password = '/f)1c(-JG';

if (password_verify($password, $hash)) {
echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

When I used this code, everything works properly

$password = '/f)1c(-JG';
$hash = password_hash($password, PASSWORD_DEFAULT, array("cost" => 10));

if (password_verify($password, $hash)) {
    echo 'Password is valid!';
} else {
     echo 'Invalid password.';
}

I use php 5.5.10

Jiggermast answered 13/3, 2014 at 10:34 Comment(3)
there was a mistak in the smtp which sends the wrong password.Shangrila
@Shangrila Sorry what ? You cannot send passwords or hashes anywhere. What do you mean with smtp here ?Strawser
@Panique I think he is building a system for bots to login :)Pathy

© 2022 - 2024 — McMap. All rights reserved.