Why isn't my PHP password hashing comparison working? - php

I have two functions, HashPassword() and ValidatePassword.
The first one hashes the password given on signup form with a dynamic salt and the second validates the password.
Basically, I am checking if the password hashes match they never do match. On my login form when I call the ValidatePassword() function I have tested echoing out the hashes in the ValidatePassword() to make sure I am splitting the hash in write place for comparing and I am but when comparing them, they echo out a different hash.
Probably easier to look at both functions to explain better.
<?php
// hashes a users password along with a dynamic salt
// dynamic salt is stored with users password and is seperated by a ;
function HashPassword($password){
// creates a dynamic salt
$DynamicSalt = uniqid('', true);
// hash the password given from user along with dynamic salt
$HashedPassword = hash('sha512', $password . $DynamicSalt);
// combine the hashed password seperated by ; then the dynamic salt to store in database
$final = $HashedPassword.';'.$DynamicSalt; // this value is stored in database like: c29fc9e4acdd2962c4db3f108bee728cf015c8f6388ab2cd4f21e405f9d2f13b2d53a1ab8629aa21c3453906a98aff0d4b9a0e14bfc2c553a4f9c7c0c32fc58a;4f91cfc746b426.53641182
return $final;
}
// validate password user entered ($password = password from user | $dbHashedPassword = hash from database)
function ValidatePassword($password, $dbHashedPassword){
// we need to get the password hash before the salt, (fetch just the first 128 characters from database hash)
$CorrectHash = substr($dbHashedPassword, 0, 128);
// get the dynamic salt from end of sha512 hash (
$DynamicSalt = substr($dbHashedPassword, 129, 151); // get just the dynamic salt part of the db hash
// hash the password from user and the dynamic salt which we got from the end of the hash from database
$TestHash = hash('sha512', $password . $DynamicSalt);
return ($CorrectHash == $TestHash);
// WHEN I ECHO OUT THE THREE VARIABLES $CorrectHash, $DynamicSalt and $TestHash
// THE $CorrectHash (from db, first 128 chars) is not the same as $TestHash
// AND TO MAKE SURE I AM SPLITTING THE HASH AND DYNAMIC SALT InN THE CORRECT PLACE I ECHO OUT
// $DynamicSalt and it is split in the correct place showing the 23 characters which the dynamic salt is 23 characters
// BUT WHEN I COMBINE THE $password and $DynamicSalt in $TestHash it shows a completely different hash from the $CorrectHash (which we got and split from database)
}
?>
I'm not sure what's wrong, but it seems I'm splitting the hash and dynamic salt in the correct place because when I echo out it shows the first 128 chars (sha512) then the dynamic salt (23 chars) but when echoing out the two 128 chars hashes they do not match (by this I mean they are completely different hashes).

It's probably something to do with how you're splitting the hash you're testing against. For instance, you're trying to get a salt that's 151 characters long.
Try this:
function ValidatePassword($password, $dbHashedPassword) {
list($CorrectHash, $DynamicSalt) = explode(";",$dbHashedPassword,2);
return $CorrectHash == hash("sha512",$password.$DynamicSalt);
}

if all your substr are correct you just forgot to append ";" . $DynamicSalt to the $TestHash
btw. this violates against the first database normalization rule: "values have to be atomic". the salt should be stored in a seperate field.

Related

validating the password in the In-Built crypt function in php

