.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容易受到影响,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();
}
9 回答
在密码学中,散列函数提供三个独立的函数 .
Collision resistance :有人找到两条散列相同的消息(任意两条消息)有多难 .
Preimage Resistance :给定哈希值,找到另一个哈希相同的消息有多难?也称为单向散列函数 .
Second preimage resistance :给定一条消息,找到另一条散列相同的消息 .
这些属性是相关但独立的 . 例如,碰撞阻力意味着第二前像素阻力,但不是相反 . 对于任何给定的应用程序,您将有不同的要求,需要这些属性中的一个或多个 . 用于保护服务器上的密码的哈希函数通常仅需要前映像素阻力,而消息摘要需要全部三个 .
已经表明MD5不是抗冲击的,但是并不排除其在不需要抗碰撞性的应用中的使用 . 实际上,MD5通常仍用于较小的密钥大小和速度有益的应用中 . 也就是说,由于其缺陷,研究人员建议在新场景中使用其他哈希函数 .
SHA1有一个缺陷,允许在理论上发现碰撞远远小于其长度的安全散列函数需要的2 ^ 80步 . 攻击不断被修改,目前可以在~2 ^ 63步骤中完成 - 几乎不在当前的可计算性范围内 . 因此,NIST正在逐步停止使用SHA1,并指出应在2010年之后使用SHA2系列 .
SHA2是在SHA1之后创建的一个新的哈希函数族 . 目前没有针对SHA2功能的已知攻击 . SHA256,384和512都是SHA2系列的一部分,只使用不同的密钥长度 .
RIPEMD我不能过多地评论,除非注意它不像SHA系列那样常用,因此加密研究人员并没有仔细检查 . 仅仅因为这个原因,我建议使用SHA函数 . 在您使用它的实现中,它似乎也很慢,这使它变得不那么有用 .
总之,没有一个最好的功能 - 这一切都取决于你需要它 . 请注意每个方面的缺陷,您最好能够为您的方案选择正确的哈希函数 .
所有哈希函数都“破碎”
pigeonhole principle表示尽可能努力,你不能在2洞中超过2只鸽子(除非你切断鸽子) . 同样,你不能在2 ^ 128个插槽中放入2 ^ 128个1个数字 . 所有散列函数都会产生有限大小的散列,这意味着如果搜索"finite size" 1序列,您总能找到碰撞 . 这样做是不可行的 . 不适用于MD5而不适用于Skein .
MD5 / SHA1 / Sha2xx没有机会碰撞
所有散列函数都有碰撞,这是生活中的事实 . 偶然发生这些碰撞相当于 winning the intergalactic lottery . 也就是说,no one wins the intergalactic lottery,它不是彩票的工作方式 . 您永远不会遇到意外的MD5 / SHA1 / SHA2XXX哈希,永远 . 每种语言中的每个单词,每种语言,都会散列到不同的值 . 整个星球上的每台机器上的每个路径名都有不同的MD5 / SHA1 / SHA2XXX哈希值 . 我怎么知道,你可能会问 . 好吧,正如我之前所说,从来没有人赢得星际彩票 .
但...... MD5坏了
Sometimes the fact that its broken does not matter .
目前在MD5上没有已知的pre-image or second pre-image attacks .
那么你可能会问,关于MD5有什么打破?第三方可能生成2条消息,其中一条消息是EVIL,另一条消息是GOOD,它们都散列到相同的值 . (Collision attack)
尽管如此,如果您需要预映像电阻,目前的RSA建议不要使用MD5 . 在安全算法方面,人们往往会谨慎行事 .
那么我应该在.NET中使用什么哈希函数?
在我之后重复这个, there are no chance MD5 collisions ,可以精心设计恶意碰撞 . 尽管到目前为止MD5上还没有已知的预映像攻击,但安全专家认为MD5不应该用于需要防御前映像攻击的地方 . SAME goes for SHA1 .
请记住,并非所有算法都需要防御前映像或碰撞攻击 . 在第一遍搜索HD的重复文件的简单案例 .
没有人发现任何SHA512碰撞 . EVER . 他们非常努力 . 就此而言,没有人发现任何SHA256或384碰撞 . .
RIPMED没有收到SHAX和MD5收到的相同数量的审查 . SHA1和RIPEMD都容易受到生日攻击 . 它们都比.NET上的MD5慢,并且具有笨拙的20字节大小 . 使用这些功能毫无意义,忘了它们 .
SHA1碰撞攻击降低到2 ^ 52,它不会太长,直到SHA1碰撞在野外 .
有关各种哈希函数的最新信息,请查看the hash function zoo .
但等等还有更多
拥有 fast 哈希函数可能是一个诅咒 . 例如:哈希函数的一个非常常见的用法是密码存储 . 实质上,您计算密码的哈希值与已知的随机字符串(以阻止彩虹攻击)并将该哈希值存储在数据库中 .
问题是,如果攻击者获得数据库的转储,他可以使用暴力来非常有效地猜测密码 . 他尝试的每个组合只需要几分之一毫秒,他可以每秒尝试数十万个密码 .
要解决此问题,可以使用bcrypt算法,它设计得很慢,因此如果使用bcrypt攻击系统,攻击者将会大大减速 . 最近scrypt已经成为一些 Headers ,并被一些人认为比bcrypt更有效,但我不知道.Net实现 .
更新:
时代变了,我们有一个SHA3冠军 . 我建议使用SHA3比赛的keccak(又名SHA3)获胜者 .
原文答案:
为了最弱到最强,我会说:
RIPEMD BROKEN,永远不应该使用as can be seen in this pdf
MD-5 BROKEN,永远不应该使用,can be broken in 2 minutes with a laptop
SHA-1 BROKEN,永远不能使用,is broken in principal, attacks are getting better by the week
SHA-2 WEAK,未来几年可能会被打破 . A few weaknesses have been found.请注意,通常密钥越大,散列函数越难破解 . 虽然密钥大小=强度并非总是如此,但大多数情况下都是如此 . 所以SHA-256可能比SHA-512弱 .
没有知道弱点,is a candidate for SHA-3 . 它是相当新的,因此未经测试 . It has been implemented in a bunch of languages.
MD6 NO KNOWN WEAKNESSES,是SHA-3的另一个候选者 . 可能比Skien强,但在单核机器上速度较慢 . 像Skien一样,它是未经测试的 . 一些具有安全意识的开发人员正在mission critical roles中使用它 .
就个人而言,我会使用MD6,因为一个人永远不会太偏执 . 如果速度是一个真正的问题,我会看看Skein,或SHA-256 .
在MD5的防御中,没有已知的方法来生成具有任意MD5哈希的文件 . 原作者必须提前计划进行工作碰撞 . 因此,如果接收者信任发送者,MD5就可以了 . 如果签名者是恶意的,MD5就会被破坏,但不知道它是否容易受到攻击中间人攻击 .
你使用哪一个真正取决于你使用它 . 如果您只是想确保文件在传输过程中没有损坏,并且不关心安全性,请选择快速和小型 . 如果您需要数十亿美元的联邦救助协议的数字签名,并且需要确保它们不是伪造的,那么就难以欺骗和放慢速度 .
我想在(在md5被撕裂之前)插话,我仍然广泛使用md5,尽管它有很多加密的破坏性 .
只要你不关心防止冲突(你仍然可以安全地在hmac中使用md5)并且你确实想要速度(有时你想要更慢的哈希),那么你仍然可以自信地使用md5 .
看看BLAKE2 algorythm是一个很好的想法 .
如上所述,它比MD5快,至少和SHA-3一样安全 . 它也由several software applications实现,包括WinRar .
我不是这方面的专家,但是我跟安全社区保持联系,很多人认为md5哈希打破了 . 我想说使用哪一个取决于数据的敏感程度和具体应用 . 只要密钥良好且强大,您就可以使用稍微不那么安全的哈希 .
以下是我给你的建议:
如果你预料到攻击,你应该忘记MD5 . 网上有很多rainbow tables,众所周知像RIAA这样的公司能够生成具有等效哈希值的序列 .
如果可以,请使用salt . 在消息中包含消息长度可能使得很难进行有用的哈希冲突 .
作为一般的经验法则,更多的比特意味着更少的碰撞(通过鸽子原理)和更慢,也许更安全(除非你是一个能找到漏洞的数学天才) .
请参阅此处,了解详细说明使用台式机Intel P4计算机在31秒内创建md5冲突的算法的文章 .
http://eprint.iacr.org/2006/105