这被用于个人网站,因此它比超级安全更具学习经验。也就是说,我一直在阅读你应该做的各种事情,至少对我来说,这看起来非常安全,尽管可能内存使用率很低。
然而,我读过的每个地方都说不要自己尝试,所以很明显我的方式会有一些缺陷。有人可以建议任何改进吗?为了记录,我试图使用内置于免费虚拟主机中的库来实现,因为PBKDF2
和bcrypt
都没有。
salt是通过substr(uniqid(mt_rand(), true), 0, 32)
生成的(substr避免它有时会溢出数据库,最终会以33个字符结束),并在输入数据库之前进行加密。这是通过全局密钥的哈希,所以你还需要一个php文件的内容来破解它(我可能会把它切换到'全局密钥+电子邮件'但是)。
IV只是存储在一个文件夹中,所以即使你破解数据库并获取php文件的内容,你仍然需要通过htaccess来读取文件。这可以删除,其中下一次运行该函数将生成一个新函数,因此使所有密码无效。
实际密码哈希使用键拉伸,但是使用的值是crc32值的模数,因此每个用户都有不同数量的哈希值。每个重复哈希都使用其中的一些哈希来尝试保持它的唯一性。
$salt_key = 'seemingly random string of characters, numbers and symbols';
function get_iv(){
// It stores it as a file, but there's no point showing that part so here's the actual code bit
return mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC), MCRYPT_RAND);
}
function generate_salt(){
global $salt_key;
$salt = substr(uniqid(mt_rand(), true), 0, 32);
$key = hash('sha256', $salt_key, true);
$iv = get_iv();
$encrypt = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $salt, MCRYPT_MODE_CFB, $iv);
return array($salt, $encrypt);
}
function decrypt_salt($encrypted){
global $salt_key;
$key = hash('sha256', $salt_key, true);
$iv = get_iv();
return mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encrypted, MCRYPT_MODE_CFB, $iv);
}
function hash_password($password, $salt){
#return hash('sha512', $password.$salt, true);
$hash = $salt;
for($i=0; $i<(crc32($salt.$password) % 129197); $i++){
$hash = hash('sha512', $hash.$password.$salt.hash('sha512', $salt.$hash.$password).md5($salt.md5($password.$hash)), true);
}
return $hash;
}
还有其他一些功能,但它们主要用于检查输入的密码与数据库中的密码。是否有一些我错过的重要部分,或者对于小规模的网站,这可能是好的吗?
此外,关于按键拉伸的快速问题,如果我需要半秒钟来计算,并不意味着如果该网站突然有500人试图登录,有人将不得不坐在那里250秒因为CPU过载?我只是想在用户表中存储哈希的最大值(上面代码中的129197),所以如果需要可以更改它而不会使密码无效。