.NET 框架附带 6 种不同的哈希算法:

  • MD5:16 字节(哈希 500MB 的时间:1462 毫秒)
  • SHA-1:20 字节(1644 毫秒)
  • SHA256:32 字节(5618 毫秒)
  • SHA3​​84:48 字节(3839 毫秒)
  • SHA512:64 字节(3820 毫秒)
  • RIPEMD:20 字节(7066 毫秒)

这些功能中的每一个的执行方式都不同;MD5 最快,RIPEMD 最慢。

MD5的优点是适合内置Guid类型; 它是类型 3 UUID 的基础. SHA-1 哈希是 5 类 UUID 的基础。 这使得它们非常容易用于识别。

然而 MD5 很容易受到 碰撞攻击, 、SHA-1 也容易受到攻击,但程度较轻。

在什么情况下应该使用哪种哈希算法?

我真的很想看到答案的具体问题是:

  • MD5不可信吗?在正常情况下,当您没有恶意地使用 MD5 算法并且没有第三方有任何恶意时,您会期望发生任何冲突(意味着两个任意 byte[] 产生相同的哈希值)

  • RIPEMD 比 SHA1 好多少?(如果有更好的话)计算速度慢 5 倍,但哈希大小与 SHA1 相同。

  • 散列文件名(或其他短字符串)时发生非恶意冲突的几率有多大?(例如。2 个具有相同 MD5 哈希值的随机文件名(使用 MD5 / SHA1 / SHA2xx) 一般而言,非恶意冲突的几率是多少?

这是我使用的基准:

    static void TimeAction(string description, int iterations, Action func) {
        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < iterations; i++) {
            func();
        }
        watch.Stop();
        Console.Write(description);
        Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
    }

    static byte[] GetRandomBytes(int count) {
        var bytes = new byte[count];
        (new Random()).NextBytes(bytes);
        return bytes;
    }


    static void Main(string[] args) {

        var md5 = new MD5CryptoServiceProvider();
        var sha1 = new SHA1CryptoServiceProvider();
        var sha256 = new SHA256CryptoServiceProvider();
        var sha384 = new SHA384CryptoServiceProvider();
        var sha512 = new SHA512CryptoServiceProvider();
        var ripemd160 = new RIPEMD160Managed();

        var source = GetRandomBytes(1000 * 1024);

        var algorithms = new Dictionary<string,HashAlgorithm>();
        algorithms["md5"] = md5;
        algorithms["sha1"] = sha1;
        algorithms["sha256"] = sha256;
        algorithms["sha384"] = sha384;
        algorithms["sha512"] = sha512;
        algorithms["ripemd160"] = ripemd160;

        foreach (var pair in algorithms) {
            Console.WriteLine("Hash Length for {0} is {1}", 
                pair.Key, 
                pair.Value.ComputeHash(source).Length);
        }

        foreach (var pair in algorithms) {
            TimeAction(pair.Key + " calculation", 500, () =>
            {
                pair.Value.ComputeHash(source);
            });
        }

        Console.ReadKey();
    }
有帮助吗?

解决方案

在密码学中,哈希函数提供三个独立的函数。

  1. 耐碰撞: :某人找到两条消息有多难(任何 两条消息)散列相同。
  2. 原像抵抗: :给定一个哈希值,找到另一条具有相同哈希值的消息有多难?也称为 单向哈希函数.
  3. 第二原像抵抗: :给定一条消息,找到另一条散列相同的消息。

这些属性相关但独立。例如,碰撞抵抗力意味着第二原像抵抗力,但反之则不然。对于任何给定的应用程序,您都会有不同的要求,需要一个或多个这些属性。用于保护服务器上密码的散列函数通常只需要原像抵抗,而消息摘要则需要全部三个。

MD5 已被证明不具有抗碰撞性,但这并不妨碍其在不需要抗碰撞性的应用中使用。事实上,MD5 通常仍用于较小密钥大小和速度有利的应用中。尽管如此,由于其缺陷,研究人员建议在新场景中使用其他哈希函数。

