0

我有一个注册页面,允许用户输入密码。我在注册时对密码进行哈希处理,以便更安全地存储在数据库中。

当用户使用相同的密码登录时,两个哈希不匹配,用户无法登录。

这是我第一次使用哈希,它的行为不像我预期的那样:

这是注册页面上的哈希码:

$salt ="";     
function cryptPass($input, $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($input, sprintf('$2y$%02d$test$', $rounds) . $salt);
}
$hashedpass = cryptPass($pass1);      
echo $hashedpass;
//************Insert all the members's input to the database**************************//
      $query = mysql_query("INSERT INTO members(user_name, first_name, last_name, governorate, district, village, birth_date, email_address, specialization, password, salt, registered_date )VALUES('$username', '$firstname', '$lastname', '$governorate', '$district', '$village', '$bdate', '$email', '$specialization', '$hashedpass', '$salt',  now())")or die(mysql_error());    

我确实加了盐,但它给空了

这是登录页面上的哈希码

function cryptPass($input, $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($input, sprintf('$2y$%02d$test$', $rounds) . $salt);
}
$hashedpass = cryptPass($pass);   
echo $hashedpass;


$sql=mysql_query( "SELECT user_id, email_address, first_name, user_name FROM members WHERE email_address='$email'AND password= '$hashedpass' LIMIT 1") or die("error in members table");
$login_check = mysql_num_rows($sql);

  if($login_check > 0)the hashing password = $2y$09$test$4ZGgCiXdKzgQvuzwu.AxfdWvZadDCE.LD6HCkrK3ZsqJeN7e 
4

4 回答 4

1

当用户注册时,您需要在数据库中存储盐和散列密码。当用户尝试登录时,您需要使用与注册时相同的盐,否则哈希将不同。这称为每用户盐,是更安全的选择。

一个更简单但安全性较低的选项是为应用程序生成一个盐值并将其用于所有用户。这将具有将所有密码散列在数据库中的效果,但安全性要低得多,因为如果该盐值被泄露,暴力破解散列密码是一件小事。

于 2013-05-19T07:50:52.220 回答
0

您需要将盐与散列密码一起存储在数据库中。

当用户尝试登录时,您需要从数据库中获取 salt,并将用户输入与它进行哈希处理,以将其与哈希密码进行比较。

在您的示例中,您在登录过程中生成了一个随机盐,它永远不会产生与数据库中相同的哈希。

于 2013-05-19T07:44:13.177 回答
0

密码加盐通过在散列密码之前将预定义的随机明文集附加到密码来工作。这避免了两个选择相同密码的用户有两个相同的哈希值。想象一下您系统的两个用户 user1 和 user2,选择“ letmein ”作为密码:

salt_user1 = 'awoidjalskdm'   
hash = MD5('letmein'+salt_user1) = ab82a9c495e3fe88d1986176e4850b1d

对于用户 2

salt_user2 = 'duiesnblekfn'
hash = MD5('letmein'+salt_user2) = 69caac44b5ee9f8b6468b5625000723a

假设您的数据库结构类似于 username:salt:password_hash,您将拥有:

user1:awoidjalskdm:ab82a9c495e3fe88d1986176e4850b1d
user2:duiesnblekfn:69caac44b5ee9f8b6468b5625000723a

密码加盐的主要目的是在您的数据库遭到破坏时避免大规模密码泄露。密码加盐将使破解由几个不同用户选择的简单和流行密码变得更加困难。

在您的情况下,您似乎正在随机生成盐以进行注册(这很好)。错误似乎出在登录函数中,您在其中重新计算了一个随机盐,而不是检索早先生成且应该存储的盐。

在散列之前附加到密码的盐对于每个用户来说必须是相同的,并且您需要能够在需要时调用它。尽管它看起来很矛盾,但这意味着它必须以明文形式存储在数据库中。

于 2013-05-19T16:24:30.647 回答
0

如果您要自己编写,则需要将生成的盐存储在数据库中(正如其他响应者所说)。更一般地说,我会尝试尽可能多地委托给提供开箱即用密码支持的外部库。获得正确的加密是很困难的,你真的需要在开始自己滚动之前阅读更多内容。那里有很好的图书馆支持。你应该使用它。

此外,您真的不应该使用 MD5 来散列密码。使用 bcrypt、pbkdf2 或其他适合密码的散列。只需使用图书馆。

于 2013-05-19T08:02:45.710 回答