I used the crypt function with the blowfish algorithm(one-way hashing)and i saved my hashed string in db there no problem.
$hash=$2y$13$1wVxPniVSiKTjBmDxUhykeec08.v0UsujEkmhjHECIUgEiSuJFag
$actual=crypt("kumar",$hash);
These is how they used to validate the password is to took our current password and the hashed password which we can stored into the db.
On during these they compared with follwing code
public function compareString($expected, $actual)
{
$expected .= "\0";
$actual .= "\0";
$expectedLength = StringHelper::byteLength($expected);
$actualLength = StringHelper::byteLength($actual);
$diff = $expectedLength - $actualLength;
for ($i = 0; $i < $actualLength; $i++) {
$diff |= (ord($actual[$i]) ^ ord($expected[$i % $expectedLength]));
}
return $diff === 0;
}
It return only 0 or 1 when the password is correct or not.
But My question is on these how they matched the current password with the hashed password which we save in db.Because the current password only contains the string and the hashed password contains the cost,salt,hashed password.
Is that they validate the password only or only the salt or how they do it?
I want the flow of validation of passwords of In-built crypt algorithm.
For a starter I would recommend to use the functions password_hash() and password_verify() to check passwords, internally they use the crypt() function.
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
// 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);
But you seem to be interested in how the crypt() is able to verify the password with its hash. When you create the first hash, you pass in the crypt-parameters as the second argument, it contains the algorithm, the cost factor and the salt (the format is explained in this answer).
For verification you can calculate the hash again, but you need the exact same crypt-parameters, then you get a comparable hash. The first hash starts with the crypt-parameters, and the crypt() function extracts those parameters from the first hash, when you pass it as the second argument.
$2y$13$1wVxPniVSiKTjBmDxUhyke
In your example this part of the hash contains the crypt-parameters, it is the start of your hash and it is used by crypt() again to verify the password.

Matching user's password with hashed password stored in DB

Somebody should pls guide me on how i can fetch out hashed password from database and match the password entered by a user when login in
i used php crypt() function with bcrypt algorithms to hash the password when registrian the user
thank you all in advance
From the documentation:
$hashed_password = crypt('mypassword'); // let the salt be automatically generated
if (crypt($user_input, $hashed_password) == $hashed_password) {
echo "Password verified!";
}
You need to pass in the original hash, otherwise crypt will generate a random salt and the passwords are very unlikely to match. I.e.
//BROKEN - will almost always print "Bugger off!".
$hash = crypt('Hello world');
$attempt = crypt('Hello world');
if($hash === $attempt){
echo "Access granted!";
}else{
echo "Bugger off!";
}
You don't need to "fetch" the hash from the database, you just hash the given password (from a login attempt I assume) and match THAT hash against the password column of a database. if a match is found where the password column matches the hash that you just made AND the username is a match, then the password is valid.
Thank you all, if i really get your explanations you mean i should hash the coming password from a user attempting to login and then compare the hash value with the one in DB
EXAMple
$salt=//the bcrypt algorithms format, cost parameter and the salt goes here, thesame with the one use when registrian
$coming_pass= crypt( $password, $salt)
mysqli_query ( SELECT from user WHERE username= $username AND
password= $coming_pass)
you just send the unencrypted password into the same crypt process as you did with the encrypted password, then they should match.
PHP has built in Options to do that, look at Creating a Hash, and Verifying a Hash
pseudo-code
hashed password = hp
plain text password = p
seed (Random Number generated by server) = s
hash algorithm (md5, sha1, sha256, ...) = hash
Example with Seeded Hash
hp = hash(p + s)
the order you set the seed is not important, as long you do it the same way every time, by Concatenate the password and seed
Example without Seeded Hash
hp = hash(p)
you will need to save the hp and seed, the p should NEVER be saved by the server, as Plain Text Passwords is a security issue.
C# Code Example:
static public bool IsPasswordCorrect(string hp, string seed, string enteredPasword)
{
return (hp == Sha1(String.Concat(enteredPasword, seed)));
}
this way you have no direct way to get the password from the database, and only the actual Client will have the Plaintext Password.
if you want a 2-way encryption algorithm, you will need to look at RSA, but it is way more complicated and requires a lot of knowledge to make secure.

How to match username with encrypted password on login [duplicate]