SHA1 有一个缺陷,理论上可以用远少于其长度的安全散列函数所需的 2^80 步来发现冲突。该攻击不断被修改,目前可以在约 2^63 步内完成 - 勉强在当前的可计算范围内。因此,NIST 正在逐步淘汰 SHA1 的使用,并指出 SHA2 系列应在 2010 年之后使用。

SHA2 是继 SHA1 之后创建的一系列新的哈希函数。目前还没有针对 SHA2 函数的已知攻击。SHA256、384 和 512 都是 SHA2 系列的一部分,只是使用不同的密钥长度。

我无法对 RIPEMD 发表太多评论,只是要注意它不像 SHA 系列那样常用,因此没有受到密码研究人员的严格审查。仅出于这个原因,我就建议使用 SHA 函数。在您使用的实现中,它看起来也很慢,这使得它不太有用。

总之,没有一种最好的功能 - 这完全取决于您需要它的用途。请注意每个缺陷,您将能够最好地选择正确的哈希函数 你的 设想。

其他提示

所有哈希函数都“损坏”

鸽巢原理 说尽你所能,2个洞里最多只能容纳2只鸽子(除非你把鸽子切碎)。同样,您不能将 2^128 + 1 个数字放入 2^128 个槽中。所有散列函数都会产生有限大小的散列,这意味着如果您搜索“有限大小”+ 1 序列,则始终可以找到冲突。这样做是不可行的。不适用于 MD5,不适用于 .

MD5/SHA1/Sha2xx 没有机会碰撞

所有的哈希函数都会发生冲突,这是不争的事实。偶然遇到这些碰撞相当于 赢得星际彩票. 。也就是说, 没有人赢得星际彩票, ,这不是彩票的运作方式。您永远不会遇到意外的 MD5/SHA1/SHA2XXX 哈希值。每本字典、每种语言中的每个单词都会哈希为不同的值。整个地球上每台计算机上的每个路径名都有不同的 MD5/SHA1/SHA2XXX 哈希值。你可能会问,我怎么知道这一点。好吧,正如我之前所说,从来没有人中过星际彩票。

但 ...MD5 已损坏

有时,它的损坏并不重要.

就目前情况而言,没有已知的 原像或第二原像攻击 在 MD5 上。

那么您可能会问,MD5 有什么问题呢?第三方有可能生成 2 条消息,其中一条是 EVIL,另一条是 GOOD,两者都哈希为相同的值。(碰撞攻击)

尽管如此,如果您需要防原像,当前 RSA 建议不要使用 MD5。当涉及到安全算法时,人们往往会过于谨慎。

那么我应该在.NET 中使用什么哈希函数呢?

  • 如果您需要速度/大小并且不关心生日攻击或原像攻击,请使用 MD5。

跟着我重复这个, MD5 不会发生冲突, ,可以精心设计恶意碰撞。尽管迄今为止还没有已知的针对 MD5 的原像攻击,但安全专家的观点是,在需要防御原像攻击的情况下不应使用 MD5。 SHA1 也是如此.

请记住,并非所有算法都需要防御原像或碰撞攻击。以首次搜索硬盘上的重复文件为例。

  • 如果您想要加密安全的哈希函数,请使用基于 SHA2XX 的函数。

没有人发现任何 SHA512 冲突。曾经。他们真的很努力。就此而言,没有人发现任何 SHA256 或 384 冲突。。

  • 除非用于互操作性场景,否则不要使用 SHA1 或 RIPEMD。

RIPMED 没有受到与 SHAX 和 MD5 同等程度的审查。SHA1 和 RIPEMD 都容易受到生日攻击。它们都比 .NET 上的 MD5 慢,并且大小为尴尬的 20 字节。使用这些功能毫无意义,忘记它们吧。

SHA1 碰撞攻击已降至 2^52,在 SHA1 碰撞出现之前,不会持续太久。

有关各种哈希函数的最新信息,请查看 哈希函数动物园.

但等等还有更多

有一个 快速地 哈希函数可能是一个诅咒。例如:哈希函数的一个非常常见的用途是密码存储。本质上,您可以计算密码与已知随机字符串相结合的哈希值(以阻止彩虹攻击),并将该哈希值存储在数据库中。

