我一直在使用PHP的crypt()
函数将密码存储和验证到我的数据库。我对其他事情使用哈希算法,但对于密码使用crypt()
。文档并不是很好,而且似乎存在很多争论。我正在使用Blowfish和两个盐来加密密码并将其存储在数据库中。以前我会存储盐和加密后的密码(就像盐值哈希一样),但意识到这是多余的,因为盐已经成为加密密码字符串的一部分。
我有点困惑关于如何在crypt()
上应用彩虹表攻击,总之从安全角度来看是否正确。我使用第二个盐将其附加到密码上,以增加短密码的熵,可能有点过度设计,但为什么不这样呢?
function crypt_password($password) {
if ($password) {
//find the longest valid salt allowed by server
$max_salt = CRYPT_SALT_LENGTH;
//blowfish hashing with a salt as follows: "$2a$", a two digit cost parameter, "$", and 22 base 64
$blowfish = '$2a$10$';
//get the longest salt, could set to 22 crypt ignores extra data
$salt = get_salt ( $max_salt );
//get a second salt to strengthen password
$salt2 = get_salt ( 30 ); //set to whatever
//append salt2 data to the password, and crypt using salt, results in a 60 char output
$crypt_pass = crypt ( $password . $salt2, $blowfish . $salt );
//insert crypt pass along with salt2 into database.
$sql = "insert into database....";
return true;
}
}
function get_salt($length) {
$options = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
for($i = 0; $i <= $length; $i ++) {
$options = str_shuffle ( $options );
$salt .= $options [rand ( 0, 63 )];
}
return $salt;
}
function verify_password($input_password)
{
if($input_password)
{
//get stored crypt pass,and salt2 from the database
$stored_password = 'somethingfromdatabase';
$stored_salt2 = 'somethingelsefromdatabase';
//compare the crypt of input+stored_salt2 to the stored crypt password
if (crypt($input_password . $stored_salt2, $stored_password) == $stored_password) {
//authenticated
return true;
}
else return false;
}
else return false;
}
mt_rand
而不是rand
将会稍微提高你的脚本性能。 - Sliq