Compare hashed password to validate if passwords are matched - php

I use blowfish method to hash the passwords from the user when they're signing up.
In the signup form, there is "Enter Password" box and "Confirm Password" box.
So, to check if the passwords are matched, I used hashed versions to compare. But then, it doesn't seem to match.
Please see the code below...
get values from the super global variables and hash them.
$hashed_password = password_encrypt($_POST['password']);
$conf_hashed_password = password_encrypt($_POST['conf_password']);
call the function
passwords_match_check($hashed_password, $conf_hashed_password);
Defined function
function passwords_match_check($hashed_pw, $conf_hashed_pw){
global $errors;
if($conf_hashed_pw != $hashed_pw){
$errors['pws_no_match'] = "Passwords do not match";
}
}
This code always says passwords do not match even if I do know passwords are same...
So, where I have gone wrong... ?
Is it OK, if I just used the values without hashing to compare ?

Just use password_hash() and password_verify() (both included in php 5.5+). And if you're on 5.3 - 5.5, use password-compat backwards compatibility library.
A custom password_encrypt() function is un-necessary and very likely less secure then the built-in one. So just use the built-in one.

Unless you share the password_encrypt function it's hard to say.
If the method seeds the encryption uniquely both hashes will be different.
( Could be the reason of your failed check. )
Why not check the raw input instead of the hashed?

Related

YII2 crypt function that did work has stopped

I have a page in my site that allows the user to change there password but as part of the form they have to enter the old password. In the model I have verification to check the old password entered on the form matches the one in the database
public function oldPasswordCheck($attribute, $params)
{
$old_password = $this->attributes['password'];
if (crypt($this->old_password, $old_password) != $old_password)
{
$this->addError('old_password', 'This is not the old password');
}
}
This worked until recently but for some reason now, if you enter the correct old password, it still tells you they didn't match.
Any pointers would be much appreciated.
Some possible answers:
1) Your salt parameter
Php crypt() function uses two parameters: crypt ( string $str [, string $salt ] ). It seems that you are using the password as salt, which is a very bad practice. Is that so or are you just confusing the salt parameter? I would also recommend to always compare passwords with php hash_equals(), because crypt() is vulnerable to timing attacks.
2) changes in your server configuration
What type of hash your php configuration use to crypt/decrypt strings?:
On systems where the crypt() function supports multiple hash types, the following constants are set to 0 or 1 depending on whether the given type is available: CRYPT_STD_DES, CRYPT_EXT_DES, CRYPT_MD5, CRYPT_BLOWFISH, CRYPT_SHA256 and CRYPT_SHA512. If you changed recently your server configuration, some of that could not be available anymore. Check it with phpinfo()
A recommendation
You are working with a framework, and Yii like every framework has its own class to crypt and decrypt strings. Take a look at yii security class. It will make your life easier.

I can't compare password from my database and the one inputted