问题是,如果攻击者获得数据库的转储,他就可以使用暴力破解相当有效地猜测密码。他尝试的每个组合只需要几分之一毫秒,而他每秒可以尝试数十万个密码。

为了解决这个问题, 密码 可以使用 bcrypt 算法,它的设计速度很慢,因此如果使用 bcrypt 攻击系统,攻击者的速度会大大减慢。最近 加密 已经成为一些头条新闻,并且被一些人认为比 bcrypt 更有效,但我不知道 .Net 实现。

更新:

时代变了,我们有了 SHA3 获胜者。我建议使用 凯恰克 (又名 SHA3) SHA3 竞赛获胜者。

原答案:

按照从弱到强的顺序,我会说:

  1. RIPEMD 已损坏,切勿使用 正如在这个pdf中可以看到的
  2. MD-5 已损坏,切勿使用, 用笔记本电脑2分钟就可以破解
  3. SHA-1 已损坏,切勿使用, 原则上已被破坏,攻击每周都在好转
  4. SHA-2 WEAK,可能会在未来几年内被破解。 发现了一些弱点。 请注意,通常密钥大小越大,哈希函数就越难破解。虽然密钥大小=强度并不总是正确的,但大多数情况下是正确的。因此 SHA-256 可能比 SHA-512 弱。
  5. 绞纱没有已知的弱点, 是 SHA-3 的候选者. 。它相当新,因此未经测试。 它已经用多种语言实现了。
  6. MD6 没有已知的弱点,是 SHA-3 的另一个候选者。可能比 Skien 强,但在单核机器上速度较慢。与斯基恩一样,它也未经测试。一些具有安全意识的开发人员正在使用它 关键任务角色.

就我个人而言,我会使用 MD6,因为一个人永远不会太偏执。如果速度确实是一个问题,我会考虑 Skein 或 SHA-256。

MD5 的辩护是,没有已知的方法可以生成具有任意 MD5 哈希值的文件。原作者一定要提前谋划,才能有工作上的碰撞。因此,如果接收方信任发送方,MD5 就可以。如果签名者是恶意的,MD5 就会被破坏,但尚不清楚它是否容易受到中间人攻击。

您使用哪一种实际上取决于您使用它的目的。如果您只是想确保文件在传输过程中不会被损坏并且不太关心安全性,那么请选择速度快且体积小的文件。如果您需要数十亿美元的联邦救助协议的数字签名,并需要确保它们不是伪造的,请选择难以欺骗和缓慢的方式。

我想插话一下(在 md5 被撕裂之前),尽管 md5 对很多加密货币来说具有压倒性的破坏性,但我仍然广泛使用 md5。

只要您不关心防止冲突(在 hmac 中使用 md5 仍然是安全的)并且您确实想要速度(有时您想要较慢的哈希值),那么您仍然可以放心地使用 md5。

看一下是个好主意 布莱克2 算法。

正如所描述的,它比 MD5 更快,并且至少与 SHA-3 一样安全。它也是由 几个软件应用程序, ,包括 WinRar。

我不是这类事情的专家,但我关注安全社区,那里的很多人都认为 md5 哈希值已损坏。我想说,使用哪一种取决于数据的敏感程度和具体应用。只要密钥良好且强大,您就可以使用安全性稍差的哈希值。

以下是我给您的建议:

  1. 如果您预见到攻击,您可能应该忘记 MD5。有许多 彩虹桌 众所周知,像 RIAA 这样的公司能够生成具有等效哈希值的序列。
  2. 用一个 如果可以的话。在消息中包含消息长度会使产生有用的哈希冲突变得非常困难。
  3. 作为一般经验法则,更多的位意味着更少的冲突(根据鸽巢原理)并且速度更慢,而且可能更安全(除非您是能够发现漏洞的数学天才)。

请参阅此处的一篇论文,详细介绍了在 31 秒内与台式 Intel P4 计算机创建 md5 冲突的算法。

http://eprint.iacr.org/2006/105

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top