This question already has an answer here:
How to check a mysql encrypt value with a salt in PHP?
(1 answer)
Closed 9 years ago.
I would like to encrypt some passwords and put it in database. How do I keep this stuff in a database so I can retrieve the data if the owner matches.
Example
<?php
// some validations and other staff
$data = $_POST['input'];
$hash = crypt($data);
//then database insert code
?>
If I echo the $hash, it's giving me some encrypted data but when I refresh the page, the numbers are changing from time to time. How do I keep the data static? How will I tell the encrypted password that this was the owner when username and password entered.
Example
<?php
//time of encryption
$name = "someone";
$pass = "p1x6Fui0p>j";
$hash = "$pass"; //outcome of $hash e.g. $1$aD2.bo0.$S93XNfgOFLskhis0qjE.Q/
// $hash and $name inserted in database
?>
When the user tries to login with collect details, how will I refer $hash "$1$aD2.bo0.$S93XNfgOFLskhis0qjE.Q/" was equal to $pass "p1x6Fui0p>j" ?
crypt() has an unfortunate name. It's not an encryption function, but a one-way hashing function.
If you're using PHP 5.5+, just use password_hash and password_verify:
$hash = password_hash($data, PASSWORD_BCRYPT); // Bcrypt is slow, which is good
And to verify the entered password:
if (password_verify($pass, $hash)) {
// The password is correct
}
Now to answer your actual question: the purpose of password hashing is to authenticate users without actually storing their plaintext passwords. If hash(a) == hash(b), then you can be pretty sure that a == b. In your case, you already have hash(a) ($hash), so you just need to hash the inputted password and compare the resulting hashes.
crypt() does this for you:
if (crypt($pass, $hash) === $hash) {
// The password is correct
}
From the php crypt page
if (crypt($user_input, $hashed_password) == $hashed_password) {
echo "Password verified!";
}
You are not using your own salt, so for every call salt is automatically generated, and salted password is hashed. To get the same hash from this password, you need to run crypt with exact salt that was generated during first run.
Generated salt varies depending on algorithm used for hashing, but from your example it's MD5, and salt is delimited by first and third dollar sign inclusively:
$hash = '$1$aD2.bo0.$S93XNfgOFLskhis0qjE.Q/';
// \ salt /
So to get Exact same hash you need to call crypt($pass, '$1$aD2.bo0.$');
Remember that if you want to use your own salt, it needs to be in proper format for given algorithm. For best results use php 5.5+ password_hash mentioned by #Blender, and for older php versions there is password_compat library, with this you don't have to worry about proper salt format.

Blowfish and Crypt Successful Example?

I'm reading up on protecting passwords and want to get feedback on if my code is correct. I'm trying to use blowfish and crypt() together to prevent anyone from decrypting passwords. Also, I have a question. When I store the password, I assume I will have to also store the variable $string so that I can use it again to verify the user when he signs in, correct?
function unique_md5() {
mt_srand(microtime(true)*100000 + memory_get_usage(true));
return md5(uniqid(mt_rand(), true));
}
//unique_md5 returns a random 16 character string
$string = '$2a$07$' . unique_md5();
$password = 'password';
$password = trim($password);
$protected_password = crypt($password, $string);
//then store the variables $string and $protected_password into the database
Blowfish takes a 22 character string for it's salt (that's not including the type and the cost parameter). MD5 returns a 32 character string, which is not accepted by crypt_blowfish. Use proper salts.
No, you don't need to store the salt with the encrypted password, as the encrypted password is returned to you with the salt already prepended. When you verify if a plaintext password matches a crypted password, you only need to check if $crypted_password == crypt($plaintext_password, $crypted_password).

secure password in php using hash_hmac

i just get one function from this site which describe that how to generate secure password using hash.
function is bellow
function hash_password($password, $nonce) {
global $site_key;
return hash_hmac('sha512', $password . $nonce, $site_key);
}
i am using this function like
$salt = sha1(rand());
$salt = substr($salt, 0, 4);
$site_key="site.com";
$pass=hash_password($pass,$salt);
it generate random text on each time.
but i am unable to verify that password in database, as in database password is stored and this generate random text every time.
i want to know how can i use this function to
Store Password in Database at time of user creation
Verify Password from database at login
or
is there any other secure way?
Thanks
You need to store the random string ($nonce I presume) in your database as part of the data, together with the resulting hash. Otherwise, you simply don't have enough information to validate the password.
Store the random generated string along with the password into user's row on the db or hardcode the salt and use always the same salt instead of changing it everytime.
If you generate a new salt then the hash will change everytime you calculate it (and since it is a random value you cannot get it back...).
By the way, why not a simple MD5?
$pass = md5( $pass.$site_key );
Edit: please don't do that (the md5 thing I mean)! Mine here is an old and wrong suggestion. Find an updated resource online and choose a secure algorithm if you need to store passwords (php now also has password hashing and verifying functions that should be secure, https://www.php.net/manual/en/function.password-hash.php, check in the comments for further suggestions).

Categories