上周我阅读了很多关于密码散列的文章,而 Blowfish 似乎是目前最好的散列算法之一——但这不是这个问题的主题!
72 个字符的限制
Blowfish 只考虑输入密码的前 72 个字符:
<?php
$password = "Wow. This is a super secret and super, super long password. Let's add some special ch4r4ct3rs a#d everything is fine :)";
$hash = password_hash($password, PASSWORD_BCRYPT);
var_dump($password);
$input = substr($password, 0, 72);
var_dump($input);
var_dump(password_verify($input, $hash));
?>
输出是:
string(119) "Wow. This is a super secret and super, super long password. Let's add some special ch4r4ct3rs a#d everything is fine :)"
string(72) "Wow. This is a super secret and super, super long password. Let's add so"
bool(true)
如您所见,只有前 72 个字符很重要。Twitter 正在使用 bcrypt 存储他们的密码 ( https://shoudichangemypassword.com/twitter-hacked.php ) 并猜猜看:将您的 twitter 密码更改为超过 72 个字符的长密码,您可以通过以下方式登录您的帐户仅输入前 72 个字符。
河豚和胡椒
关于“peppering”密码有很多不同的看法。有人说这是不必要的,因为您必须假设秘密胡椒串也是已知/已发布的,因此它不会增强散列。我有一个单独的数据库服务器,所以很可能只有数据库被泄露,而不是不断的胡椒。
在这种情况下(胡椒没有泄露),您根据字典进行攻击会更加困难(如果这不正确,请纠正我)。如果你的胡椒串也泄露了:还不错——你还有盐,而且它的保护和没有胡椒的哈希一样好。
所以我认为加密密码至少是不错的选择。
建议
我的建议是为超过 72 个字符(和胡椒)的密码获取 Blowfish 哈希:
<?php
$pepper = "foIwUVmkKGrGucNJMOkxkvcQ79iPNzP5OKlbIdGPCMTjJcDYnR";
// Generate Hash
$password = "Wow. This is a super secret and super, super long password. Let's add some special ch4r4ct3rs a#d everything is fine :)";
$password_peppered = hash_hmac('sha256', $password, $pepper);
$hash = password_hash($password_peppered, PASSWORD_BCRYPT);
// Check
$input = substr($password, 0, 72);
$input_peppered = hash_hmac('sha256', $input, $pepper);
var_dump(password_verify($input_peppered, $hash));
?>
这是基于这个问题:password_verify
return false
。
问题
什么是更安全的方法?首先获取 SHA-256 哈希(返回 64 个字符)还是只考虑密码的前 72 个字符?
优点
- 用户无法通过仅输入前 72 个字符来登录
- 您可以在不超过字符限制的情况下添加辣椒
- hash_hmac 的输出可能比密码本身具有更多的熵
- 密码由两个不同的函数散列
缺点
- 仅使用 64 个字符来构建河豚哈希
编辑 1:这个问题仅涉及河豚/bcrypt 的 PHP 集成。感谢您的评论!