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.

Community
  • 1
  • 1
mnlfischer
  • 397
  • 4
  • 12
  • 26
  • 1
    Is your database column long enough to store the entire hash untruncated? – deceze Mar 13 '14 at 09:42
  • 1
    yes user_password_hash VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL – mnlfischer Mar 13 '14 at 09:49
  • 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. – deceze Mar 13 '14 at 09:58
  • 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. – mnlfischer Mar 13 '14 at 10:23
  • 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. – deceze Mar 13 '14 at 10:25
  • 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... – mnlfischer Mar 13 '14 at 10:35
  • 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. – deceze Mar 13 '14 at 10:40
  • okay thank you for the advice. I will create a new generator. – mnlfischer Mar 13 '14 at 10:46
  • 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. – Sliq May 17 '14 at 12:22

1 Answers1

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

mca
  • 66
  • 3