我应该选择哪个密码杂凑函数?

NET 框架提供了6种不同的哈希算法:

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

每个函数的性能都不同; MD5是最快的,RIPEMD 是最慢的。

MD5的优势在于它适合内置的 Guid 类型; 它是类型3 UUID 的基础。这使得他们真的很容易使用鉴定。

然而,MD5是脆弱的 碰撞攻击,SHA-1也是脆弱的,但程度较轻。

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

我特别想知道答案的问题是:

  • 难道 MD5不值得信任吗?在正常情况下,当您使用 MD5算法时,没有恶意意图,也没有第三方有任何恶意意图,您会预期任何冲突(意味着两个任意字节[]产生相同的散列)

  • RIPEMD 比 SHA1好多少?(如果它更好的话)它的计算速度比 SHA1慢5倍,但是散列大小是相同的。

  • 当散列文件名(或其他短字符串)时,获得非恶意冲突的几率有多大?(例如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();
}
81117 次浏览

您使用哪一个真正取决于您使用它的目的。如果您只是想确保文件在传输过程中不会损坏,并且不太担心安全性,那么可以尝试快速和小型的方法。如果你需要数十亿美元的联邦救助协议的数字签名,并且需要确保这些协议不是伪造的,那么就尽量慢慢来。

我想插一句(在 md5被分解之前) ,我仍然广泛使用 md5,尽管它对于很多加密算法来说有着巨大的破坏性。

只要你不在意防止冲突(在 hmac 中使用 md5仍然是安全的) ,并且你想要速度(有时你想要一个较慢的 hash) ,那么你仍然可以自信地使用 md5。

我不是这方面的专家,但是我和安全社区保持联系,那里的很多人认为 md5散列已经坏了。我想说的是,使用哪一个取决于数据的敏感程度和特定的应用程序。只要密钥是好的和强大的,您也许可以使用稍微不那么安全的散列表。

以下是我给你的建议:

  1. 如果您预见到攻击,那么您可能应该忘记 MD5。网上有很多 彩虹桌,像 RIAA 这样的公司已经知道能够产生具有等效散列的序列。
  2. 如果可以的话,使用 。在消息中包含消息长度可能会使得制作有用的散列冲突变得非常困难。
  3. 根据经验法则,更多的比特意味着更少的冲突(通过鸽巢原理)和更慢的冲突,也许更安全(除非你是一个能找到漏洞的数学天才)。

请参阅这里的一篇论文,其中详细介绍了使用 Intel P4桌面计算机在31秒内创建 md5冲突的算法。

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

在 MD5的防御下,没有已知的方法来生成具有任意 MD5散列的文件。原作者必须事先计划好工作冲突。因此,如果接收方信任发送方,MD5就没问题。如果签名者是恶意的,MD5就会被破坏,但是不知道它是否容易受到中间人攻击。

在加密技术中,哈希函数提供三个独立的函数。

  1. 抵抗冲突 : 找到两条(任何两条)相同的散列消息有多难。
  2. 前像阻力 : 给定一个散列,找到另一个散列相同的消息有多难?也叫 单向散列函数
  3. 第二个前像阻力 : 给定一个消息,找到另一个散列相同的消息。

这些属性是相关的,但是是独立的。例如,碰撞阻力意味着第二前像阻力,而不是反过来。对于任何给定的应用程序,您都会有不同的需求,需要一个或多个这样的属性。用于在服务器上保护密码的哈希函数通常只需要映像前电阻,而消息摘要需要这三者。

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

SHA1有一个缺陷,它允许碰撞在理论上远远少于其长度的安全哈希函数所需的2 ^ 80步。这种攻击正在不断地被修改,目前只需要大约2 ^ 63个步骤就可以完成——仅仅在当前可计算性的范围内(截至2009年4月)。出于这个原因,NIST 正在逐步淘汰 SHA1的使用,声明 SHA2系列应该在2010年之后使用。

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

我不能对 RIPEMD 做太多评论,只能说它不像 SHA 家族那样常用,因此没有被密码学研究人员仔细研究过。仅仅出于这个原因,我建议使用 SHA 函数。在实现中,您使用它的速度似乎也很慢,这使得它不那么有用。

总而言之,没有一个最好的功能-这完全取决于您需要它的目的。留意每个缺陷,您将能够最好地为 你的场景选择正确的散列函数。


警告

2022年8月

不要使用 SHA-1或 MD5进行密码学应用。这两种算法都是 都坏了(手机可以在30秒内破解 MD5)。


更新:

时代变了,我们有一个 SHA3冠军。我会推荐使用 Keccak(又名 SHA3)的 SHA3比赛的冠军。

原答案:

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

  1. RIPEMD 破损,永远不应该使用 可以在这个 pdf 中看到
  2. MD-5坏了,永远不应该使用,用笔记本电脑2分钟就能破解
  3. SHA-1坏了,永远不应该使用,校长被打垮了,袭击事件一周比一周好
  4. SHA-2弱,可能会在未来几年内被打破。注意,通常键大小越高,哈希函数越难中断。虽然密钥大小 = 强度并不总是正确的,但大多数情况下是正确的。所以 SHA-256可能比 SHA-512弱。
  5. 皮肤没有已知的弱点,是 SHA-3的候选人。它是相当新的,因此未经测试
  6. MD6没有已知的弱点,是 SHA-3的另一个候选者。可能比 Skien 更强,但在单核机器上更慢。和 Skien 一样,它也是未经测试的。一些有安全意识的开发人员正在 任务关键角色中使用它。

就我个人而言,我会使用 MD6,因为一个人永远不会太偏执。如果速度是一个真正的问题,我会看斯凯恩,或 SHA-256。

所有散列函数都是“坏的”

鸽巢原理告诉我们,尽你最大的努力,你不能在2个洞里放2只以上的鸽子(除非你把鸽子切开)。类似地,在2 ^ 128个槽中也不能容纳2 ^ 128 + 1个数字。所有哈希函数的结果都是有限大小的哈希,这意味着如果你搜索“有限大小”+ 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也一样.

请记住,并非所有的算法都需要防御前映像或碰撞攻击。采取的第一次通过搜索的重复文件在您的 HD 的琐碎情况。

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

没人发现任何 SHA512的碰撞。从来没有。他们已经很努力了。因此,没有人曾经发现任何 SHA256或384碰撞。.

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

RIPMED 没有受到 SHAX 和 MD5所受到的同等程度的审查。SHA1和 RIPEMD 都容易受到生日攻击。它们都比 MD5慢。NET,并在尴尬的20字节大小来。使用这些函数毫无意义,忘了它们吧。

SHA1碰撞攻击下降到2 ^ 52,不会太久,直到 SHA1碰撞在野外。

有关各种散列函数的最新信息,请参阅 散列函数动物园

等等,还有呢

拥有 很快散列函数可能是一个诅咒。例如: 散列函数的一个非常常见的用法是密码存储。实际上,您可以计算密码的哈希值和一个已知的随机字符串(以阻止彩虹攻击) ,并将该哈希值存储在数据库中。

问题是,如果攻击者得到了数据库的转储,他可以非常有效地使用蛮力猜测密码。他尝试的每个组合只需要几毫秒的时间,而且他每秒钟可以尝试成千上万的密码。

为了解决这个问题,可以使用 地下室算法,它的设计是缓慢的,因此如果使用 bcrypt 攻击系统,攻击者的速度会大大减慢。最近 脚本制作了一些标题,并被认为是一些比 bcrypt 更有效,但我不知道一个。净执行额。

看看 BLAKE2算法是个不错的主意。

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