I am using php crypt function to make a password secure, but when I try and compare a password entered to a one in the database it will not work.
here is my code to create the password in the first place:
$crypt_password = crypt($_POST['confirm-password']);
here is me trying to compare to the password in another function:
$input_crypt_password = crypt($_POST['input-pw']);
if ($input_crypt_password == $dbpassword){
// do change password function
}
This is not working.
when i print both passwords the are different.
why are the passwords different even though I am entering the same password and using crypt function on both?
can anyone point me in the right direction?
From the docs
Example #1 crypt() examples
<?php
$hashed_password = crypt('mypassword'); // let the salt be automatically generated
/* You should pass the entire results of crypt() as the salt for comparing a
password, to avoid problems when different hashing algorithms are used. (As
it says above, standard DES-based password hashing uses a 2-character salt,
but MD5-based hashing uses 12.) */
if (hash_equals($hashed_password, crypt($user_input, $hashed_password))) {
echo "Password verified!";
}
?>
The code in the question will effectively generate a new hash every time it's called - the existing password hash needs to be passed as the salt to get a consistent result.
As also mentioned in the docs:
Use of password_hash() is encouraged.
I'd go further and say you definitely should be using password_hash instead of calling crypt for password usage (assuming php >= 5.5); in any case though for whichever whatever tools/methods you're using - please read the docs to know how to use them.
Don't use crypt directly for passwords.
If you have PHP 5.5+, than use the built in password_hash function, otherwise if you have PHP 5.3.7+ use the polyfill for this function.
Try to something like this.
$crypt_password = crypt($_POST['confirm-password'],salt);
$input_crypt_password = crypt($_POST['input-pw'],salt);
if ($input_crypt_password == $dbpassword){
// do change password function
echo "Password match successfully!";
}
Here salt parameter to base the hashing on. If not provided, the behaviour is defined by the algorithm implementation and can lead to unexpected results.
I don't know what to say that will add more detail than what everyone else has already said...
So, in modern day hash/unhashing algorithms it would be unsafe to store passwords using standard hashing functions (e.g. MD5 / SHA256) as it is quick and easy to unhash this type of entry.
password_hash() as referenced in other answers and comments should be you're #1 way to safely store passwords as it uses a one way hashing algorithm.
You should read this page!
And then in response to your original question, use hash_equals() function to compare passwords.
As many guys here said, you should use password_hash php function.
Here you can see a simple example how to use it:
<?php
$password = '123456';
$userInput = '123456';
$storedHash = password_hash($password, PASSWORD_DEFAULT);
if (password_verify($userInput, $storedHash)) {
echo 'OK';
} else {
echo 'ERROR';
}
Also as mentioned before, if you use older version of PHP, you can install polyfill.
Did you trim the input before saving in db and while making the comparison. Since the input is coming from browser this may be a reason why it is not matching. otherwise this https://stackoverflow.com/a/41141338/1748066 seems appropriate.

Codeigniter password matches not working with md5

When I use the following code in a validation form the password matches do not match the two passwords even when the two passwords are same.
$this->form_validation->set_rules('password','Password','required|md5|trim|xss_clean|matches[rpassword]');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean');
But when I remove the md5 function then the password matches is working properly.
Can someone understand why this happens?
When you do matches[rpassword], it's looking at the current value of password after the md5 but rpassword before the md5.
Switch it to this so that it does the match validation BEFORE converting to md5:
$this->form_validation->set_rules('password','Password','required|matches[rpassword]|md5|trim|xss_clean');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean');
Also, if this is an application where security truly matters - please know that md5 is very easy to crack and that if someone is able to ever get into your database that they will be able to hack all of these passwords. So basically using md5 is almost the equivalent to not encrypting in the first place.
For password storage, use CRYPT_BLOWFISH or PHP 5.5's password_hash() function. For PHP < 5.5 use the password_hash() compatibility pack.
This is happening because the operation do comparation of "matches[rpassword]" it is before of variable "rpassword" be found, see below:
Your code:
$this->form_validation->set_rules('password','Password','required|md5|trim|xss_clean|matches[rpassword]');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean');
Updated and working:
$this->form_validation->set_rules('password','Password','required|md5|trim|xss_clean');
$this->form_validation->set_rules('rpassword','Repeat Password','required|md5|trim|xss_clean|matches[password]');

Password does not match after being encrypted using crypt() and password_hash() function

