PHP VERIFY HASH (using a new hashing password $432$45435454.5454554)

Hi people,

I’m not new in php but this php 5.5 change my life and i’m very confuse about it.
I wanna change my hashing password tipe “sha254” for the new hashing system. And i make it.
But now i wanna use the login.php to log in in user accounts to check if it works.

My problem start there. I’m confused to create the verify… in login.php

This one is the old hashing verify code.

[php]$row = $stmt->fetch();
if($row)
{

      $check_password = hash('sha256', $_POST['password'] . $row['salt']); 
        for($round = 0; $round < 65536; $round++) 
        { 
            $check_password = hash('sha256', $check_password . $row['salt']); 
        }

        if($check_password === $row['password']) 
        { 
            // If they do, then we flip this to true 
            $login_ok = true; 
        } else {
            echo "<span class='icon-x'></span><span class='mls'> Username or Passcode are wrong.</span>";
        }
    } 

[/php]

Simple

To setup password in order to save password to a database table:

[php]$password = password_hash($_POST[‘password’], PASSWORD_DEFAULT);[/php]

to check password:

[php]if (password_verify($_POST[‘password’], $row[‘password’])) {
echo ‘Password is valid!’;
} else {
echo ‘Invalid password.’;
}[/php]

check out http://php.net/manual/en/function.password-hash.php and http://php.net/manual/en/function.password-verify.php for further information and help.

One thing that should be added is password_needs_rehash. When using “PASSWORD_DEFAULT” the hash algorithm might change over time. This is also why you should leave good room in your password field in db, and not limit it to 60 chars - which is the current string length of hashed passwords (Bcrypt).

[php]if (password_verify($_POST[‘password’], $row[‘password’])) {
echo ‘Password is valid!’;
if (password_needs_rehash($row[‘password’], PASSWORD_DEFAULT)) {
$hash = password_hash($_POST[‘password’], PASSWORD_DEFAULT);
// update the user in db to save the new hash
}
// do other stuff to log in user, ie
// $_SESSION[‘user’] = $row[‘id’];
} else {
echo ‘Invalid password.’;
}[/php]

[hr]

We can force-change the algorithm by adjusting the options for the Bcrypt hashing, ie changing the hash cost. If you adjust the cost below you can see that the hash needs a rehash, and outputs a new hash with the new cost. This hash should then be saved to the database. The idea is that as time go PHP can increment this cost, or change the algortith completely - in order to make sure passwords are stored securely.

[php]<?php

$submittedPassword = ‘demo123’;
$options = [‘cost’ => 11];

// the user in the db which matches the supplied login name (username/email)
$row = [
‘id’ => 1,
‘username’ => ‘JimL’,
‘password’ => ‘$2y$10$9adCj36UUgfYIO5SgX6/pOIB/DxmlsX/AXndH2RqBvT5ranvL7l4C’
];

if (password_verify($submittedPassword, $row[‘password’]))
{
if (password_needs_rehash($row[‘password’], PASSWORD_DEFAULT, $options))
{
$hash = password_hash($submittedPassword, PASSWORD_DEFAULT, $options);
var_dump($hash);
// update the user in db to save the new hash
}
}[/php]

I wasn’t aware of password_needs_rehash(). I have used a versioning system in the database to determine what value to check for.

Good information.

Isn’t it great that no matter how much each of us knows, there is still more we can learn from each other.

That is the joy of developers getting together to share ideas and grow off of each other.

We have our debates, but we should, it’s another way to learn.

Hey Guys, i’am Silva1000, finally create an account.

So, my question is… I want run the “login.php”.
I try your code “JimL”, but still no working…
Say: Password invalid.

I can send u my all login code to someone help me, because i really need this code working, is for an schooll project.

[php] //session_start();
// First we execute our common code to connection to the database and start the session
require("…/assets/class/common.php");

define("COOKIE_EXPIRE", 2*7*24*60*60);  //2 weeks by default
define("COOKIE_PATH", "/");  //Available in whole domain

