How to verify an hashed password - php

I am using the password_hash() function.
Now it works to hash the password, but how do I verify it?

Well the function for this option is called: password_verify.
How it does work is this;
<?php
$password = "[PASS]"; //Password user fill in.
$hash= "[HASH]"; //The hashed password that you saved.
$checkPass = password_verify($password, $hash); //This returns a boolean; true or false
if ($checkPass == true)
{
echo 'Password is good!';
}
else
{
echo 'Password is wrong!';
}
?>

boolean password_verify ( string $password , string $hash )
Verifies that the given hash matches the given password.
Note that password_hash() returns the algorithm, cost and salt as part of the returned hash. Therefore, all information that's needed to verify the hash is included in it. This allows the verify function to verify the hash without needing separate storage for the salt or algorithm information.
password
The user's password.
hash
A hash created by password_hash()
http://php.net/manual/en/function.password-verify.php

Related

Yii2 - generated password hash different every time

I'm trying to use Yii's generatePasswordHash() function, but I get a different hash with the same password, every time.
$this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
Here 3 hashes created with the password "test":
$2y$13$wsvC4i8YMwKKHJ2K5iYRG.Z0KBetOh3BctVpJN5pVkXGOcW85hRkO ,
$2y$13$QfV2Qxlj4F5gUh1wIL2WUewoZ55CKYKevjRmRqrenxq8L5ym5xX9. ,
$2y$13$rDArvLa8hnpDGiiDdCs7be4iTsr2T3XMXmnapynuD1i1ekbz8zF4m
Anyone an idea what's happening?
EDIT:
When I try to verify with:
Yii::$app->getSecurity()->validatePassword($password, $this->password)
it returns false.
EDIT#2:
function looks like this:
public function validatePassword($password)
{
return Yii::$app->getSecurity()->validatePassword($password, $this->password);
}
$password is the input password and $this->password is the hash.
Strangely password_verify($password, $this->password) works, but Yii's verifier doesn't.
All hashes are correct. Because hash algorithms make different hashes for the same password. Where does the password variable come from in your code? It should be a password string not a hash.
$hash = "hashed version";
$password = "string password";
if (Yii::$app->getSecurity()->validatePassword($password, $hash)){
// password correct
}
Adding to efendi's answer.
Getting a different hash each time Yii's generatePasswordHash() function is run is normal behavour.
Validating the password against the hash requires the 'salt' from the 'hash'.
The first 22 characters after '$2y$13$' in the hash is the salt.
The validatePassword($password, $hash) function gets the salt from the hash, hashes the $password using the salt which should get the same hash as the $hash if the password were to be correct.

sha1() for Password hashing

I am using sha1 for my password security. I have stored password in this way in register.php
// secure password
$salt = openssl_random_pseudo_bytes(20);
$secured_password = sha1($password . $salt);
//Send it to mysql table
$result = $access->registerUser($username, $secured_password, $salt, $email, $fullname);
This all is working fine.
Problem is here:
In my login.php
$password = htmlentities($_POST["password"]);
$secure_password = $user["password"];
$salt = $user["salt"];
// 4.2 Check if entered passwords match with password from database
if ($secure_password == sha1($password . $salt)) {
//do something
} else {
//do something
}
I am always getting as password does not match.
where am I going wrong?
First is first. NEVER USE SHA OR MCRYPT TO STORE YOUR PASSWORD.
EDIT : The password_hash() function generates a long password hash, so make sure that your column in the mysql is a VARCHAR of 500 space
All these useless practises is the root reason why almost many websites get hacked. To tackle the situation, php did a lot of research and then at last came with the most secure function called the password_hash(). I am not more onto explaining about password_hash() here as there are already many documents on the internet.
You can always hash a password like this
<?php
$securePassword = password_hash($_POST['password'], PASSWORD_DEFAULT);
$query = $db->query('INSERT INTO users ......');
?>
And, to verify the password, you can simply use this function
<?php
$passwordHash = $query['password']; //Password from database
$userPassword = $_POST['password']; //Password from form
if(password_verify($userPassword, $passwordHash)) {
echo 'Password is correct, logged in!';
} else {
echo 'Password is wrong, try again';
}
?>
And, answer for your question.
PLEASE DON'T USE SHA OR MCRYPT OR BCRYPT. IF YOU WANNA GET YOUR WEBSITE HACKED, THEN CONTINUE. OR USE password_hash()
The reason you don't get the hash genereated each time because the openssl_random_pseudo_bytes() generates random numbers each time. So each time, during execution, the function returns different numbers and you get your sha result wrong and thus giving a FALSE alert.
PLEASE, AGAIN. I BEG YOU TO USE password_hash() FUNCTION
For more information on password_hash() and password_verify() :
http://php.net/manual/en/function.password-hash.php
http://php.net/manual/en/function.password-verify.php

