Say I wanted to store a password for a user, would this be the right way to do it with PHP 5.5's password_hash()
function (or this version for PHP 5.3.7+: https://github.com/ircmaxell/password_compat)?
$options = array("cost" => 10, "salt" => uniqid());
$hash = password_hash($password, PASSWORD_BCRYPT, $options);
Then I would do:
mysql_query("INSERT INTO users(username,password, salt) VALUES($username, $hash, " . $options['salt']);
To insert into database.
Then to verify:
$row = mysql_fetch_assoc(mysql_query("SELECT salt FROM users WHERE id=$userid"));
$salt = $row["salt"];
$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10, "salt" => $salt));
if (password_verify($password, $hash) {
// Verified
}
It is a one-way algorithm, in that you don't decrypt it to validate it, you simply pass the original string in with your password and if it generates the same hash for the provided password, you're authenticated. It's best to omit the salt and let it generate one for you.
password_hash() creates a new password hash using a strong one-way hashing algorithm. The following algorithms are currently supported: PASSWORD_DEFAULT - Use the bcrypt algorithm (default as of PHP 5.5. 0). Note that this constant is designed to change over time as new and stronger algorithms are added to PHP.
Is password_hash good enough?" Yes it is safe enough, and yes there is a better/safer way. As of PHP 7.2, Argon2 is part of a newly implemented (hashing) method that won the Password Hashing Competition which offers a more robust method, should you want to upgrade your version of PHP to 7.2.
You can't decrypt it. A hash is a one-way function. Hash the password the user has given you and see the the hashes match.
Ignoring the issues with your database statements for now, I'll answer the question regarding password_hash
.
In short, no, that is not how you do it. You do not want to store the salt alone, you should be storing both the hash and salt, and then using both to verify the password. password_hash
returns a string containing both.
The password_hash
function returns a string that contains both the hash and the salt. So:
$hashAndSalt = password_hash($password, PASSWORD_BCRYPT);
// Insert $hashAndSalt into database against user
Then to verify:
// Fetch hash+salt from database, place in $hashAndSalt variable
// and then to verify $password:
if (password_verify($password, $hashAndSalt)) {
// Verified
}
Additionally, as the comments suggest, if you're interested in security you may want to look at mysqli
(ext/mysql
is deprecated in PHP5.5), and also this article on SQL injection: http://php.net/manual/en/security.database.sql-injection.php
Using your own salt is not recommended and, as of PHP 7, its use is deprecated. To understand why, the author of password_hash
shared these thoughts (link defunct)
One thing has become abundantly clear to me: the salt option is dangerous. I've yet to see a single usage of the salt option that has been even decent. Every usage ranges from bad (passing mt_rand() output) to dangerous (static strings) to insane (passing the password as its own salt).
I've come to the conclusion that I don't think we should allow users to specify the salt.
He even made this comment in SO chat noting how bad passing your own salt can be
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With