0

i am using the Bcrypt with php to get a safe hashing password to submit to the database in the registration the password get hashed but in the login the system display that the 2 password to not match can anyone help me ????????

i just need from the password.php file

  • the password_hash function
  • password_verify function

password.php

<?php
/**
 * A Compatibility library with PHP 5.5's simplified password hashing API.
 *
 * @author Anthony Ferrara <ircmaxell@php.net>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @copyright 2012 The Authors
 */

if (!defined('PASSWORD_DEFAULT')) {

    define('PASSWORD_BCRYPT', 1);
    define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);

    /**
     * Hash the password using the specified algorithm
     *
     * @param string $password The password to hash
     * @param int    $algo     The algorithm to use (Defined by PASSWORD_* constants)
     * @param array  $options  The options for the algorithm to use
     *
     * @return string|false The hashed password, or false on error.
     */
    function password_hash($password, $algo, array $options = array()) {
        if (!function_exists('crypt')) {
            trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
            return null;
        }
        if (!is_string($password)) {
            trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
            return null;
        }
        if (!is_int($algo)) {
            trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
            return null;
        }
        switch ($algo) {
            case PASSWORD_BCRYPT:
                // Note that this is a C constant, but not exposed to PHP, so we don't define it here.
                $cost = 10;
                if (isset($options['cost'])) {
                    $cost = $options['cost'];
                    if ($cost < 4 || $cost > 31) {
                        trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
                        return null;
                    }
                }
                // The length of salt to generate
                $raw_salt_len = 16;
                // The length required in the final serialization
                $required_salt_len = 22;
                $hash_format = sprintf("$2y$%02d$", $cost);
                break;
            default:
                trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
                return null;
        }
        if (isset($options['salt'])) {
            switch (gettype($options['salt'])) {
                case 'NULL':
                case 'boolean':
                case 'integer':
                case 'double':
                case 'string':
                    $salt = (string) $options['salt'];
                    break;
                case 'object':
                    if (method_exists($options['salt'], '__tostring')) {
                        $salt = (string) $options['salt'];
                        break;
                    }
                case 'array':
                case 'resource':
                default:
                    trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
                    return null;
            }
            if (strlen($salt) < $required_salt_len) {
                trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING);
                return null;
            } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
                $salt = str_replace('+', '.', base64_encode($salt));
            }
        } else {
            $buffer = '';
            $buffer_valid = false;
            if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
                $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
                if ($buffer) {
                    $buffer_valid = true;
                }
            }
            if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
                $buffer = openssl_random_pseudo_bytes($raw_salt_len);
                if ($buffer) {
                    $buffer_valid = true;
                }
            }
            if (!$buffer_valid && is_readable('/dev/urandom')) {
                $f = fopen('/dev/urandom', 'r');
                $read = strlen($buffer);
                while ($read < $raw_salt_len) {
                    $buffer .= fread($f, $raw_salt_len - $read);
                    $read = strlen($buffer);
                }
                fclose($f);
                if ($read >= $raw_salt_len) {
                    $buffer_valid = true;
                }
            }
            if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
                $bl = strlen($buffer);
                for ($i = 0; $i < $raw_salt_len; $i++) {
                    if ($i < $bl) {
                        $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
                    } else {
                        $buffer .= chr(mt_rand(0, 255));
                    }
                }
            }
            $salt = str_replace('+', '.', base64_encode($buffer));
        }
        $salt = substr($salt, 0, $required_salt_len);

        $hash = $hash_format . $salt;

        $ret = crypt($password, $hash);

        if (!is_string($ret) || strlen($ret) <= 13) {
            return false;
        }

        return $ret;
    }

    /**
     * Get information about the password hash. Returns an array of the information
     * that was used to generate the password hash.
     *
     * array(
     *    'algo' => 1,
     *    'algoName' => 'bcrypt',
     *    'options' => array(
     *        'cost' => 10,
     *    ),
     * )
     *
     * @param string $hash The password hash to extract info from
     *
     * @return array The array of information about the hash.
     */
    function password_get_info($hash) {
        $return = array(
            'algo' => 0,
            'algoName' => 'unknown',
            'options' => array(),
        );
        if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) {
            $return['algo'] = PASSWORD_BCRYPT;
            $return['algoName'] = 'bcrypt';
            list($cost) = sscanf($hash, "$2y$%d$");
            $return['options']['cost'] = $cost;
        }
        return $return;
    }

    /**
     * Determine if the password hash needs to be rehashed according to the options provided
     *
     * If the answer is true, after validating the password using password_verify, rehash it.
     *
     * @param string $hash    The hash to test
     * @param int    $algo    The algorithm used for new password hashes
     * @param array  $options The options array passed to password_hash
     *
     * @return boolean True if the password needs to be rehashed.
     */
    function password_needs_rehash($hash, $algo, array $options = array()) {
        $info = password_get_info($hash);
        if ($info['algo'] != $algo) {
            return true;
        }
        switch ($algo) {
            case PASSWORD_BCRYPT:
                $cost = isset($options['cost']) ? $options['cost'] : 10;
                if ($cost != $info['options']['cost']) {
                    return true;
                }
                break;
        }
        return false;
    }

    /**
     * Verify a password against a hash using a timing attack resistant approach
     *
     * @param string $password The password to verify
     * @param string $hash     The hash to verify against
     *
     * @return boolean If the password matches the hash
     */
    function password_verify($password, $hash) {
        if (!function_exists('crypt')) {
            trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
            return false;
        }
        $ret = crypt($password, $hash);
        if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
            return false;
        }

        $status = 0;
        for ($i = 0; $i < strlen($ret); $i++) {
            $status |= (ord($ret[$i]) ^ ord($hash[$i]));
        }

        return $status === 0;
    }
}

