.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();
}
在密码学中,散列函数提供三个独立的函数。
碰撞阻力:某人找到两条哈希相同的消息(任意两条消息)有多难。原像阻力:给定一个散列,找到另一个散列相同的消息有多难?也称为单向哈希函数。第二个原像阻力:给定一条消息,找到另一条哈希相同的消息。
这些属性是相关但独立的。例如,碰撞阻力意味着第二原像阻力,但反之则不然。对于任何给定的应用程序,您将有不同的要求,需要这些属性中的一个或多个。用于保护服务器密码的散列函数通常只需要原像抗性,而消息摘要需要这三个功能。
已经证明 MD5 不耐碰撞,然而,这并不排除它在不需要耐碰撞的应用中的使用。事实上,MD5 仍然经常用于较小的密钥大小和速度有好处的应用程序中。也就是说,由于其缺陷,研究人员建议在新场景中使用其他哈希函数。
SHA1 有一个缺陷,理论上它允许在远少于其长度的安全散列函数所需的 2^80 步中发现冲突。攻击不断被修改,目前可以在 ~2^63 步内完成 - 仅在当前可计算性范围内(截至 2009 年 4 月)。出于这个原因,NIST 正在逐步淘汰 SHA1 的使用,并指出 SHA2 系列应该在 2010 年之后使用。
SHA2 是在 SHA1 之后创建的一个新的哈希函数系列。目前没有针对 SHA2 函数的已知攻击。 SHA256、384 和 512 都是 SHA2 系列的一部分,只是使用了不同的密钥长度。
RIPEMD 我不能过多评论,只是要注意它不像 SHA 系列那样常用,因此没有受到密码学研究人员的仔细审查。仅出于这个原因,我建议使用 SHA 函数。在您使用的实现中,它似乎也很慢,这使得它不太有用。
总之,没有一个最好的功能——这完全取决于你需要它做什么。请注意每个缺陷,您将能够最好地为您的场景选择正确的哈希函数。
所有哈希函数都“损坏”
pigeonhole principle 说尽你所能,你不能在 2 个洞里放超过 2 只鸽子(除非你把鸽子剪掉)。同样,您不能在 2^128 个插槽中放置 2^128 + 1 个数字。所有哈希函数都会产生有限大小的哈希,这意味着如果您搜索“有限大小”+ 1 个序列,您总能找到冲突。这样做是不可行的。不适用于 MD5,也不适用于 Skein。
MD5/SHA1/Sha2xx 没有机会碰撞
所有的散列函数都有冲突,这是不争的事实。偶然遇到这些碰撞相当于中了星际彩票。也就是说,no one wins the intergalactic lottery,它不是彩票的运作方式。您永远不会遇到意外的 MD5/SHA1/SHA2XXX 哈希。每个字典中的每个单词,每种语言中的每个单词,都会散列到不同的值。整个星球上每台机器上的每个路径名都有不同的 MD5/SHA1/SHA2XXX 哈希值。我怎么知道的,你可能会问。好吧,正如我之前所说,从来没有人中过星际彩票。
但是……MD5坏了
有时,它损坏的事实并不重要。
就目前而言,MD5 上没有已知的 pre-image or second pre-image attacks。
那么,您可能会问,MD5 有什么问题?第三方有可能生成 2 条消息,其中一条是 EVIL,另一条是 GOOD,它们的哈希值相同。 (Collision attack)
尽管如此,如果您需要抗原像性,当前的 RSA 建议是不要使用 MD5。在涉及安全算法时,人们倾向于谨慎行事。
那么我应该在 .NET 中使用什么哈希函数呢?
如果您需要速度/大小并且不关心生日攻击或原像攻击,请使用 MD5。
在我之后重复这个,没有机会 MD5 碰撞,可以精心设计恶意碰撞。尽管迄今为止在 MD5 上没有已知的原像攻击,但安全专家的说法是,MD5 不应该用于需要防御原像攻击的地方。 SHA1 也一样。
请记住,并非所有算法都需要防御原像或碰撞攻击。以第一次搜索 HD 上的重复文件为例。
如果您想要加密安全的散列函数,请使用基于 SHA2XX 的函数。
没有人发现任何 SHA512 冲突。曾经。他们真的很努力。就此而言,没有人发现任何 SHA256 或 384 冲突。 .
不要使用 SHA1 或 RIPEMD,除非它用于互操作性场景。
RIPMED 没有受到与 SHAX 和 MD5 一样多的审查。 SHA1 和 RIPEMD 都容易受到生日攻击。它们都比 .NET 上的 MD5 慢,并且只有 20 字节大小。使用这些功能毫无意义,忘记它们。
SHA1 碰撞攻击下降到 2^52,在 SHA1 碰撞在野外出现之前不会太久。
有关各种散列函数的最新信息,请查看 the hash function zoo。
但是等等还有更多
拥有一个快速的散列函数可能是一个诅咒。例如:哈希函数的一个非常常见的用法是密码存储。本质上,您计算密码的哈希值和已知的随机字符串(以阻止彩虹攻击)并将该哈希值存储在数据库中。
问题是,如果攻击者得到数据库的转储,他可以非常有效地使用暴力破解密码。他尝试的每个组合只需要几分之一毫秒,他每秒可以尝试数十万个密码。
为了解决这个问题,可以使用 bcrypt 算法,它被设计为很慢,因此如果使用 bcrypt 攻击系统,攻击者的速度会大大降低。最近 scrypt 做了一些标题,并且被一些人认为比 bcrypt 更有效,但我不知道 .Net 实现。
更新:
时代变了,我们有了 SHA3 赢家。我建议使用 SHA3 竞赛的 keccak(又名 SHA3)获胜者。
原答案:
按照从弱到强的顺序,我会说:
RIPEMD BROKEN,永远不应该使用,正如在这个 pdf 中可以看到的那样 MD-5 BROKEN,永远不应该使用,可以在 2 分钟内用笔记本电脑破坏 SHA-1 BROKEN,永远不应该使用,原则上被破坏,攻击是本周 SHA-2 WEAK 变得更好,可能会在未来几年内被打破。发现了一些弱点。请注意,通常密钥大小越大,哈希函数越难破解。虽然密钥大小 = 强度并不总是正确的,但大多数情况下都是正确的。所以 SHA-256 可能比 SHA-512 弱。 Skein NO KNOWN WEAKNESSES,是 SHA-3 的候选者。它是相当新的,因此未经测试。它已经以多种语言实现。 MD6 NO KNOWN WEAKNESSES,是 SHA-3 的另一个候选者。可能比 Skien 强,但在单核机器上速度较慢。像 Skien 一样,它未经测试。一些具有安全意识的开发人员正在使用它,担任关键任务角色。
我个人会使用 MD6,因为人们永远不会太偏执。如果速度是一个真正的问题,我会考虑 Skein 或 SHA-256。
在 MD5 的辩护中,没有已知的方法可以生成具有任意 MD5 散列的文件。原作者必须提前计划进行工作冲突。因此,如果接收方信任发送方,MD5 就可以了。如果签名者是恶意的,MD5 就会被破坏,但不知道它是否容易受到中间人攻击。
看看 BLAKE2 算法是个好主意。
如前所述,它比 MD5 更快,并且至少与 SHA-3 一样安全。它也由 several software applications 实现,包括 WinRar。
您使用哪一个实际上取决于您使用它的目的。如果您只是想确保文件在传输过程中不会损坏并且不太担心安全性,请选择快速和小型。如果您需要数十亿美元的联邦救助协议的数字签名,并且需要确保它们不是伪造的,那么请努力欺骗和放慢速度。
我想插话(在 md5 被撕裂之前)我仍然广泛使用 md5,尽管它对于很多加密货币来说是压倒性的破坏。
只要您不关心防止碰撞(您仍然可以安全地在 hmac 中使用 md5)并且您确实想要速度(有时您想要更慢的哈希),那么您仍然可以自信地使用 md5。
我不是这类事情的专家,但我跟上安全社区的步伐,那里的很多人认为 md5 哈希已损坏。我会说使用哪一个取决于数据的敏感程度和特定的应用程序。只要密钥良好且强大,您就可以摆脱安全性稍差的哈希值。
以下是我给你的建议:
如果您预期攻击,您可能应该忘记 MD5。网上有很多彩虹表,众所周知,像 RIAA 这样的公司能够生成具有等效哈希的序列。如果可以,请使用盐。在消息中包含消息长度会使产生有用的哈希冲突变得非常困难。作为一般经验法则,更多位意味着更少的冲突(根据鸽巢原理)并且更慢,并且可能更安全(除非您是可以发现漏洞的数学天才)。
请参阅此处查看论文,该论文详细介绍了使用台式 Intel P4 计算机在 31 秒内创建 md5 冲突的算法。
http://eprint.iacr.org/2006/105