1

我在登录我的网站时尝试验证我的密码时遇到了一个严重问题。我正在使用 php 使用下面的代码创建一个带盐的河豚加密密码。

<?php
function cryptPass($p, $rounds = 9) {
$salt = "";
$saltChars = array_merge(range('A','Z'),range('a','z'),range('0','9'));
for($i = 0; $i < 22; $i++){
    $salt .= $saltChars[array_rand($saltChars)];    
}
return crypt($p, sprintf('$2y$%02d$', $rounds) . $salt);
}
?>

这工作正常,加密密码被放入我的 mysql 数据库。问题在于登录时它不会验证。这是登录脚本。

if(isset($_POST["u"])){
 // CONNECT TO THE DATABASE
 include_once("php_includes/db_connect.php");
 // GATHER THE POSTED DATA INTO LOCAL VARIABLES AND SANITIZE
 $u = mysqli_real_escape_string($db_connect, $_POST['u']);
 include_once("php_includes/hasher.php");
 $p = (cryptPass($_POST['p']));
 // GET USER IP ADDRESS
$ip = preg_replace('#[^0-9.]#', '', getenv('REMOTE_ADDR'));
 // FORM DATA ERROR HANDLING
 if($u == "" || $p == ""){
     echo "login_failed";
    exit();
 } else {
 // END FORM DATA ERROR HANDLING
     $sql = "SELECT id, username, password FROM users WHERE username='$u' AND activated='1' LIMIT 1";
    $query = mysqli_query($db_connect, $sql);
    $row = mysqli_fetch_row($query);
     $db_id = $row[0];
     $db_username = $row[1];
    $db_pass_str = $row[2];
     if($p != $db_pass_str){
         echo "login_failed";
        exit();
     } else {
//goto the users account

我不应该对传入的用户数据运行 cryptPass 函数吗?

另外值得注意的是mysql数据库密码列设置为VARCHAR(255),因此它有足够的空间。此时密码正确,我无法将其与数据库中的密码进行正确比较。这是我第一次真正尝试将所有教程拼凑在一起的河豚,我想按照 php.net 的建议摆脱 md5。任何帮助将不胜感激。提前感谢您阅读本文。

4

2 回答 2

1

crypt()下面是 PHP手册页上的更深入的演示:

// Only for demonstration, see mcrypt_create_iv() for a better salt:
//   http://php.net/manual/en/function.mcrypt-create-iv.php
$salt = substr(sha1(date('r')), rand(0, 17), 22);
$cost = 10;
$hash = '$2y$' . $cost . '$' . $salt;
$pass = 'mypass';
$notpass = 'notmypass';

$hashed = crypt($pass, "$hash");

echo "
Hash:
$hash

Hashed:
$hashed

Verified: 
" . crypt($pass, $hashed) . "

Not Verified: 
" . crypt($notpass, $hashed);

https://ignite.io/code/51323c3aec221e7b73000000

这给出了(至少这次):

Hash:
$2y$10$a80ded6289240c2e41a5e4

Hashed:
$2y$10$a80ded6289240c2e41a5euUFPvmt.sb6lBwOE.JTAdxQsDWmmM.Me

Verified: 
$2y$10$a80ded6289240c2e41a5euUFPvmt.sb6lBwOE.JTAdxQsDWmmM.Me

Not Verified: 
$2y$10$a80ded6289240c2e41a5euj06Emi8HigWM6BpqVFZ.ZtpA9wK5c8G
于 2013-03-02T17:52:52.773 回答
0

要验证密码,您需要用于创建第一个密码哈希的 salt。这个盐包含在crypt()函数的输出字符串中,crypt 可以从密码哈希中提取这个盐。

当您查看 PHP 5.5 中的新哈希函数时,您可以很好地了解它是如何工作password_hash()password_verify()......

$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

...验证登录密码的功能,需要第一个密码的哈希值。然后它可以从这个字符串中提取盐和成本因子,以使用相同的参数对登录密码进行哈希处理。

我可以推荐这个新功能,早期版本有一个兼容包

于 2013-03-02T17:54:06.717 回答