How to compare a hashed password from user input?

I want my login password to be secured. So I came up to use the PHP's crypt() function to hash the password before inserting it to database. But Im having trouble when comparing the user input password from the converted hash password. Here's my code:
<?php
$password = 'hello_password';
# A higher "cost" is more secure
$cost = 10;
# Create a random salt
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
# Blowfish algorithm.
$salt = sprintf("$2a$%02d$", $cost) . $salt;
$salted_password = $password . $salt; // apply salt to password
# hash the password
$hash_password = hash('sha256', $salted_password);
$userInput = 'hello_password'; // suppose this is the user input password
if (hash('sha256',$userInput) == $password) {
echo "Password Verified.";
}
else {
echo "Incorrect Password";
}
?>
But it always displays Incorrect Password although my password is correct. I don't want to use "hash_equals" function as it is not supported with my current PHP version. Can someone help me with this ? Thanks
You're comparing a hashed user input to the actual user password. So of course this is never going to work.
You're basically asking if hash == 'hello_password'. A hash will never match that, that is the whole point of a hash. You also aren't using the salt with the user input.
You hash the actual password with a salt which is fine:
$salted_password = $password . $salt; // apply salt to password
# hash the password
$hash_password = hash('sha256', $salted_password);
So you need to hash the user input with the salt, the same way:
$salted_input = $userInput . $salt; // apply salt to user input
# hash the input
$hash_input = hash('sha256', $salted_input);
Then you can compare $hash_input with $hash_password.
You also aren't using a salt properly. The salt is supposed to be used in the storage of the password to prevent rainbow table attacks. Randomly generating a salt to apply to both the input and the password at the time of comparison is pointless.

hashing password with salt

I have searched through Internet and found the function for hashing the password. But
i'm having trouble to deal with hashed password stored in the the database. the function i'm using generate the random password as it is concatenated with the random generated salt.
the problem comes when a user wants to change his password.
current_password = random hashed password( which must match the one stored in db).
if(current_password == $db_password){
enter new password
}
the above condition wont be true since the password is always random.
my function
function cryptPass($input,$rounds = 9) {
$salt = "";
$saltChars = array_merge(range('A','Z'),range('a','z'),range(0,9));
for($i = 0;$i < 22; $i++){
$salt .= $saltChars[array_rand($saltChars)];
}
return crypt($input,sprintf('$2y$%02d$', $rounds).$salt);
}
$pass = "password";
$hashedPass = cryptPass($pass);
echo $hashedPass;
i have 3 column in my user table (id, username, password).
can any one tell me how to properly use this function,
or is there a best way to do this?
You want to store the $salt generated in the database along with the hashed password. Then when you come to check the password you will be able to get the salt from the database and use it in the hashing process again.
So your database table with have an extra column in it called "salt"
(id, username, password, salt)
You need to do the same steps, as you would for the login. Check if the entered old password matches the password-hash in the database, then create a hash from the entered new password and store it.
PHP already has a function password_hash() to create a hash, and a function password_verify() to check whether the entered password matches the stored password-hash.
// 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);
So your code would look something like this:
if (password_verify(current_password, $db_password))
{
enter new password
}

PHP encrypt password before storing it to database

