MD5,密码哈希和盐位置


MD5, password hashing and salt position

在我开始之前,我知道MD5受到了损害(碰撞攻击和哈希速度),不应该使用散列密码,但只是为了它,请耐心等待。

我的问题是:使用 md5 进行哈希处理时,盐的位置如何影响"质量"还是哈希的"强度"?

假设我有以下一段代码,它对用户进行哈希处理使用他的部分电子邮件地址作为盐的密码:

<?php
    $email = 'user@emailservice.ex';
    $password = 'RandomPassWithChars';
    $segments = explode('@', $email);
    list($saltPart1, $saltPart2, $saltPart3) = $segments;
    $hash = md5($saltPart1.$password.$saltPart3.$saltPart2);
?>

该代码是否会减慢蛮力/字典/彩虹表攻击,比说:

<?php
    $password = 'RandomPass';
    $salt     = 'RandomSaltStoredInTheDatabase';
    $hash = md5($password, $salt);
?>

是否值得尝试像第一个代码中那样加盐密码,或者它大喊大叫与第二个代码相同的结果?这有什么好处吗?第一个代码是否会延迟破解以这种方式散列的密码列表第二种方法?

这就引出了我第二个问题:在数据库中存储盐是否比获取盐安全从用户 ID(例如电子邮件地址)?我看到的方式,一旦攻击者获得了数据库的副本这也使盐类变得更容易一些,试图破解哈希。但是,如果不存储盐,攻击者还需要创建盐的算法。如果我错了,请纠正我。

我希望我把自己说清楚了。提前感谢您的任何答案。

第一个问题:

盐的位置对特定哈希的安全性没有影响。一个好的哈希函数具有完美的熵,因为对于每个变化的输入位,每个输出位都有 50% 的机会发生变化。

某个顺序的任何可能的安全优势将完全来自用于将盐与预期密码连接起来的算法的相对缓慢(例如,如果"password" . "salt""salt" . "password"慢,则使用前者)。但是,大多数编程语言都没有这种性能"问题"。

第二个问题:

如果盐显式存储在数据库中,攻击者将知道盐,并能够发起暴力哈希攻击。如果盐是未知的,仍然可以使用暴力密码攻击(尽管通过在尝试之间插入延迟很容易使其无效)。此外,攻击者可能能够对程序进行反向工程并检索哈希字段。

至于哈希的安全性,如果用户在两个不同的地方使用相同的电子邮件和密码,这否定了随机盐的好处之一,因为相同的哈希将在两个地方都可见。

就个人而言,我认为散列的最佳方法是使用:

"password" . "salt" . "internalconstantvalue"

这样做的好处是简单,并且不亚于大多数其他安全方法的安全性。

这取决于攻击者是试图绕过您的安全还是试图找到密码。

如果由于散列算法的加密弱点,攻击者依赖于查找与数据库给定哈希的冲突,则盐将没有任何影响:我有一堆位,我想找到一些 XXX 哈希算法的输入,这在输出中给了我相同的一堆位。

如果他试图通过尝试每种可能的组合来暴力破解密码,那么他可以收集的有关原始密码的任何信息都会有所帮助:

  • 长度
  • 组成(字母数字字符、特殊符号等)
通过

创建自己的盐算法,您实际上是在尝试通过混淆来确保安全性,这确实会限制任何不知道您的算法的人暴力破解密码,但它不会加强哈希算法。

当您处理密码安全性时,请始终假设如果攻击者有权访问您的数据库,那么他可以访问您的代码。

因此,在加盐时,只需生成一个随机值的哈希(例如,mcirotime()),并在散列之前使用它来加盐密码,并将其存储在密码旁边的数据库中。

在将哈希添加到密码时,我个人的观点是,将其放在第一位,最后还是放在中间并不重要。

你想要安全吗?然后使用慢速哈希算法,我强烈推荐PHPass,因为它使用bcrypt(基于河豚)作为默认哈希算法。