// This variable will be used to re-display the user's username to them in the
// login form if they fail to enter the correct password.  It is initialized here
// to an empty value, which will be shown if the user has not submitted the form.
$submitted_username = '';

// This if statement checks to determine whether the login form has been submitted
// If it has, then the login code is run, otherwise the form is displayed
if(!empty($_POST))
{
    // This query retreives the user's information from the database using
    // their username.

	$query = "
        SELECT
            id,
			name,
            username,
            password,
			token,
            salt,
            email,
			date,
			profile_pic,
			credits
        FROM users
        WHERE
            username = :username
    ";

    // The parameter values
    $query_params = array(
        ':username' => $_POST['username']
    );

    try
    {
        // Execute the query against the database
        $stmt = $db->prepare($query);
        $result = $stmt->execute($query_params);
    }
    catch(PDOException $ex)
    {
        // Note: On a production website, you should not output $ex->getMessage().
        // It may provide an attacker with helpful information about your code.
        die("Failed to run query: " . $ex->getMessage());
    }
    // This variable tells us whether the user has successfully logged in or not.
    // If we determine that they have entered the right details, then we switch it to true.
	$login_ok = false;
	
    // Retrieve the user data from the database.  If $row is false, then the username
    // they entered is not registered.
    $row = $stmt->fetch();

	  if (password_verify($_POST['password'], $row['password'])) 
	  
	  {
		  echo 'Password is valid!';
		  
		  $login_ok = true;
		  
		  if (password_needs_rehash($row['password'], PASSWORD_DEFAULT)) 
		  {
			  $hash = password_hash($_POST['password'], $row['salt'], PASSWORD_DEFAULT);
			  // update the user in db to save the new hash
		  }
		  // do other stuff to log in user, ie
		  // $_SESSION['user'] = $row['id'];
	   } else {
		  echo 'Invalid password.';
		  $login_ok = false;
	  }


	/* 
	  $check_password = hash('sha256', $_POST['password'] . $row['salt']); 
        for($round = 0; $round < 65536; $round++) 
        { 
            $check_password = hash('sha256', $check_password . $row['salt']); 
        }

		if($check_password === $row['password']) 
        { 
            // If they do, then we flip this to true 
            $login_ok = true; 
        } else {
			echo "<span class='icon-x'></span><span class='mls'> Username or Passcode are wrong.</span>";
		}*/
	
    // If the user logged in successfully, then we send them to the private members-only page
    // Otherwise, we display a login failed message and show the login form again
		
		if(empty($_POST['username']))
		{
				echo "<span class='icon-x'></span><span class='mls'> Username or Passcode are empty.</span></span>";
		} else {		
			
			if($login_ok)
			{
				// Here I am preparing to store the $row array into the $_SESSION by
				// removing the salt and password values from it.  Although $_SESSION is
				unset($row['salt']);
				unset($row['password']);

				// This stores the user's data into the session at the index 'user'.
				$_SESSION['user'] = $row;
				$_SESSION['date'] = $row['date'];

				if($_POST['rememberme'] != 'Yes')
				{
					$_SESSION['login_time'] = date("H:i:s");
				}
				else
				{
					unset($_SESSION['login_time']);
				}

				header("Location: ../market.php");
			}
			else
			{
				// Tell the user they failed
			  $submitted_username = htmlentities($_POST['username'], ENT_QUOTES, 'UTF-8');
			}
		}
}[/php]

How was the hash that is stored in the DB created?

Can you share the hash? (to verify it looks correct)

This is wrong:
[php]$hash = password_hash($_POST[‘password’], $row[‘salt’], PASSWORD_DEFAULT);[/php]
you do not need to add your own salt as Bcrypt handles that for you. In addition the second parameter should be the algo (PASSWORD_DEFAULT), not a salt.

Given the hash

