顺便:2016 年如何安全存储用户密码 https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016.
您的选择是:
- Argon2(需要 PHP 7.2 或 PHP 扩展)
- Scrypt(需要 PHP 扩展)
- Bcrypt
如果您确实需要,也可以考虑 PBKDF2。
旧的备用:Bcrypt
鉴于您是初学者,您应该像这样编写密码验证:
// Creating your hashed password:
$hash = password_hash($userPassword, PASSWORD_DEFAULT);
// Checking a user-supplied password against a stored hash:
if (password_verify($userPassword, $hash)) {
// Login successful.
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
// Recalculate a new password_hash() and overwrite the one we stored previously
}
}
bcrypt 的缺点:
- 超过 72 个字符的密码将被截断。
- 带有 NUL 字节的密码将被截断。
解决这些限制的权宜之计已内置于密码锁 https://github.com/paragonie/password_lock:它使用 SHA384 预先对密码进行哈希处理,然后对原始哈希值进行 Base64 编码,然后再传递给 PHP 的密码 API。
首先,创建一个加密密钥并存储它在文档根目录之外。 (否则,黑客就可以窃取密钥。)
$newKey = \Defuse\Crypto\Key::createNewRandomKey();
file_put_contents(
'/outside/document/root/enckey.txt',
$newKey->saveToAsciiSafeString()
);
现在,您可以将此密钥与您的密码结合使用:
$key = Key::loadFromAsciiSafeString(
file_get_contents('/outside/document/root/enckey.txt')
);
// Hashing a password with PasswordLock:
$storeMe = PasswordLock::hashAndEncrypt($_POST['password'], $key);
// Verifying a password with PasswordLock:
if (PasswordLock::decryptAndVerify($_POST['password'], $storeMe, $key)) {
// Success!
}
您现在可以使用 Argon2password_hash()在 PHP 7.2 中 https://framework.zend.com/blog/2017-08-17-php72-argon2-hash-password.html
新标准:Argon2(通过 Libsodium)
除非您使用的是 PHP 7.2 或更高版本,否则您需要安装 libsodium 和 PHP 扩展 https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium使用Argon2。密码哈希是其中一项功能not由odium_compat 提供。
// Password hashing:
$hash_str = sodium_crypto_pwhash_str(
$password,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
// Password verification:
if (sodium_crypto_pwhash_str_verify($hash_str, $password)) {
// recommended: wipe the plaintext password from memory
sodium_memzero($password);
// Password was valid.
} else {
// recommended: wipe the plaintext password from memory
sodium_memzero($password);
// Password was invalid.
}
中级:Scrypt
你需要scrypt 扩展 https://github.com/DomBlack/php-scrypt可通过 PECL 获得:
pecl install scrypt
echo "extension=scrypt.so" > /etc/php5/mods-available/scrypt.ini
php5enmod scrypt
一旦安装完毕,使用它就相当简单了:
// Hashing:
$hash = \Password::hash($userProvidedPassword);
// Validation:
if (\Password::check($userProvidedPassword, $hash)) {
// Logged in successfully.
}
真正使用 scrypt 的唯一原因是兼容性;此时,请选择 Argon2 或 bcrypt。
可以接受但不太好:PBKDF2
我强烈推荐去Defuse Security 的跨平台密码哈希库 https://github.com/defuse/password-hashing如果您需要 PBKDF2。 (你应该考虑只使用password_*
, 然而!)
$hash = PasswordStorage::create_hash($password);
if (PasswordStorage::verify_password($password, $hash)) {
// Success
}
上述任何一个选择都是可以接受。 Argon2 可能是最安全的,但它尚未在 PHP 中广泛使用。任何未包含在该列表中的内容都应该以适当的怀疑态度来看待。