I realize this is not as secure as it could be, but I want to do it this way.
I have this code which generates the password from a user's entry ($password)...
$salt = mcrypt_create_iv(22, MCRYPT_DEV_URANDOM);
$new_password = md5($salt . $password);
$new_password = $salt . $new_password;
This is how I'm trying to check against the saved password:
$split_salt = substr($saved_password, 0, 22);
$incomplete_password = md5($split_salt . $current_password);
$hashed_password = $split_salt . $incomplete_password;
if ($saved_password != $hashed_password) {
$error = "error";
} else {
//Validated
}
As far as I can tell this should work. However, I'm getting the error instead of the validation. Does this have something to do with MCRYPT not producing exactly 22 characters?
I know this is not what you want to hear, but your scheme is so utterly unsafe and a good solution is so simple to implement, that you should reconsider:
// 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);
Your actual problem is the salt, mcrypt_create_iv() will return a binary string and it can very well contain \0 characters. So it is pure luck if your approach works or not.
Related
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
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.
i'm sorry for the bad use of English... I'm having a problem with making a function that hashes my password with a salt(first time using a salt).
The problem is that I don't know how to really return the salted/hashed password from the function.
My code:
# Password hashing with a salt.
function hashing($stringPassword)
{
// Making a random uniq code as salt.
$salt = uniqid(mt_rand(), true);
$HASH512 = hash('SHA512', $stringPassword);
$hashPassword = $salt.$HASH512;
return $stringPassword;
}
And how I tried to test it:
<?php
$stringPassword = '482301';
hashing($stringPassword);
echo $hashPassword;
?>
Thank you for helping!
Your code is backwards. The salt has to be part of the password BEFORE you hash it. and then you need to return the hashed password AND the salt, so that you can do proper comparisons later.
function hashing($cleartext) {
$salt = uniqid(mt_rand(), true);
$hash512 = hash('SHA512', $salt . $cleartext);
return(array('hash' => $hash512, 'salt' => $salt));
}
$foo = hashing('letmein');
echo "Salt is: $foo[salt]";
Since you are hashing passwords, you should be aware that the SHA* algorithms are not appropriate to hash passwords. They are much too fast, instead you need a function with a cost factor like BCrypt or PBKDF2 where you can control the necessary time for the calculation.
PHP offers a dedicated function password_hash() to generate BCrypt hashes, for earlier PHP versions you can use the compatibility pack:
// 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);
I'm trying to hash the password if you sign up on my website, but it doesn't work.
This is my code to hash the password upon signing up:
$escapedName = mysql_real_escape_string($_POST['user']);
$escapedPW = mysql_real_escape_string($_POST['password']);
$salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
$hashedPW = hash('sha256', $escapedPW . $salt);
Then I just insert it in a database (the hashed password and the salt).
For example, when I hash Sas, with the following salt:
abac7ad23185ad19967f0d13e962197962782f0b7ec32d9889c27a93a9e800fa
This is the hashed password:
8ca5c5f31fafbf382533dbcbfc22b3635d776ec7770c7eac58d8ef9f1fa3613c
But when I try to hash the password on log in, with the exact same password and salt, this becomes the hashed pass:
6eb4b16444f18cee19db32bd29a39970e3019c5b1972a982ae4cb9a59642dffc
This is the code I use to login:
$escapedName = mysql_real_escape_string($_POST['user']);
$escapedPW = mysql_real_escape_string($_POST['password']);
$saltQuery = mysql_query("SELECT salt FROM members WHERE user='{$escapedName}'");
while($result = mysql_fetch_assoc($saltQuery)) {
$salt = $result['salt'];
}
$hashedPW = hash('sha256', $escapedPW . $salt);
$sql = mysql_query("SELECT * FROM members WHERE user='$escapedName' AND pass='$hashedPW'; ");
while ($res = mysql_fetch_assoc($query2)) {
$username = $res['user'];
$PW = $res['pass'];
}
I hope it's not too much code and I also hope you will understand my question.
Sorry I can't comment but something tells me that there is a length restriction on the salt column in your database.
Example: The salt field might only allow a 64 characters while the generated salt might be longer therefore when you save the salt it gets trimmed which ultimately changes the hashed password.
If that's the case, you might want to trim the salt before saving it.
I'd advise using PDO to make queries against your database.
Your inputs to the hash function must be different for some reason or other.
Add log output messages that print your inputs before you hash for both use cases (create user and login). Also be sure to put quotes around the inputs in your logging to show whitespace issues.
Compare the raw inputs as well as the output of the hash function in both cases, and there will be a difference somewhere. If there is no difference, and the output of the hash is the same, then there is a problem in your query that is looking up the user in the login case.
Whatever you're doing, it's insecure if you WANT the hashes to be the same! See http://php.net/crypt for proper password hashing.
All you need:
function check_password($password) {
...//get db password to compare
if (crypt($post_password, $db_results[0]['password']) == $db_results[0]['password']) {
return true;
} else { return false; }
}
I have been trying to learn about hashes and salts stored in a users table withing a mysql DB. I get through with storing them but can't seem to wrap my head around how to validate when the user logs in.
I have looked through and seen about storing the salt and hash seperately and together. The salt that I am producing is random.
Any ideas?
I have posted my code.
<?php
$password = 'passwordwhatever';
//generate the salt
function gen_salt() {
$salt = uniqid(mt_rand(), true) . sha1(uniqid(mt_rand(), true));
$salt = crypt('sha512', $salt);
return $salt;
}
//generate the hash
function gen_hash($salt, $password) {
$hash = $salt . $password;
for($i = 0; $i < 100000; $i++) {
$hash = crypt('sha512', $hash);
}
$hash = $salt . $hash;
return $hash;
}
$password = gen_hash(gen_salt(), $password);
echo $password;
?>
As long as you produce the same salt, it shouldn't matter too much. Store it in your db, in configuration, as long as you can get to it. The effort of reversing a SHA512 hash is so high that unless you're the Pentagon, nobody will bother. The point is that you want to be able to repeat the hash with the same salt so you can be very sure that the input was the same without having to store the sensitive input. If that makes sense.
The salt is going to need to be contained somewhere within the database (or somewhere). Some options are to append the salt to the hash or stored as its own field. I like appending it to the hash.
$password = $salt . '.' . $hash;
Then when the user goes to login, you grab his password, break it into the hash and the salt, and use your password generation function (with the salt from the password instead of a random salt) to determine if it matches the password in the db.
list($salt,$hash) = explode('.', $password);
$check = gen_hash($salt, $input_pass);
if ($check === $password)
// valid
Maybe you should take a look on bcrypt. This might help you. I wrote some tutorials but they are in german. Oh and PHP 5.3 support bcrypt natively.