c# - 我应该选择哪种加密哈希函数?

标签 c# .net hash cryptography cryptographic-hash-function

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

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

这些函数中的每一个都有不同的表现; MD5 最快,RIPEMD 最慢。

MD5的优点是适合内置的Guid类型; and it is the basis of the type 3 UUID . SHA-1 hash is the basis of type 5 UUID.这使得它们非常容易用于识别。

然而,MD5 容易受到 collision attacks 的攻击, SHA-1 也很脆弱,但程度较轻。

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

我真的很想知道答案的具体问题是:

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

  • 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. Preimage Resistance:给定一个散列,找到另一条散列相同的消息有多难?也称为单向哈希函数
  3. 第二原像阻力:给定一条消息,找到另一条散列相同的消息。

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

虽然已经证明MD5是不抗碰撞的,但这并不排除它在不需要抗碰撞的应用中的使用。事实上,MD5 通常仍用于需要较小 key 大小和速度的应用程序中。也就是说,由于其缺陷,研究人员建议在新场景中使用其他哈希函数。

SHA1 有一个缺陷,理论上可以在远少于其长度的安全哈希函数所需的 2^80 步内发现冲突。攻击不断被修改,目前可以在 ~2^63 步内完成——勉强在当前的可计算范围内(截至 2009 年 4 月)。出于这个原因,NIST 正在逐步停止使用 SHA1,并声明 SHA2 系列应该在 2010 年之后使用。

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

我不能对 RIPEMD 发表太多评论,只是要注意它不像 SHA 系列那样常用,因此密码学研究人员没有仔细审查它。仅出于这个原因,我建议在它上面使用 SHA 函数。在您使用的实现中,它似乎也很慢,这使得它不太有用。

总而言之,没有最好的功能 - 这完全取决于您需要它做什么。请注意每个缺陷,您将能够最好地为您的场景选择正确的哈希函数。


⚠️警告

2022 年 8 月

请勿将 SHA-1 或 MD5 用于加密应用程序。这两种算法都已损坏(手机可在 30 秒内破解 MD5)。


关于c# - 我应该选择哪种加密哈希函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/800685/

相关文章:

c# - 如何在 while(dr.read()) 中运行 SqlCommand

c++ - 使用 BeginInvoke 时出现参数计数不匹配异常

.net - SSL 失败 - 将 HttpWebRequest 与客户端证书一起使用时收到 SSL/TLS 异常

java - 如何为android中的字符串输入生成唯一的哈希码...?

hash - 具有 md5 哈希值的旧版应用程序 : how to add salt and SHA1?

c# - 赋值不会使用 lambda 表达式修改 List ForEach 函数中的变量

c# - 我需要一个从 MSI 源目录复制文件的 MSI 自定义操作

c# - 在 ASP.NET MVC 中使用全局变量

c# - 使用 LINQ 获取一个具有大部分子实体的实体

hash - 如何防止这个循环多项式哈希函数使用类型约束?