【发布时间】:2013-05-11 18:28:54
【问题描述】:
上周我阅读了很多关于密码散列的文章,而 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 aka bcrypt 来存储他们的密码 (https://shouldichangemypassword.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));
?>
这是基于this question:password_verify 返回false。
问题
什么是更安全的方法?首先获取 SHA-256 哈希(返回 64 个字符)还是只考虑密码的前 72 个字符?
优点
- 用户无法通过仅输入前 72 个字符来登录
- 您可以在不超过字符限制的情况下添加辣椒
- hash_hmac 的输出可能比密码本身具有更多的熵
- 密码由两个不同的函数散列
缺点
- 仅使用 64 个字符来构建河豚哈希
编辑 1: 这个问题仅涉及河豚/bcrypt 的 PHP 集成。感谢cmets!
【问题讨论】:
-
Blowfish 并不是唯一一种截断密码的方法,它误导人们认为它比实际更安全。这是interesting history of the 8-character limit.
-
72 个字符的截断是 Blowfish 算法的基础,还是只是 PHP 实现? IIRC Blowfish 也用于(至少一些)'nixes 来加密用户密码。
-
问题在于 Bcrypt,而不是 Blowfish。我可以单独使用 Python 和 Bcrypt 重现这个问题。
-
@Blender:感谢您的评论和您的工作。我在 php 中找不到针对河豚和 bcrypt 的不同函数,尽管它们是相同的。但是在php中对我来说没有什么不同吗?我更喜欢使用标准的php函数。
-
另见 Openwall 的PHP password hashing framework (PHPass)。它的便携性和强化了针对用户密码的一些常见攻击。编写框架 (SolarDesigner) 的人与编写 John The Ripper 并在 Password Hashing Competition 担任评委的人是同一个人。所以他对密码攻击略知一二。
标签: php security hash passwords blowfish