I found the following example on php.net to secure password before storing it. However, I don't quite understand line 3. Could someone explain this a little bit? Thanks!
1 <?php
2 $password = crypt('mypassword'); // let the salt be automatically generated
3 if (crypt($user_input, $password) == $password) {
4 echo "Password verified!";
5 }
6 ?>
crypt is a one-way function and returns a string that already contains the salt,
When comparing the user input with the crypt result, the function automatically extracts the salt from the string.
To be more clear :
crypt() outputs a string that contains both the salt and the result of the hash. When you pass it that string as a salt, it knows to extract only the salt part and ignore the hash part. And it still returns a string containing both the salt and the hash. So these strings can be compared
You can clearly understand by:
when user signups for the first time , the process is:
$password = crypt($user_input); // let the salt be automatically generated
if (crypt($user_input, $password) == $password) {
echo "Password verified!";
}
when user tries to login , the process will be :
if(crypt($user_passsword_currentlyin_db, $user_inputted_password) == $user_inputted_password) {
echo "Password verified!";
}
Hope you get the thing :)
EDIT:
The output of crypt consists of:
When you pass this output as "salt" back to crypt, it will extract the right algorithm and salt, and use these for the operation. If there is only an algorithm mentioned, it uses this one and generate random salt. Otherwise it will choose a default algorithm and generate random salt. The hash part in the passed salt parameter is ignored.
So you can simply compare your stored_hash with crypt(password, stored_hash) - if it is equal, it quite likely was the right password.
Here is an pseudocode explanation (in PHP-like syntax) how crypt works:
function crypt($password, $salt)
{
if (substr($salt,0 1) == "_") {
$count = substr($salt, 1, 4);
$real_salt = substr($salt, 5, 4);
return "_" . $count . $real_salt . crypt_ext_des($password, $count, $salt);
}
if(substr($salt, 0, 3) == "$1$") {
list($ignored, $real_salt, $ignored) = explode("$", $salt);
return "$1$" . $real_salt . "$" . crypt_md5($password, $real_salt);
}
if(substr($salt, 0, 4) == "$2a$") {
$cost = substr($salt, 4, 2);
$real_salt = substr($salt, 7, 22);
return "$2a$" . $cost . "$" . $real_salt . crypt_brypt($password, $real_salt, $cost);
}
// ... SHA256 and SHA512 analogons
// no match => STD_DES
$real_salt = substr($salt, 0, 2);
return $real_salt . crypt_std_des($password, $real_salt);
}
It is considered good security practice not to store plain text passwords on the server side in case the password file is compromised and user's passwords revealed.
Instead, when the user registers, you should use a one-way hash algorithm on the password before storing it in the database. This way, it is impossible to reproduce the user's password if the file is compromised.
When the user logs in, it is not possible to compare the plaintext password they just entered with that in the database because the password in the database has been hashed.
However, because the same input to a hash function will always produce the same output, line #3 will hash the plaintext input the user just entered and compare it with the hash stored in the database. That way you are comparing hashes with hashes and can establish if the user is authenticated.
A couple notes on security: you should always fail-safe, so your code should read:
if(crypt($user_input, $password) == $password) {
echo "Password verified!";
} else { die("Wrong username/password"); }
Also note that a compromised password file can be reconstructed using a rainbow table.
$user_input is nothing but your password which is stored in the DATABASE
if(crypt($stored_passsword_in_db, $current_password) == $current_password) {
echo "Password verified!";
}
Hope this helps you....
The second parameter is the key. That accepts either nothing, a salt, or a hash that crypt made earlier, which has the salt to make the hash, embedded in it. In the first case, a salt is made up. In the latter case, the salt is used and not the entire hash. So therefore this holds (make sure you understand that, because that's the key to understanding line 3):
crypt($input, $salt) == crypt($input, crypt($input, $salt))
What you have in your database as the user's hashed password, is the left term in that equation. So line 3 can be rewritten as:
if (crypt($user_input, crypt('mypassword')) == crypt('mypassword'))
And the salt was automatically generated in line 2, let's assume it equals 'autosalt'. Line 3 can now be rewritten to this:
if (crypt($user_input, crypt('mypassword', 'autosalt')) == crypt('mypassword', 'autosalt')
And there you go: this is only true if $user_input == 'mypassword'.

Categories