使用salt/password/hash进行密码验证时出现问题


Trouble with password verification with salt/password/hash

我有一个函数可以通过生成salt、将其附加到密码并对组合进行哈希来创建新用户。我有另一个用于用户登录验证的功能,它获取用户输入的密码,并将其添加到用户的唯一salt、hashes中,并与数据库中的加密密码进行比较(请参阅整个代码中的注释)。

我已经回显了userValidate()函数中的所有重要变量,但我永远无法从数据库中获得与加密密码匹配的hash+用户密码。有人能告诉我我做错了什么吗?

创建用户功能:

function createNewUser($firstName, $lastName, $email, $password, $address, $city, $state) {
    $conn = connectPDO();
    // Create a salt
    $salt = mcrypt_create_iv(64, MCRYPT_DEV_URANDOM);
    // Add salt to password
    $salted_password = $salt.$password;
    // Hash salt/password combination, to be added to "password" column of database
    $encrypted_password = hash('sha256', $salted_password);
    $datetime = date("Y-m-d H:i:s");
    $stmt = $conn->prepare("INSERT INTO users (`first-name`, `last-name`, `email-address`, 
                             `password`, `salt`, `address`, 
                             `city`, `state`, 
                             `registered-timedate`) VALUES (
                                :field1, :field2, :field3, :field4, :field5, :field6, :field7, :field8, '$datetime')");
    return ($stmt->execute(array('field1' => $firstName, 
                         'field2' => $lastName, 
                         'field3' => $email, 
                         'field4' => $encrypted_password, 
                         'field5' => $salt, 
                         'field6' => $address, 
                         'field7' => $city, 
                         'field8' => $state)));
}

验证用户登录:

function userValidate($email, $user_password) {
    $conn = connectPDO();
    $sql = "SELECT `salt`,`password` FROM users where `email-address`='$email'";
    $q = $conn->query($sql);
    $row = $q->fetch();
// Get the user's unique password salt
$salt = $row['salt'];
// Find the hashed salt/password combination
$database_password = $row['password'];
// Add salt to user's entered password and encrypt
$salted_password = $salt.$user_password;
$encrypted_password = hash('sha256', $salted_password);

// Compare the user password/salt hash to one stored in database
if($encrypted_password == $database_password) {
    return true;
} else {
    return false;
}
}

编辑:

我在注册页面上回复了我的vars,我得到了盐和许多特殊的字符,比如"J~â×/q,óõ5áczçvÁ!"4a7ec3d72f00712cf31eb8350f20e1637ae776c1902197ce2f1ae57fff0be2d1135e3a681e315aac4dc346a4ba608402f98b77a1ec126590281157faf409775700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"。我应该在盐的数据库中使用什么数据类型…并且盐析/哈希/比较不应该为每个生成相同的两个加密密码吗(因为盐仍然相同?)

我怀疑您遇到了这两个问题之一:

  1. 哈希密码的数据库字段太小,该字段必须能够存储64个字符
  2. salt的编码有问题,请记住,用mcrypt_create_iv()生成的salt是一个二进制字符串,可以包含任何字符(甚至''0个字符)

即使你能解决这个问题,你也有一个不安全的密码存储方案(SHA256对哈希密码来说太快了)。看看PHP函数password_hash(),它将生成一个BCrypt哈希,并负责生成一个安全的salt。盐将是生成的62个字符串的一部分,因此不需要单独存储盐。还有一个针对旧PHP版本的兼容性包。

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);