When validating user logins, is it safe to first search for the username and THEN if found, retrieve the hashed password and salt and compare it with the user input?
Or, should the salt for the user-inputed username be retrieved by itself, then be hashed with the inputed password and compared with the final hash in the database?
In essence, is it safe to store a password for an inputed username from a database before knowing whether the password the user entered is valid?
If you look at the examples of the PHP Password Hashing API https://github.com/ircmaxell/password_compat the answer is: No, you read the user from the database and compare the stored password hash with the password you just got from the login form.
And please try to use this library - PHP 5.5 will support the functions natively, and if you are on PHP 5.3.7 and later, it sounds like a very good idea not to reinvent the wheel and simply use these functions. Doing your own thing is more likely to be attackable.
You may check both loginname and password at the same time. Get the raw password; salt it, then check if salted password and username combination exist. Ofcourse, password in db should have been salted and hashed before.
if($loginname AND $loginpass){
$loginpass=sha1($salt1.$loginpass.$salt2,$raw_output=false );
$userinfo_query="SELECT * FROM users WHERE user_name='$loginname' AND user_pass='$loginpass' LIMIT 1";
}
Related
I have a database with accounts that still use the MD5 algorithm which is old and unsafe, so I wanted to update the passwords with the password_hash function in php.
I made a login for users with a md5 password so they can be prompted with an update field to update their password. It all works and I see the new hash string in the database. But when I want to login using their new password it's just not possible.
I use a PDO update query to update the passwords, does anyone have a solution or know if this is even possible?
Thanks in advance,
Bram.
EDIT:
This is the code I use to verify the passwords.
if (password_verify($password, $rowofusers['passwordhere'])) {
//code here
}
As mentioned, the correct way to do this can be completely transparent to the user and should not require an "update password prompt".
When the user tries to log in take the following steps to modify your login process accordingly.
Check if the hash in the db starts with $2y$ to determine if the password should be check with md5 or password_verify. If it does start with $2y$ then just use password_verify and ignore the remaining steps (continuing on with the rest of your normal login process).
If the password hash in the database does not start with $2y$ then first, check the plain-text password against its md5 hash.
If the plain-text password's hash doesn't matches the md5 hash in your database continue with normal failed authentication process and ignore the remaining steps here
If the plain-text password's hash does match the md5 hash in your database then take the plain-text password and run it through password_hash and update your database with the newly generated BCRYPT hash from password_hash.
You would have to keep this code in your login process until all passwords in your database have been updated and no remaining md5 hashes are left. The user will never know that their password hash is updated and never be prompted to enter their password twice as it's completely unnecessary.
What method can I apply if I want a user to edit their original password after storing as hash.
A website that shows a user their password is VERY insecure. Always hash it and never show the user their password. If they forget their password have the user reset their password and rehash it and replace it in their database. But NEVER show the user their password and ALWAYS hash.
DO NOT store an unhashed password in the database.
DO NOT show passwords in the 'change password form'
DO NOT show password hashes anywhere.
Provide the user with a form to edit the password but do not provide the previous one. Just show the user an empty text box for inserting a new password while also having a text box for the user to input their current password.
You can check any password hashed with password_hash() using password_verify().
If password_verify() returns true just use an UPDATE query to change the stored hash.
As for the suggestion of saving it, please, do never store unencrypted passwords in your database: every single of them will be exposed if your database is ever accessed.
As for your question: an encrypted or hashed word is very difficult (or plainly impossible, are you hashing or encrypting?) and costly to restore. I understand the usability issue but once a password is stored the user should never be able to query it (that's what we have password recovery measures)... So, in short, you could have them create new passwords but you can't have them editing the one they have since you don't even know it.
PS: All this assumes that the password is already been stored. Of course... If we're talking about html password tags the issue is different.
My database stores unique salts for every user.
I'm creating a login script in php for an application where each user has it's own unique salt and here's how I plan to implement the login.
User enters details and sends them
Username is sent and script check if it exists
If it does then returns the salt for that user otherwise general error is returned
I need the script to return the salt for that user because otherwise how would my app verify that the submitted password is correct when it cannot hash the password without the salt and send it back?
Now here's what I'm unsure about. Does it matter whether the salt is encrypted or not because a hacker could just see what it is and see the password hash and maybe could do something with it. Should I encrypt the salt before I send it?
Maybe I'm not understanding/overlooking something in the replies below.
Advice needed please.
It doesn't matter if your salts are hashed or left as plain strings - the important point is that salting a password prevents the direct use of dictionary/rainbow table attacks to brute-force crack passwords. An added advantage is that each user has a different hashed password as a result.
Salts are randomly generated string that are created server-side and don't involve any kind of transmission to or from the browser.
On your server:
// Password from form
$pw = $_GET['password'];
// Generate salt using unique values
$salt = (rand(8).$registration_date.$username);
// Password to be hashed
$pwthb = ($pw.$salt);
If a hacker gains access to your databases, then your game is over in the majority of cases as you need to store the initial random salt to hash it for comparison.
A simple example:
User enters initial password in browser upon registration
On your server, password is combined with a unique salt, hashed and stored as password in DB
Salt is stored in DB
Note: hashing can be done using PHP or using MySQL/DB functions
When the user returns:
User enters password in browser
Grab salt from DB and combine with the password entered
Hash password+salt and compare with stored/hashed password
If they match: authenticate
In terms of further reading, It's probably worth looking over the following:
Is encrypting a salt value with a password/plaintext a viable alternative to straight up hashing?
The necessity of hiding the salt for a hash
How store salt in distributed environment
I'm using salt to encrypt my users' passwords.
I'm using PHP, and here's a quick sample of what happens during a users registers.
Here it is:
PHP code:
// Gives me my random key. My salt generator.
$salt = uniqid(mt_rand());
// My password via what users inputs.
$userpwd;
// Then the encryption. I use a HMAC hash.
$encrypted = hmac_hash("sha256", $userpwd, $salt);
?>
Now that all works for me in my script. But my question is, how do I authenticate a user logging in? The new encrypted password is random, so I can't compare the password from the login form to the saved encrypted password in the database.
I've searched and can't find a solution. Maybe I haven't searched hard enough, but is there a way to decrypt the password? What can I do to authenticate the user with my script?
You need to generate a unique salt for each user's password, and then store the value of the salt somewhere you can retrieve it. For example, by saving the salt to a user table along with the username and hashed password. That way you can extract the known salt and run it through your function when you go to authenticate a user.
Here is an article that contains more information: Storing Passwords - done right!
And for more information about salts: salt-generation-and-open-source-software
You hash the user's inputted password the same way, then compare if the hash is the same as the one you stored.
if (hmac_hash("sha256", $_POST['password'], $saltFromDatabase) === $hashFromDatabase)
$login = true;
You also have to store the salt since it's different for each user. I would also recommend using a second salt that is constant across the application (stored on a hard config file, so that even if the database is compromised, the passwords are still safe).
Note: Hashing is not the same as encryption; It is an irreversible process.
You encrypt the password used to log in and compare it with the encrypted password in your database. :)
You compute the hash of the password user has entered, just as you do when registering them. Note that the code is semi-pseudo code, you need to adapt it to your libraries or functions.
$res = db('SELECT etc FROM users WHERE user=? AND pass=?',
$_POST['user'], hmac_hash("sha256", $_POST['pass'], $salt));
if(numRows($res) > 0) {
// continue with authentication
}
If the salt is stored in the db, then you have to either fetch it first, or do the comparison in the db.
You don't decrypt what you've stored. You hash the entered password and compare it with what was stored at registration. This is because if two hashes match then (to all intents and purposes) you can be confident that the source data matches.
Your salt needs to be constant, and not random. That way when you are checking the password against the hash, all you have to do is hash the input with the salt again, and the resulting hash should be the same as what came out before.
Please try to search StackOverflow before asking a question. Many questions are already answered. For example:
PHP & MySQL compare password
how do I create a mySQL user with hash(‘sha256’, $salt . $password)?
Secure hash and salt for PHP passwords
User Login with a single query and per-user password salt
Non-random salt for password hashes
Hi
I want that nobody can see my password even in database..
So i used hash function like this
$passowrd_hash=hash('shal',$_POST['password']);
Now easily I can store this password_hash value into database. It will be something like in encrypted form.
Now user know its original password he don't know this encrypted password.
Now if he try to login through this original password..He is not able to login.
So is there any method so that it can be decrypted and user can make log in. So he can achieve both security of password as well as login again.
How to do this?
you need to hash the user input password and compare hashes.
Before comparing the posted password by the user with the one in the database, encrypt the posted password the same way as the stored password.
All you need to do is encrypt the password you type in and compare the two; the hash in the database and the one you just encrypted. If they match then the password entered is the right one. I am assuming you are using an algorithm like SHA1.
As already answered, you need to hash the password every time they re-enter it and compare the hash to what is in your database.
You ALSO should look into using salt in your hashing algorithm. There is a good deal of discussion in this question:
Secure hash and salt for PHP passwords
You dont need to decrypt it. You cannot convert back a hash to a plain text, its a one way function. So, basically you hash the input password and compare the two hash:
E.g (pseudo code):-
if hash(password entered by user) == password stored in databse Then
//logged in successfully
else
//login failed
end if
I highly recommend using md5() http://php.net/manual/en/function.md5.php.
When the user signs up, you store:
$password = md5($_POST['password']);
And when the user logs in you check:
if($_POST['password_entered'] == $passwordFromDB) :
// Log user in
else :
// Show error to user
endif;