如何散列长密码(> 72个字符)与河豚如何散列长密码(> 72个字符)与河豚(How t

2019-05-12 16:14发布

上周,我读了很多关于密码散列和河豚的文章似乎是(之一),现在最好的哈希算法 - 但这不是这个问题的话题!

72个字符的限制

河豚只考虑在输入密码的前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://shouldichangemypassword.com/twitter-hacked.php )和猜测:有超过72个字符改变你的Twitter密码的长密码,你可以通过登录到您的帐户只进入第一72个字符。

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个字符登录
  • 您可以添加辣椒不超过字符限制
  • hash_hmac的输出可能会比密码本身更熵
  • 密码是由两个不同的功能散列

缺点

  • 只有64个字符用于构建河豚哈希


编辑1:这个问题不仅不会忽略河豚/ bcrypt的PHP集成。 感谢对评论!

Answer 1:

这里的问题基本上是熵的问题。 因此,让我们开始寻找有:

熵每字

每字节熵比特数是:

  • 十六进制字符
    • 位:4
    • 值:16
    • 熵在72个字符:288位
  • 字母数字
    • 位:6
    • 值:62
    • 熵在72个字符:432位
  • “common”标志
    • 位:6.5
    • 值:94
    • 熵在72个字符:468位
  • 全字节
    • 位:8
    • 值:255
    • 熵在72个字符:576位

那么,我们如何行动取决于我们期待什么类型的字符。

第一个问题

与您的代码的第一个问题是,你的“辣椒”散列步骤输出十六进制字符(因为第四个参数hash_hmac()未设置)。

因此,通过散列你胡椒,你用有效的2(从576到288 可能位)的因素切割可用密码的最大熵。

第二个问题

然而, sha256只提供256放在首位熵位。 所以你有效地切断可能的576位下降到256位。 你的哈希步* *立即由本身的定义失去的密码可能的熵的至少 50%。

你可以通过切换到部分地解决了这个SHA512 ,在这里你只约12%减少可用的熵。 但是,这仍然是一个不可忽略的差别。 这12%的因数降低了排列的数目1.8e19 。 这是一个大数目......就是这样通过降低它的因素 ...

根本的问题

根本的问题是,有三种类型超过72个字符的密码。 这种风格系统对他们的影响会有很大的不同:

注意:从这里开始了我假设我们要比较于使用胡椒系统SHA512与原始输出(不是十六进制)。

  • 高熵的随机密码

    这些都是使用产生什么样量为密码按键宽大密码生成你的用户。 他们是随机的(产生的,没有人选择),并且每个字高熵。 这些类型均使用高字节(字符> 127)和一些控制字符。

    对于这一组,你的散列函数会显著减少其可用熵到bcrypt

    让我再说一遍。 对于谁是使用高熵,长密码的用户,您的解决方案显著降低可测量的量的密码强度。 (熵的62个比特丢失了72个字符的密码,多用于较长的密码)

  • 中熵的随机密码

    该组被使用含有常用符号密码,但没有高字节或控制字符。 这些都是你的密码键式。

    对于这一组,你要稍微解开更多的熵(不创建它,而是让更多的熵融入bcrypt密码)。 当我说咯,我稍微意思。 当您最大程度的发挥512位是SHA512具有收支平衡发生。 因此,峰值是在78个字符。

    让我再说一遍。 对于这类密码,您可以在用完熵的前只能存储一个额外的6个字符。

  • 低熵非随机密码

    这是谁正在使用的可能不是随机生成的字母数字字符组。 像一本圣经报价或此类。 这些短语有每个字符的熵的大约2.3位。

    对于这个组,可以显著通过散列解开更多的熵(不创建它,而是让更多的融入bcrypt密码输入)。 盈亏平衡大约是223个字符,你用完了熵之前。

    让我们再说一遍。 对于这类密码,预哈希绝对显著提高了安全性。

回到现实世界

这些类型的熵的计算并不真正的问题多,在现实世界中。 重要的是猜测熵。 这就是直接的影响是什么攻击者可以做。 这就是你想要什么最大化。

虽然有这么不见了成猜测熵的研究很少,也有一些,我想指出的点。

的随机猜测在一排72个正确字符的可能性非常低。 你就更有可能赢得强力球彩票的21倍,比有这种碰撞......这是多大我们谈论了许多。

但是,我们可能无法在统计上它绊倒。 在短语的情况下,第一72个字符是相同的机会比一个随机密码较高一大堆。 但它仍然是平凡低(你更有可能赢得强力球彩票的5倍,基于每个字符2.3位)。

几乎

实际上,它并不真正的问题。 有人猜测第72个字符正确,后者者作出显著差异的机会是如此之低,这是不值得担心。 为什么?

好吧,让我们说你正在做的短语。 如果人能拿到第72个字符的权利,他们要么真的很幸运(不太可能),或者这是一个常见的词组。 如果它是一个常见的词组,唯一的变量是多久才能做到这一点。

让我们看一个例子。 让我们引自圣经(只是因为它是长文本的一个共同的来源,而不是任何其他原因):

你不可贪图你的邻居的房子。 你不可贪恋人的妻子,他的仆人仆婢,他的牛,驴,或任何属于你的邻居。

这是180个字符。 第73字符是g第二neighbor's 。 如果你猜是多少,你可能不会在停止nei ,但与诗的其余部分继续(因为这是密码会如何被使用)。 因此,你的“哈希”没有增加多少。

BTW:我绝对没有使用的圣经报价主张。 事实上,正好相反。

结论

你不是真的要帮助的人多谁首先散列使用长密码。 一些团体,你一定能帮助。 有些你绝对可以伤害。

但最终,这一切没有过于显著。 我们正在处理的数字只是太高 。 在熵的差异不会太大。

你马上去bcrypt,因为它是更好的。 你很可能会搞砸了散列(从字面上看,你做到了已经,而且你不是第一个,或最后,以犯类似的错误)比你试图阻止事情发生了攻击。

专注于固定网站的其余部分。 和密码熵计添加到密码框上登记,表示密码强度(并注明如果密码过长,用户可能希望改变它)...

这是我的$ 0.02,至少(或可能的方式超过$ 0.02)...

至于使用一个“秘密”辣椒:

从字面上有没有研究到喂养一个散列函数分为bcrypt。 因此,目前还不清楚,在最好的,如果喂“胡椒”散列成bcrypt都不会造成未知的漏洞(我们知道这样hash1(hash2($value))可以暴露围绕抗碰撞性和原像攻击显著漏洞)。

考虑到你已经在考虑保存密钥(以下简称“胡椒”),为什么要在这个井的研究和理解的方式不使用它呢? 为什么不早于存储时进行加密哈希?

基本上,你哈希密码后,养活整个哈希输出成一个强大的加密算法。 然后存储加密的结果。

现在,一个SQL注入攻击不会泄漏任何有用的东西,因为他们没有密钥。 而如果密钥泄漏,攻击者没有关闭,如果你使用普通的哈希优于(这是可证明,一些与花椒“预哈希”不提供)。

注意:如果你选择这样做,使用图书馆。 对于PHP,我强烈建议Zend框架2的Zend\Crypt包。 实际上,它是唯一一个我想在这个当前点建议的时间。 它已经强烈地审查,它使你所有的决定(这是一件非常好的事情)...

就像是:

use Zend\Crypt\BlockCipher;

public function createHash($password) {
    $hash = password_hash($password, PASSWORD_BCRYPT, ["cost"=>$this->cost]);

    $blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
    $blockCipher->setKey($this->key);
    return $blockCipher->encrypt($hash);
}

public function verifyHash($password, $hash) {
    $blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
    $blockCipher->setKey($this->key);
    $hash = $blockCipher->decrypt($hash);

    return password_verify($password, $hash);
}

它是有益的,因为你正在使用的所有的算法是很好的理解并很好的研究方法(比较至少)。 记得:

任何人,从最无能爱好者最好的译电员,可以创建一种算法,他本人不能打破。

  • 布鲁斯


Answer 2:

尖刻的密码肯定是做的,但让我们来看看为什么一件好事。

首先,我们应该回答这个问题什么时候辣椒帮助。 胡椒不仅保护了密码,只要它保持秘密,所以,如果攻击者能够访问到服务器本身,它是没有用的。 一个更容易的攻击虽然是SQL注入,允许读取访问数据库(我们的哈希值),我准备了一个SQL注入的演示来显示它多么容易(点击旁边的箭头获得准备输入)。

那么,什么是辣椒实际的帮助? 只要保持辣椒秘密,它保护从字典攻击弱密码。 密码1234 ,然后会成为像1234-p*deDIUZeRweretWy+.O 。 这个密码是不仅要长得多,它也包含特殊字符,并且将永远不会有任何字典的一部分。

现在,我们可以估算一下我们的口令用户会使用,可能更多的用户将进入弱密码,因为有用户使用64-72个字符(实际上这将是非常罕见的)之间的密码。

另一点是暴力破解的范围内。 该SHA256哈希函数将返回256位输出或1.2E77组合,这方面太多的暴力破解,即使是GPU的(如果我计算正确,这将需要大约2E61年在GPU在2013年)。 所以,我们没有得到应用辣椒一个真正的缺点。 由于哈希值是不是系统性的,你不能加快与普通模式暴力破解。

PS据我所知,72个字符的限制是特定于BCrypt本身的算法。 最好的答案,我发现是这个 。

PPS我觉得你的例子是有缺陷的,你不能生成完整的密码长度的哈希值,并用截短一个验证。 你可能意味着应用辣椒做同样的方式生成散列和散列的验证。



Answer 3:

Bcrypt使用基于昂贵的Blowfish键设置算法的算法。

所推荐的56字节密码限制(包括空终止字节),用于bcrypt涉及的Blowfish密钥的448位限制。 超出限额的任何字节不完全混合所产生的哈希值。 因此在bcrypt密码的72字节的绝对限制是不太相关的,当你考虑这些字节的结果散列的实际效果。

如果你认为你的用户通常会选择的密码长度超过55个字节,还记得你总是可以提高密码的伸展而不是回合,以增加其在密码表违约的情况下,安全性(尽管这已被大量使用添加额外的比较字符)。 如果用户的访问权限是关键,以至于用户通常需要一个大规模长密码,则密码到期也应该是短期,如2周。 这意味着密码很可能要少得多,而黑客投资其资源在击败参与测试每个试验密码,看它是否会产生一个匹配的散列工作因素被保持有效。

当然,在不违反被密码表的情况下,我们应该只允许黑客,顶多十次猜测用户的55字节的密码,锁定用户帐户之前;)

如果你决定预哈希密码大于55个字节长,那么你应该使用SHA-384,因为它没有去超过限制的最大输出。



文章来源: How to hash long passwords (>72 characters) with blowfish