$2y$10$jY9PsAkSZ7jsO2fCn.8oluntqNSze.9bsl9SS01XzVgfdNBTjAryu

Algorithm:
$2y$10$jY9PsAkSZ7jsO2fCn.8oluntqNSze.9bsl9SS01XzVgfdNBTjAryu

Rounds (cost):
$2y$10$jY9PsAkSZ7jsO2fCn.8oluntqNSze.9bsl9SS01XzVgfdNBTjAryu

Salt:
$2y$10$jY9PsAkSZ7jsO2fCn.8oluntqNSze.9bsl9SS01XzVgfdNBTjAryu

Resulting hash:
$2y$10$jY9PsAkSZ7jsO2fCn.8oluntqNSze.9bsl9SS01XzVgfdNBTjAryu

HUmm the db that is hased is this one.

$2y$10$ckzTSTUh9QWh/aw5HUtj4OjHJBSunNHHTmHQCDoUNb1FTOzjKvjge

what is wrong?

Maybe o i know what is the problem…

In the register.php page… i put the hash like that, without scripts… but is creating the hash anyway…

    $salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647)); 
    $password = password_hash($salt, PASSWORD_BCRYPT, array('cost' => 10));

As said, you shouldn’t create your own salts. And in that code you are hashing the salt, not the supplied password.

Remove the code concerning salts and you should be good to go.

In register you also don’t need the options array (for the time being Bcrypt has 10 rounds by default)

I take off salt… but still the same… “Password invalid”.

how did you create the password in the first place?

Post the current register/login code

Have yoy updated the hash in the db?

I will putt again everything here DB, Register, Login…

Then help me to fix it… :S

REGISTER.PHP

[php]
// First we execute our common code to connection to the database and start the session
require("…/assets/class/common.php");

session_start();

