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
}
You should not enter own salt, leave salt empty, function will generate good random salt.
Insert into database (or file or whatever you use) whole the string returned by the function. it contains: id of algorithm, cost, salt (22 chars) and hash password.
The entire string is required to use password_verify (). Salt is random and does not harm to fall into the wrong hands (with hashed password). This prevents (or very difficult) to use ready sets generated lists of passwords and hashes - rainbow tables.
You should consider add cost parameter. Default (if omitted) is 10 - if higher then function compute hash longer. Increasing the cost by 1, double time needed to generate a hash (and thus lengthen the time it takes to break password)
you should set this parameter based on speed check on your server. It is recommended that the function performed 100ms+ (some prefer to make it 250 ms). Usually cost = 10 or 11 is a good choice (in 2015).
To increase security, you might want to add to passwords a long (50-60 characters is good choice) secret string. before you use password_hash() or password_verify().
If $password will be longer than 72 chars and you change or add 73 or 90 characters hash will not change. Optional, sticking $secret_string should be at the end (after the user's password and not before).
Using your own salt is not recommended and, as of PHP 7, its use is deprecated. To understand why, read the author's thoughts
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:Then to verify:
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.phpNote this from php.net
Conclusion? Forget about salt option.
This would be quite enough
password_hash('password', PASSWORD_DEFAULT)
*(or _BCRYPT)