PHP MySQL密码哈希返回始终为false

时间:2016-08-09 06:38:06

标签: php

我知道这个问题被问过这么多次,有很多关于这个主题的教程,但我无法解释我做错了什么。你能告诉我我的代码有什么问题吗?数据库连接正常工作,但我不知道问题出在哪里或者我是否理解错误,当我不对密码进行哈希并直接输入时没有问题。无论我输入什么,我的登录都不起作用并且总是返回“false”。

这是我的代码(注意,我有一个处理变量类型的自定义DBConnector类)

    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();
            }
        }
    }

这是我的登录功能

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();
            }
        }
    }

这是我控制台的输出

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

我在本地机器上使用最新版本的XAMPP
很多谢谢

1 个答案:

答案 0 :(得分:1)

问题是hash()返回二进制数据,你显然没有在数据库中处理/存储为二进制数据,这会破坏散列。

更大的问题是你首先使用的是hash()甚至更大的问题是你错误地使用它。见其签名:

string hash ( string $algo , string $data [, bool $raw_output = false ] )

它无处接受盐。您设置为$salt的内容实际上是$raw_output,这就是您从中获取二进制数据的原因。

单个无盐的SHA-256回合也无法保证密码存储安全;你的散列密码是彩虹表攻击的主要部分,可能已存在于某处。

停止使用hash,改为使用password_hashpassword_verify。请参阅他们的示例,了解如何准确使用它们。