register.php

 require_once('include/password.php');

    $hash = password_hash($pass1, PASSWORD_BCRYPT);
    if(password_verify($pass1, $hash))
    {
        echo "matched";
    }
    echo "do not match";

//************Insert all the user's input to the database**************************//
      $query = mysql_query("INSERT INTO user(user_name, first_name, last_name, governorate, district, village, birth_date, email_address, specialization, password, registered_date)VALUES('$username', '$firstname', '$lastname', '$governorate', '$district', '$village', '$bdate', '$email', '$specialization', '$hash',  now())")or die("could not insert data");   

login.php

//***********for hashing password***************************//

require_once('include/password.php');

    $hash = password_hash($pass, PASSWORD_BCRYPT);
    if(password_verify($pass, $hash))
    {
        echo "matched";
    }
    echo $hash;

$sql=mysql_query( "SELECT user_id, email_address, first_name, user_name FROM user WHERE email_address='$email'AND password= '$hash' LIMIT 1") or die("error in user table");
$login_check = mysql_num_rows($sql);
kittycat
  • 14,983
  • 9
  • 55
  • 80
user2372265
  • 5
  • 5
  • 12
  • Does this answer your question? [How do you use bcrypt for hashing passwords in PHP?](https://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php) – Dharman Jan 20 '20 at 22:28
  • 1
    **WARNING**: This is code back-ported to very early versions of PHP 5.0. Later versions have all of these as [built-in functions](https://www.php.net/manual/en/ref.password.php). Do not use this code unless you're stuck on very, very old versions of PHP. – tadman Jan 20 '20 at 23:42

2 Answers2

2

You are doing it wrong.

When creating a new account, you get a password from the user. You hash it and store that hash into your database. There is no need at this point to check whether the password already matches the hash.

register

require_once('include/password.php');

$hash = password_hash($pass1, PASSWORD_BCRYPT);

//************Insert all the user's input to the database**************************//
$query = mysql_query("INSERT INTO user (user_name, .... password, registered_date) VALUES('".mysql_real_escape_string($username)."', ... '".mysql_real_escape_string($hash)."', now())") or die("could not insert data");

Please never forget to escape all strings when putting them into a query string. I added this for you in the example above.

When checking the password on login, you read the hash from the database and call the verify function with this hash and the currently given password from the login form:

login

require_once('include/password.php');

$sql=mysql_query( "SELECT user_id, ... password FROM user WHERE email_address='".mysql_real_escape_string($email)."'") or die("error in user table");

$error = false;
if (mysql_num_rows($sql) == 0) { $error = true; // user not found - don't tell anyone this detail! }
if (mysql_num_rows($sql) > 1) { $error = true; // email addresses are not unique in your database - this should not happen!}
if (!$error) {
    $user = mysql_fetch_assoc($sql);
    if (password_verify($pass, $user['password']) {
        $login=true;
    } else {
        $error = true; // Password is wrong - don't tell anyone this detail!
    }
}

This isn't that hard to get, just have a look at the documentation: https://github.com/ircmaxell/password_compat

And while you are at it: There is very little overhead in implementing the re-hashing of a password.

Sven
  • 69,403
  • 10
  • 107
  • 109
  • It should be noted that the escaping function used here (`mysql_real_escape_string`) has been deprecated with the rest of the library. Use "mysqli", and `mysqli_real_escape_string` instead. – Carcigenicate Jan 31 '16 at 01:12
  • While you are complete right on the general topic of deprecation of the `mysql` extension, you are probably aware that this anwer is from almost 3 years ago - and note that only changing `mysql_real_escape_string` to `mysqli_real_escape_string` is not enough, you'd have to change ALL `mysql_*` functions to their `mysqli_*` counterpart. This however requires more characters to describe than fits into a SO comment section. – Sven Feb 01 '16 at 00:23
  • 2
    I know this is old, that's why I didn't downvote. It's just a heads up to anyone reading this to point them to the updated function. No disrespect to your answer. – Carcigenicate Feb 01 '16 at 00:24
0

If you are receiving a warning like "password_hash() expects parameter 2...", when you call password_hash() function, you could try comment the following lines:

if (!is_int($algo)) {
   trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
   return null;
}

I did it in my password class and the function worked! My PHP environment was PHP Version 7.4.1.

  • Why do you have a "password class" in PHP 7 which has the `password_hash` function builtin? This is a backport for PHP 5.x. Using this code in production is a huge problem. – tadman Jan 20 '20 at 23:40