我在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 ?>
答案 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'
才会出现这种情况。