【问题标题】:How can I make MD5 more secure? Or is it really necessary?如何使 MD5 更安全?还是真的有必要?
【发布时间】:2011-05-13 10:32:07
【问题描述】:

我将用户名和密码存储在 MySQL 数据库中,并使用 MD5 对其进行哈希处理。但是,我只使用标准的 PHP 函数,没有任何修改。现在,我读到 MD5 坏了。你怎么样?您是通过不同的哈希机制多次运行它还是添加某种形式的盐?

【问题讨论】:

    标签: php security md5


    【解决方案1】:

    我很惊讶人们如何跳上“该死,它坏了,我不会使用它!”的潮流,不要犯同样的错误。

    你不能让 MD5 变得更好。即使使用 SHA-1 也容易受到与 MD5 相同类型的攻击。 使用 bcrypt 将比 MD5 和 SHA 算法使用更多的 CPU。

    MD5 的设计速度很快,与 SHA 相同。 bcrypt 不是,它允许更多的排列,这使得人们更难尝试解密原始字符串。

    你需要知道为什么 MD5 被认为是“损坏的”。

    • 因为可以快速计算出最多 6 个字符的彩虹表密码

    使用当今的计算能力,可以创建一个字符数组和 MD5 所有排列,并将它们映射到原始字符串。这就是你如何得到一个彩虹表。如果有人下载您的数据库,然后将密码与他们的彩虹表进行比较 - 他们可以获得用户的原始密码。这是危险的原因是因为人们在许多事情上使用相同的密码 - 包括贝宝和其他货币处理服务。这就是为什么你使用所谓的盐。这使得获取原始字符串变得更加困难,因此对用户的密码进行加盐(比如说通过反转密码并对反转的输入进行 MD5 处理)将使攻击者更难将哈希恢复为原始字符串。

    • 因为碰撞

    什么是碰撞?如果你给散列函数两个不同的字符串,它返回相同的散列——那就是冲突。它如何转化为用于登录的 Web 和散列密码?如果您对 user1/password1 和 user2/password2 具有相同的哈希值 - 他们可以以其他人身份登录。这就是碰撞在安全中发挥作用的地方。

    MD5 被认为是损坏的原因是因为 MD5 为小百分比不同的字符串返回相同的哈希值。计算那个字符串可能是什么并不容易! 从数学的角度来看 - 是的,它被“破坏”了,因为如果你的字符串有 100 个字符,并且它与其他字符串的 10 个字符不同(10% 的差异) - 你会得到相同的哈希值。

    适用于 MD5 的内容适用于所有散列算法。最后,他们都没有无限数量的可能散列。 但是,其中一些(如 MD5)具有较少可能的哈希值并且执行速度更快。

    最后,如果有人访问了您的数据库 - 您遇到的问题比使用 MD5 代替 bcrypt 或 SHA1 更大。

    【讨论】:

    • 谢谢迈克尔,我最喜欢你的回答,因为我的想法与我今天越来越多地了解哈希的想法完全相同。如果 sb 能够访问数据库,他们可能也可以访问 PHP 文件,这意味着无论您认为自己多么聪明,他们都会为您赢得大量时间。最后,我使用了 SHA-512 和一些盐,因为速度对我来说真的很重要,而且它似乎很快。
    • 我使用了 SHA-512,因为输出的字符串长度为 128 个字符,这使得它不太可能被匹配 - 尽管可能并非不可能。
    • 对于其他阅读本文的人,在 PHP 中您只需使用:hash("sha512", 123);您可以随意添加盐。
    • 我一直在考虑这个响应,我可以看到逻辑上的缺陷。密码的存储方式应该是任何人都无法对其进行逆向工程或创建与哈希匹配的输入。当您说“如果有人进入您的数据库 - 您有一个更大的问题”时,这实际上只是问题的一半。应该存储密码,以便任何可能合法访问数据库的人(例如,开发应用程序的开发人员)都无法对其进行逆向工程/匹配。因此,安全性与速度的平衡应该更多地落在安全性上。
    • MD5 没有损坏,因为它快速。它应该很快。这是加密哈希函数的主要特征。它被破坏了,因为既有已知的碰撞,又有产生碰撞的攻击向量。但这并不是因为为小百分比不同的字符串返回相同的哈希。对于非工程碰撞,这甚至不是真的。
    【解决方案2】:

    为每个存储的密码添加一个盐,每个密码都不相同

    【讨论】:

    • 你的意思是我应该创建 3-5 种不同的盐,然后简单地记下一个数字以检索已使用的盐吗?或者您是否为每个密码创建不同的盐?在这种情况下如何检索它?
    • @Frank 以与您存储用户名和哈希相同的方式,在您的表中添加另一列。
    【解决方案3】:

    只需使用MD5("yoursite.com".$string);

    MD5 不可解密。破解它的唯一可能方法是通过暴力破解所有内容的哈希表。如果你添加一个只有你知道他们无法破解的随机字符串。

    【讨论】:

    • 这不是真的,考虑到鸽巢原理,任何给定的哈希都可以由无限数量的可能输入产生。已经证明可以为具有 MD5 的哈希计算其他可能的匹配输入。盐不能保护你免受某些东西的伤害。
    【解决方案4】:

    如果您担心密码安全,那么您应该使用 SHA1()(或替代方法)而不是 MD5()。虽然 MD5 不可解密,但它可以被彩虹表或匹配散列打败。

    盐对彩虹表起作用,但对匹配用 MD5 实现的哈希不起作用。

    【讨论】:

    • 哇,你刚刚解释了这么简单的词。谢谢本。
    【解决方案5】:

    有几件事你应该做。

    1. 使用SHA 代替MD5。 SHA 在密码学上比 MD5 更安全。位数越多越好!
    2. 使用盐。这让rainbow table attacks 变得更加困难。
    3. Strengthen your key 通过如下计算哈希:

    function strenghtened_hash( $password, $salt, $n ) {
        $crypted = sha( $password . $salt );
        for( $i = 0; $i < $n; $i++ ) {
            $crypted = sha( $crypted . $password . $salt );
        }
        return $crypted;
    }
    

    现在你的状态应该不错!

    【讨论】:

    • 感谢 stevevls,这种计算在 CPU 上是否非常密集?因为每次某人登录时我都必须这样做,不是吗?
    • 它有多贵取决于你做哈希的次数。如果您的服务器负载不重,您可以轻松地进行大量迭代。如果你担心,从 16 开始,看看它会把你带到哪里。
    【解决方案6】:

    您最好使用using bcrypt for password storage 来防止彩虹表攻击,以防坏人控制您的数据库。

    至少,转储 MD5(虽然计算速度很快,但现在不是很安全)并使用更安全的东西,比如 SHA256 和长盐。

    【讨论】:

      【解决方案7】:

      切换到不同的哈希机制(您可以在人们登录时逐步进行)并且绝对使用(每个用户不同的)盐!

      【讨论】:

        【解决方案8】:

        你可以使用一种叫做盐的东西。这意味着您还将此盐保存到您的数据库中。它是一个或多或少长的随机字符串,并且对于每个用户都是唯一的。

        然后,要检查密码,请执行以下操作:

        <?php 
             $crypted = md5($salt.$passwordFromForm);
        
             if($crypted == $passwordFromDB) {
                 // user logged on
             }
        ?>
        

        【讨论】:

          【解决方案9】:

          您可以通过我写的称为“循环哈希”的方法使MD5 或任何哈希函数更强大,请在此处阅读,Good method to encrypte data,,使用循环“for”或“while”对密码进行大量加密用随机生成的密钥号,真的很强大,很容易,所以不会再被黑客吓到,目前没有人可以用可用的数据库破解加密的“循环哈希”。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-01-08
            • 1970-01-01
            • 2011-02-26
            • 1970-01-01
            • 2013-05-18
            • 1970-01-01
            • 2017-10-29
            • 1970-01-01
            相关资源
            最近更新 更多