上周我读了很多关于密码哈希和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正在使用blowfish(又名bcrypt)来存储他们的密码(https://shouldichangemypassword.com/twitter-hacked.php)。如果您更改您的Twitter密码为一个超过72个字符的长密码,您只需输入前72个字符即可登录到您的帐户。
Blowfish和Pepper
关于“加入pepper”的密码保护方法,有很多不同的观点。有些人认为这是不必要的,因为您必须假设秘密的pepper字符串也已知/公开,所以它并没有增强哈希函数的安全性。我有一台单独的数据库服务器,所以仅泄漏了数据库而未泄漏常量pepper的可能性很大。
在这种情况下(pepper未泄漏),您可以使基于字典的攻击变得更加困难(如果我理解不正确,请纠正我)。如果您的pepper字符串也被泄露:那也没什么大不了的 - 您仍然拥有salt,并且与没有pepper的哈希值一样得到保护。
因此,我认为加入pepper的密码保护至少不是一个坏选择。
建议
我建议为密码生成一个带有pepper的Blowfish哈希值,长度超过72个字符的密码,步骤如下:
<?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
返回false
。
问题
哪种方法更安全?先获取一个SHA-256哈希值(返回64个字符)还是仅考虑密码的前72个字符?
优点
- 用户不能通过只输入前72个字符来登录
- 您可以添加pepper而不超过字符限制
- hash_hmac的输出可能比密码本身具有更多的熵
- 密码由两个不同的函数哈希
缺点
- 仅使用64个字符构建blowfish哈希
编辑1:此问题仅涉及blowfish / bcrypt的PHP集成。感谢评论!