我应该选择哪个密码散列函数?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (84)

.NET框架附带了6种不同的散列算法:

  • MD5:16字节(散列时间为500 MB:1462 ms)
  • SHA 1:20字节(1644 Ms)
  • SHA 256:32字节(5618 Ms)
  • SHA 384:48字节(3839 Ms)
  • SHA 512:64字节(3820 Ms)
  • RIPEMD:20字节(7066 Ms)

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

MD5的优点是它适合内置GUID类型。这使得它很容易被用来识别。

然而,MD5很容易受到碰撞攻击,SHA 1也很脆弱,但程度较小。

在什么情况下我应该使用哪种散列算法?

我很想看到答案的特别问题是:

  • MD5不可信吗?在正常情况下,当您使用MD5算法时,没有恶意意图,也没有第三方有任何恶意意图。
  • RIPEMD比SHA 1好多少?它的计算速度慢了5倍,与SHA 1相同。
  • 当散列文件名(或其他短字符串)时,获得非恶意冲突的几率有多大?(例如。2随机文件名与相同的MD5散列)(与MD5/SHA 1/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仍然经常被应用程序使用,因为它的密钥大小和速度都比较小。

SHA 1有一个缺陷,允许在理论上发现冲突远小于长度为2^80的安全散列函所需的步骤。攻击正在不断地被修改,目前可以在2^63步内完成--仅仅在当前的可计算范围内。由于这个原因,NIST正在逐步淘汰SHA 1的使用,声明SHA 2家族应该在2010之后使用。

SHA 2是继SHA 1之后创建的一个新的哈希函数系列。目前还没有针对SHA 2功能的已知攻击。SHA 256、384和512都是SHA 2家族的一部分,只是使用不同的密钥长度。

我不能对RIPEMD发表太多评论,但要注意的是,它并不像SHA家族那样被广泛使用,因此密码学研究人员也没有对它进行仔细的研究。仅出于这个原因,我建议对其使用SHA函数。在您正在使用的实现中,它的使用似乎也很慢,这使得它不太有用。

总之,没有一个最好的功能--这完全取决于你需要它做什么。注意每一个错误,将最好地选择正确的散列函数。你的场景。

用户回答回答于

所有散列函数都是“中断”的。

不能把2只以上的鸽子放进两个洞里。同样,不能在2^128插槽中安装2^128+1数字。所有哈希函数都会产生有限大小的散列,这意味着如果搜索“有限大小”+1序列,则始终可以找到冲突。这样做是不可行的

MD5/SHA 1/Sha2xx没有机会碰撞

所有的散列函数都有冲突,这是生命的事实。永远不会遇到意外的MD5/SHA 1/SHA2XXX散列。每本字典里的每一个词,每种语言中的每一个词,都有着不同的价值。整个星球上每台机器上的每个路径名都有不同的MD5/SHA 1/SHA2XXX散列。

有时候它的断裂并不重要

那么,你可能会问,MD5到底有什么问题呢?第三方有可能生成2条消息,其中一条消息是邪恶的,另一条消息是好的,这两条消息的哈希值都是相同的。

尽管如此,如果需要图像前电阻,当前的RSA建议是不使用MD5。当涉及到安全算法时,人们往往倾向于过于谨慎。

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

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

跟我重复一遍,不可能发生md5碰撞,恶意冲突可以精心设计。尽管到目前为止还没有已知的对MD5的预映像攻击,但安全专家的意见是,MD5不应该被用于需要防御预映像攻击的地方。

记住,并不是所有的算法都需要防御预图像或碰撞攻击。以第一遍搜索HD上的重复文件为例。

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

没有人发现任何SHA 512碰撞。永远不会。他们真的很努力。因此,从来没有人发现过任何SHA 256或384碰撞..

  • 不要使用SHA 1或RIPEMD,除非用于互操作性场景。

RIPMED没有收到Shax和MD5所收到的同等数量的审查。SHA 1和RIPEMD都容易受到生日攻击。它们都比.NET上的MD5慢,而且都有20字节的大小。

SHA 1的碰撞攻击减少到2^52,不会太长,直到SHA 1碰撞在野外出现。

但是等待还有更多

哈希函数的一个非常常见的用法是密码存储。本质上,可以计算密码的散列和已知的随机字符串(以阻止彩虹攻击),并将该哈希存储在数据库中。

问题是,如果攻击者获得了数据库的转储,他就可以有效地使用蛮力猜测密码。他尝试的每一个组合都只需要一毫秒的一小部分,而且他可以每秒尝试数十万个密码。

扫码关注云+社区