$newACC = True;	

	if(strlen($_POST['name']) < 6)
    { 
     $_SESSION['error'] = "<span class='icon-x'></span><span class='mls'> Please select your name, with at least 6 characters.</span></span><br />";
	 $newACC = False;		 
    }

	if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) 
    { 
     $_SESSION['error'] = "<span class='icon-x'></span><span class='mls'> Please select a valid e-mail.</span></span>";  
	 $newACC = False;       
   } 

    if(strlen($_POST['username']) < 5)
    { 

     $_SESSION['error'] = "<span class='icon-x'></span><span class='mls'> Please select a different username (id), with at least 5 characters.</span></span><br />"; 
	 $newACC = False;       
   } 	   
	
	if(strlen($_POST['password']) < 8)
    { 
     $_SESSION['error'] = "<span class='icon-x'></span><span class='mls'> Please select a different password, with at least 8 characters.</span></span><br />";
	 $newACC = False;		 
    }          
  
    // Make sure the user entered a valid E-Mail address 
    // filter_var is a useful PHP function for validating form input, see: 
    // http://us.php.net/manual/en/function.filter-var.php 
    // http://us.php.net/manual/en/filter.filters.php 
    $query = " 
        SELECT 
            1 
        FROM users 
        WHERE 
            username = :username 
    "; 
     
    // This contains the definitions for any special tokens that we place in 
    // our SQL query.  In this case, we are defining a value for the token 
    // :username.  It is possible to insert $_POST['username'] directly into 
    // your $query string; however doing so is very insecure and opens your 
    // code up to SQL injection exploits.  Using tokens prevents this. 
    // For more information on SQL injections, see Wikipedia: 
    // http://en.wikipedia.org/wiki/SQL_Injection 
    $query_params = array( 
        ':username' => $_POST['username'] 
    ); 
     
    try 
    { 
        // These two statements run the query against your database table. 
        $stmt = $db->prepare($query); 
        $result = $stmt->execute($query_params); 
    } 
    catch(PDOException $ex) 
    { 
        // Note: On a production website, you should not output $ex->getMessage(). 
        // It may provide an attacker with helpful information about your code.  
        die("Failed to run query line 68: " . $ex->getMessage()); 
    } 
     
    // The fetch() method returns an array representing the "next" row from 
    // the selected results, or false if there are no more rows to fetch. 
    $row = $stmt->fetch(); 
     
    // If a row was returned, then we know a matching username was found in 
    // the database already and we should not allow the user to continue. 
    if($row) 
    { 
     $_SESSION['error'] = "<span class='icon-x'></span><span class='mls'>  Please select another username, this already is in use. </span></span><br />"; 
    } 
     
    // Now we perform the same type of check for the email address, in order 
    // to ensure that it is unique. 
    $query = " 
        SELECT 
            1 
        FROM users 
        WHERE 
            email = :email 
    "; 
     
    $query_params = array( 
        ':email' => $_POST['email'] 
    ); 
    
    try 
    { 
        $stmt = $db->prepare($query); 
        $result = $stmt->execute($query_params); 
    } 
    catch(PDOException $ex) 
    { 
       $_SESSION['error'] .= "Failed to run query line 103: " . $ex->getMessage(); 
    } 
     
    $row = $stmt->fetch(); 
     
    if($row) 
    { 
        $_SESSION['error'] .= "<span class='icon-x'></span><span class='mls'> Please select another e-mail, this already is in use.  </span></span><br />"; 
    } 
     
    // An INSERT query is used to add new rows to a database table. 
    // Again, we are using special tokens (technically called parameters) to 
    // protect against SQL injection attacks. 
    $query = " 
        INSERT INTO users ( name, username, password, token, salt, email, date, credits) 
		VALUES (
			:name,
			:username, 
            :password,
			:token,				
            :salt, 
            :email,
			NOW(),
			50
        ) 
    "; 
     
	//$hash = password_hash($password, PASSWORD_BCRYPT);
	
		$options = ['cost' => 12 // the default cost is 10];
		$hash = password_hash($password, PASSWORD_BCRYPT, $options);
	
	
	
	/*$salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647)); 
    $password = hash('sha256', $_POST['password'] . $salt); 

    for($round = 0; $round < 65536; $round++) 
    { 
        $password = hash('sha256', $password . $salt); 
    }*/
     
    // Here we prepare our tokens for insertion into the SQL query.  We do not 
    // store the original password; only the hashed version of it.  We do store 
    // the salt (in its plaintext form; this is not a security risk). 
	
	//generate a new tokenid
	$token = generateTokenId();
	
    $query_params = array(
		':name' => $_POST['name'],
		':username' => $_POST['username'],
        ':password' => $password,
		':token' => $token,
        ':salt' => $salt, 
        ':email' => $_POST['email']
    ); 
    
	
	
	if($newACC == True)
	{
		try 
		{ 
			// Execute the query to create the user 
			$stmt = $db->prepare($query); 
			$result = $stmt->execute($query_params); 
			
			$_SESSION['success'] = "<span class='icon-checkmark'></span><span class='mls'> Your account has been successfully created. <a href='live.php'>Sign in</a></span></span><br />";
		} 
		catch(PDOException $ex) 
		{ 
			// Note: On a production website, you should not output $ex->getMessage(). 
			// It may provide an attacker with helpful information about your code.  
			//die("Failed to run query line 177: " . $ex->getMessage() . ":" . $query); 
			echo "<span class='icon-warning'></span><span class='mls'>Slow Connection: Check your connection... </span></span><br />";
		}
	}
	

	
    // This redirects the user back to the login page after they register 
	header("Location: ../join.php"); 
	
     
    // Calling die or exit after performing a redirect using the header function 
    // is critical.  The rest of your PHP script will continue to execute and 
    // will be sent to the user if you do not die or exit. 
    die("Redirecting to ../join.php"); 


	// define variables and set to empty values
	$nameErr = $emailErr = $genderErr = $websiteErr = "";
	$name = $email = $gender = $comment = $website = "";

[/php]

LOGIN.php

[php]//session_start();
// First we execute our common code to connection to the database and start the session
require("…/assets/class/common.php");

define("COOKIE_EXPIRE", 2*7*24*60*60);  //2 weeks by default
define("COOKIE_PATH", "/");  //Available in whole domain

// This variable will be used to re-display the user's username to them in the
// login form if they fail to enter the correct password.  It is initialized here
// to an empty value, which will be shown if the user has not submitted the form.
$submitted_username = '';

// This if statement checks to determine whether the login form has been submitted
// If it has, then the login code is run, otherwise the form is displayed
if(!empty($_POST))
{
    // This query retreives the user's information from the database using
    // their username.

	$query = "
        SELECT
            id,
			name,
            username,
            password,
			token,
            email,
			date,
			profile_pic,
			credits
        FROM users
        WHERE
            username = :username
    ";

    // The parameter values
    $query_params = array(
        ':username' => $_POST['username']
    );

    try
    {
        // Execute the query against the database
        $stmt = $db->prepare($query);
        $result = $stmt->execute($query_params);
    }
    catch(PDOException $ex)
    {
        // Note: On a production website, you should not output $ex->getMessage().
        // It may provide an attacker with helpful information about your code.
        die("Failed to run query: " . $ex->getMessage());
    }
    // This variable tells us whether the user has successfully logged in or not.
    // If we determine that they have entered the right details, then we switch it to true.
	$login_ok = false;
	
    // Retrieve the user data from the database.  If $row is false, then the username
    // they entered is not registered.
    $row = $stmt->fetch();

	  if (password_verify($_POST['password'], $row['password'])) 
	  
	  {
		  //echo 'Password is valid!';
		  
		  $login_ok = true;
		  
		  if (password_needs_rehash($row['password'], PASSWORD_DEFAULT)) 
		  {
			  $hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
			  // update the user in db to save the new hash
		  }
		  // do other stuff to log in user, ie
		  // $_SESSION['user'] = $row['id'];
	   } else {
		  echo "<span class='icon-x'></span><span class='mls'> Username or Passcode are wrong.</span>";
		  $login_ok = false;
	  }


	/* 
	  $check_password = hash('sha256', $_POST['password'] . $row['salt']); 
        for($round = 0; $round < 65536; $round++) 
        { 
            $check_password = hash('sha256', $check_password . $row['salt']); 
        }

		if($check_password === $row['password']) 
        { 
            // If they do, then we flip this to true 
            $login_ok = true; 
        } else {
			echo "<span class='icon-x'></span><span class='mls'> Username or Passcode are wrong.</span>";
		}*/
	
    // If the user logged in successfully, then we send them to the private members-only page
    // Otherwise, we display a login failed message and show the login form again
		
		if(empty($_POST['username']))
		{
				//echo "<span class='icon-x'></span><span class='mls'> Username or Passcode are empty.</span></span>";
		} else {		
			
			if($login_ok)
			{
				// Here I am preparing to store the $row array into the $_SESSION by
				// removing the salt and password values from it.  Although $_SESSION is
				//unset($row['salt']);
				unset($row['password']);

				// This stores the user's data into the session at the index 'user'.
				$_SESSION['user'] = $row;
				$_SESSION['date'] = $row['date'];

				if($_POST['rememberme'] != 'Yes')
				{
					$_SESSION['login_time'] = date("H:i:s");
				}
				else
				{
					unset($_SESSION['login_time']);
				}

				header("Location: ../market.php");
			}
			else
			{
				// Tell the user they failed
			  $submitted_username = htmlentities($_POST['username'], ENT_QUOTES, 'UTF-8');
			}
		}
}

[/php]

DB Fields

NAME | Username | Password | Salt |
admin | administrator |$2y$10$HX50wYtV7OYGaZqBmBsTGusikbqjaDNKwfNwE7PqcQfQogmPzj0M. | 2a0bd83469519148

Sponsor our Newsletter | Privacy Policy | Terms of Service