I have some code here for a login system, that is purely or learning purposes, created with some major help from the great people of stackoverflow, and i was told not to store the salt and the hash seperate, but rather, together. I am wondering how I am going to compare the passwords when the user tries to login. if the salt is not stored, how can i compare the two. Can anyone help?
require("constants.php");
$DBH = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
function createSalt() {
$length = mt_rand(64, 128);
$salt = '';
for ($i = 0; $i < $length; $i++) {
开发者_Python百科 $salt .= chr(mt_rand(33, 255));
}
return $salt;
}
//Salt function created by ircmaxell
function registerNewUser() {
//Check to see if Username Is In Use//
$q = $DBH->prepare("SELECT id FROM users WHERE username = ?");
$username = filter_var($username, FILTER_SANITIZE_STRING);
$data = array($username);
$q->execute($data);
$row = $q->fetch();
if ($row === false) {
//If Username Is Not Already In Use Insert Data//
$hash = hash('sha256', $pass);
$salt = createSalt();
$hash = hash('sha256', $salt . $hash . $pass); //UPDATED
$data = array($username, $hash, $salt);
$qInsert = $DBH->prepare(
"INSERT INTO users (username, password, salt) values (?, ?, ?)"
);
$qInsert->execute($data); //Inserts User Data Into Table//
}
}
You have to query your database to retrieve the user row (if any), get the salt and use the same algorithm over the password provided by the user. If both hashes matches the user provided a good password.
doing some code it would make something like this:
$qSelect = $DBH->prepare('SELECT salt,password FROM users WHERE username = ?');
$qSelect->execute();
$qSelect->bind_result($salt, $db_password);
$qSelect->fetch();
if($salt == null){
// username doesn't exist
return;
}
$hash = hash('sha256', $pass);
$hash = hash('sha256', $salt . $hash . $pass);
if($hash == $db_password){
// login ok
} else {
// login nok
}
Do the same work:
$hash = hash('sha256', $row['salt'] . hash('sha256', $pass) . $pass);
if ($row['password'] == $hash) {
// the password is correct
}
Where $row
has been taken from the database according to the username, and $pass
is the password retrieved from the form.
Also, it is pointless to include password in the hash twice: hashed and plain text one
$hash = hash('sha256', $salt . $pass); // this would be enough
Issues:
1) Your method for creating a password hash of the hash+salt is non-traditional. This isn't strictly an issue, it just isn't what it seemed like you wanted. zerkms made this point pretty clearly.
2) Your database insert requires either that username is a unique column and is missing some exception handling, or it is vulnerable to a race that will result in multiple users with the same username and different passwords (and different IDs if that is a key)
精彩评论