PHP在将密码存储到数据库之前加密密码

时间:2012-01-28 12:38:30

标签: php

我在php.net上找到了以下示例,以便在存储之前保护密码。但是,我不太了解第3行。有人可以解释一下吗?谢谢!

1 <?php
2 $password = crypt('mypassword'); // let the salt be automatically generated

3 if (crypt($user_input, $password) == $password) {
4   echo "Password verified!";
5 }
6 ?>

4 个答案:

答案 0 :(得分:4)

crypt 是一个单向函数,它返回一个已包含salt的字符串,

将用户输入与crypt结果进行比较时,该函数会自动从字符串中提取盐。

更清楚:

crypt()输出一个包含salt和hash结果的字符串。当你将该字符串作为salt传递时,它知道只提取salt部分并忽略散列部分。它仍然返回一个包含salt和hash的字符串。所以可以比较这些字符串

您可以通过以下方式清楚地理解:

当用户第一次注册时,过程为:

 $password = crypt($user_input); // let the salt be automatically generated

 if (crypt($user_input, $password) == $password) {
   echo "Password verified!";
 }

当用户尝试登录时,过程将为:

if(crypt($user_passsword_currentlyin_db, $user_inputted_password) == $user_inputted_password) {
      echo "Password verified!";
}

希望你得到的东西:)

修改

crypt的输出包括:

当您将此输出传递为&#34; salt&#34;回到crypt,它会提取正确的算法和salt,并将它们用于操作。如果只提到一个算法,它会使用这个算法并生成随机盐。否则,它将选择默认算法并生成随机盐。传递的salt参数中的哈希部分将被忽略。

所以你可以简单地将你的stored_hash与crypt(密码,stored_hash)进行比较 - 如果它相等,很可能是正确的密码。

这是一个伪代码解释(用类似PHP的语法)如何工作:

function crypt($password, $salt)
{
   if (substr($salt,0 1) == "_") {
     $count = substr($salt, 1, 4);
     $real_salt = substr($salt, 5, 4);
     return "_" . $count . $real_salt . crypt_ext_des($password, $count, $salt);
   }
   if(substr($salt, 0, 3) == "$1$") {
     list($ignored, $real_salt, $ignored) = explode("$", $salt);
     return "$1$" . $real_salt . "$" . crypt_md5($password, $real_salt);
   }
   if(substr($salt, 0, 4) == "$2a$") {
      $cost = substr($salt, 4, 2);
      $real_salt = substr($salt, 7, 22);
       return "$2a$" . $cost . "$" . $real_salt . crypt_brypt($password, $real_salt, $cost);
  }
  // ... SHA256 and SHA512 analogons

  // no match => STD_DES
  $real_salt = substr($salt, 0, 2);
  return $real_salt . crypt_std_des($password, $real_salt);
}

答案 1 :(得分:1)

如果密码文件被泄露并显示用户密码,则不应在服务器端存储纯文本密码,这是一种良好的安全措施。

相反,当用户注册时,您应该在将密码存储到数据库之前对密码使用单向哈希算法。这样,如果文件被泄露,则无法重现用户的密码。

当用户登录时,无法将刚刚输入的明文密码与数据库中的密码进行比较,因为数据库中的密码已经过哈希处理。

但是,因为哈希函数的相同输入将始终产生相同的输出,所以第3行将对用户刚刚输入的明文输入进行哈希处理,并将其与存储在数据库中的哈希进行比较。这样你就可以将哈希与哈希进行比较,并且可以确定用户是否经过身份验证。

关于安全性的一些注意事项:您应该始终是故障安全的,因此您的代码应该是:

if(crypt($user_input, $password) == $password) {
   echo "Password verified!";
} else { die("Wrong username/password"); }

另请注意,可以使用彩虹表重建受损密码文件。

答案 2 :(得分:0)

$ user_input只是您的密码,存储在DATABASE

if(crypt($stored_passsword_in_db, $current_password) == $current_password) {
 echo "Password verified!";
}

希望这可以帮助你......

答案 3 :(得分:0)

第二个参数是关键。它接受了crypt之前所做的任何事情,一个盐或哈希,它具有嵌入其中的哈希值。在第一种情况下,制成盐。在后一种情况下,使用salt而不是整个哈希。所以这就行了(确保你理解,因为这是理解第3行的关键):

crypt($input, $salt) == crypt($input, crypt($input, $salt))

您在数据库中拥有的用户哈希密码是该等式中的左侧术语。所以第3行可以改写为:

if (crypt($user_input, crypt('mypassword')) == crypt('mypassword'))

盐在第2行自动生成,我们假设它等于'自动盐'。现在可以将第3行重写为:

if (crypt($user_input, crypt('mypassword', 'autosalt')) == crypt('mypassword', 'autosalt')

然后你去:只有$user_input == 'mypassword'才会出现这种情况。