I modified my old post. I tried the crypt() function and now trying to work with password_hash() and password_verify() to verify the encrypted password coming from database but on each call, password_hash() function retuns a different encrypted string and password_verify() cannot match it.
This is how I am doing this.
//please ignore the syntax error if any
$data = '11';
$dbpass = password_hash($data, PASSWORD_BCRYPT);
echo $dbpass; // displays the random strings on each page refresh.
Once password is saved into database does not get match during the login process. Below is my actual function.
private function process_data($password){
$password = __STR.$password.__STR;
return password_hash($password, PASSWORD_BCRYPT);
}
private function processed($login_password, $dbpassword){
$login_password = __STR.$login_password.__STR;
return password_verify($login_password, $dbpassword);
}
On each function call for creating a hashed string for password, the function returns the different string next time.
Ok, Let's go through this one by one.
First, it's hashing, not encryption. Encryption is two-way, hashing is one way. We want to hash. We never want to encrypt. Yes, terminology matters. Please use the correct terminology.
Next, each call to password_hash is supposed to return a different hash. That's because it's generating a strong random salt. This is how it was designed, and how you really should be using it.
Further, DO NOT do the "pepper" thing of adding __STR before and after the password. You're doing nothing but potentially weakening the users password (which is not good). If you want more information around why that's a bad idea: Read This Answer.
Continuing, I would highly recommend that you do not use crypt directly. It is actually surprisingly easy to screw up and generate extremely weak hashes. This is why the password_* api was designed. crypt is a low level library, you want to use a high level library in your code. For more information on ways to screw up bcrypt, check out my blog: Seven Ways To Screw Up Bcrypt.
The Password API was designed to be a simple, one-stop shop. If it's not working for you check the following things:
Are you using PHP >= 5.5.0? Or are you using PHP >= 5.3.7 with password_compat?
Is your database column wide enough?
It needs to be at least 60 characters long.
Are you checking that the result of the function is a string, and not bool(false)?
If there is an internal error, it will return a non-string from password_hash.
Are you getting any errors?
Have you turned on error_reporting to its maximum setting (I recommend -1 to catch everything) and checked that the code isn't throwing any errors?
Are you sure you are using it correctly?
function saveUser($username, $password) {
$hash = password_hash($password, PASSWORD_BCRYPT);
// save $username and $hash to db
}
function login($username, $password) {
// fetch $hash from db
return password_verify($password, $hash);
}
Note that each one should be called only once.
Are you using PHP < 5.3.7 with password_compat? If so, this is your problem. You are using the compatability library on an unsupported version of PHP. You may get it to work (certain RedHat distributions have backported the necessary fixes), but you are using an unsupported version. Please upgrade to a reasonable release.
If all else fails, please try running this code and reporting back the output:
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
$test = crypt("password", $hash);
$pass = $test == $hash;
echo "Test for functionality of compat library: " . ($pass ? "Pass" : "Fail");
echo "\n";
If that returns Fail, you are running an unsupported version of PHP and should upgrade. If it returns pass, than the error is somewhere in your logic (the library is functioning fine).
The best way to store passwords is to use PHP's function password_hash(). It automatically generates a cryptographically safe salt for each password and includes it in the resulting 60-character string. You won't have to worry about the salt at all!
// 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);
Your own scheme is very weak, first you are using MD5 which is ways too fast for generating password hashes, then you use a static salt, which defeats the purpose of a salt. Maybe you want to have a look at my tutorial about safely storing passwords.
Edit to answer updated question:
It is not necessary to add the __STR to the password (if you want to add a pepper there are better ways), but your example functions should actually work. The returned value of password_hash() will be different each time because of the random salt. This is correct, the function password_verify() is able to extract this salt for the verification. In your case the database field is probably the problem. Make sure it can hold a 60 character string.

Correct use of crypt?

So after researching this quite a bit I'd like to know if this is the best practices way of doing it or not.
When I send the user's password to the DB I'm doing this:
// DB input:
$mySalt = time(); // generate random salt such as a timestamp
$password = crypt($_POST['password'], $mySalt);
// submit $password and $mySalt to DB here via PDO
And when I go to check the password at login I'm doing this:
// At login:
// retrieve the password and the salt from the DB
if(crypt($_POST['password'], $saltFromDb) === $passFromDb)
// allow login
Would this be the correct way to do that or am I missing something? Thank you for any advice.
What you need instead is to use the inbuilt salting and hashing functions supplied within crypt. Here is an example using a good hashing algorithm call blowfish (bcrypt): How do you use bcrypt for hashing passwords in PHP?
In this case the slower the algorithm the better.
When getting it from DB you would simply use crypt() to evaluate the entire string to understand if it validates as the correct password etc.

Categories