I know this question is asked so many times and there are many tutorials about this thematic but I can't explain what I'm doing wrong. Could you pls tell me what is wrong in my code? The database connection works as it should, but I don't know where the problem is or if I understood something wrong, when I don't hash the password and entry it directly there is no problem. No matter what I entry my login will not work and always returns "false".
Here is my code (note, I have a custom DBConnector class that handles variable types)
public function insertUser(){
if (isset($_POST['name']) && isset($_POST['password'])){
try
{
$name = $_POST['name'];
$password = $_POST['password'];
$db = CDatabase::getInstance();
//check if username is already in use
$db->prepare("SELECT * FROM user where LOWER(name) = LOWER(?)");
$db->bindParams(array($name));
$db->execute();
$result = $db->fetch();
//if no user with the same name was found
if ($result->num_rows == 0){
//insert user without password
$db->prepare("INSERT INTO user (name) VALUES(?)");
$db->bindParams(array($name));
$db->execute();
//get user_id of last inserted user because I use user_id as salt
//pls feel free to correct me if this is stupid
$user_id = $db->getLastInsertedId();
$salt = $user_id;
//hash password with user_id
$saltedHash = hash('sha256', $password, $salt);
var_dump($saltedHash);
//update user with password
$db->prepare("UPDATE user set password = ? where user_id = ?");
$db->bindParams(array($saltedHash, $user_id));
$db->execute();
//since I call this function via ajax true -> user is inserted correct
echo "true";
}else{
echo "Error: name is already in use";
}
}
catch(Exception $e)
{
$this->m_renderer->loadTemplate('error.html');
$this->m_renderer->assign(array('errorcode' => 6000, 'errormessage' => $e->getMessage()));
$this->m_renderer->render();
}
}
}
And this is my login function
public function loginUser(){
if (isset($_POST['name']) && isset($_POST['password'])){
try
{
$name = $_POST["name"];
$password = $_POST['password'];
$db = CDatabase::getInstance();
$db->prepare("SELECT * FROM user where LOWER(name) = LOWER(?)");
$db->bindParams(array($name));
$db->execute();
$result = $db->fetch();
if ($result->num_rows > 0){
$row = $result->fetch_assoc();
$salt = $row["user_id"]; //use user_id as salt
$saltedHash = $row["password"];
var_dump($password);
var_dump(hash('sha256', $password, $salt));
var_dump($saltedHash);
if (hash('sha256', $password, $salt) == $saltedHash) {
echo "correct";
} else {
echo 'Error: password incorrect';
}
}else{
echo "Error: username does not exist";
}
}
catch(Exception $e)
{
$this->m_renderer->loadTemplate('error.html');
$this->m_renderer->assign(array('errorcode' => 6000, 'errormessage' => $e->getMessage()));
$this->m_renderer->render();
}
}
}
And this is the output from my console
string(32) "��Ё�L}e�/���Z���O+�,�]l�� //insertUser hash('sha256', $password, $salt);
"
true
string(4) "test"
string(32) "��Ё�L}e�/���Z���O+�,�]l�� //loginUser hash('sha256', $password, $salt)
"
string(31) "????L}e?/???Z???O+?,?]l?? //this value is in my database
"
Error: password incorrect
I'm using the latest version of XAMPP on my local machine
Thank you very much
The problem is that hash()
returns binary data, which you're apparently not handling/storing as binary data in the database, which corrupts the hash.
The bigger problem is that you're using hash()
in the first place. The even bigger problem is that you're using it incorrectly. See its signature:
string hash ( string $algo , string $data [, bool $raw_output = false ] )
Nowhere does it accept a salt. What you set as $salt
is actually $raw_output
, which is why you're getting binary data from it.
A single unsalted SHA-256 round is also nowhere close to being secure for password storage; your hashed passwords are prime for a rainbow table attack, which probably already exists somewhere.
Stop using hash
, use password_hash
and password_verify
instead. See their examples for how to use them exactly.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments