我应该select哪种密码散列函数?

.NET框架提供了6种不同的哈希algorithm:

  • MD5:16字节(散列时间500MB:1462毫秒)
  • SHA1:20个字节(1644毫秒)
  • SHA256:32个字节(5618毫秒)
  • SHA3​​84:48个字节(3839毫秒)
  • SHA512:64个字节(3820毫秒)
  • RIPEMD:20个字节(7066毫秒)

这些function中的每一个function都不相同 MD5是最快的,RIPEMD是最慢的。

MD5的优点是它适合内置的Guidtypes。 这使得它很容易用于识别。

然而,MD5很容易受到碰撞攻击 ,SHA1也是脆弱的,但程度较低。

我应该在什么条件下使用散列algorithm?

具体问题我真的很好奇,看到回答是:

  • MD5不被信任? 在正常情况下,当你使用MD5algorithm而没有恶意的意图,没有任何第三方有任何恶意的意图时,你会期待任何冲突(意味着两个任意字节[]产生相同的散列)

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

  • 散列文件名(或其他短string)时获得非恶意冲突的几率是多less? (例如,具有相同MD5散列的2个随机文件名)(使用MD5 / SHA1 / SHA2xx)一般来说,非恶意冲突的几率是多less?

这是我使用的基准:

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. 碰撞阻力 :有人find两条散列相同的消息( 任何两条消息)有多困难。
  2. Preimage Resistance :给定一个散列,要find另一个散列相同的消息有多困难? 也称为单向散列函数
  3. 第二原像阻力 :给定一个消息,find另一个哈希相同的消息。

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

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

SHA1有一个缺陷,允许在理论上发现碰撞远小于2 ^ 80步长的安全哈希函数的长度将需要。 攻击不断被修改,目前可以在2 ^ 63步骤内完成 – 仅仅在目前的可计算性范围内。 出于这个原因,NIST正在逐步淘汰使用SHA1,指出SHA2系列应该在2010年之后使用。

SHA2是在SHA1之后创build的一个新的散列函数族。 目前还没有针对SHA2function的已知攻击。 SHA256,384和512都是SHA2系列的一部分,只是使用不同的密钥长度。

RIPEMD我不能太多评论,除了要注意的是它不像SHA家族那样普遍使用,所以密码学研究者也没有仔细研究过。 仅仅因为这个原因,我会build议在其上使用SHA函数。 在你使用的实现中,它似乎也很慢,这使得它不太有用。

总之,没有最好的function – 这一切都取决于你需要什么。 注意每个的缺陷,你最好能够为你的场景select正确的散列函数。

所有散列函数都“破碎”

鸽舍的原则是尽可能的努力,如果你不能在两洞里放2羽以上的鸽子(除非你把鸽子砍掉)。 同样的,你不能在2 ^ 128个插槽中插入2 ^ 128 + 1的数字。 所有散列函数都会导致有限大小的散列,这意味着如果您search“有限大小”+ 1序列,则总是可以find冲突。 这样做是不可行的。 不适用于MD5,不适用于Skein 。

MD5 / SHA1 / Sha2xx没有机会碰撞

所有的哈希函数都有碰撞,这是一个事实。 偶然碰到这些碰撞就相当于赢得星系间彩票 。 也就是说, 没有人赢得星系间彩票 ,而不是彩票的工作方式。 你将不会遇到意外的MD5 / SHA1 / SHA2XXX散列,EVER。 每一种字典中的每一个字,每种语言,都有不同的价值。 每个path名称在整个星球上的每台机器上都有不同的MD5 / SHA1 / SHA2XXX散列。 我怎么知道,你可能会问。 那么,正如我之前所说,没有人赢得星系间彩票,永远。

但是…… MD5坏了

有时它的破坏并不重要

就目前来看,在MD5上没有已知的预映像或第二次预映像攻击 。

那么关于MD5是如何被破坏的,你可能会问? 第三方有可能生成2条消息,其中一条是EVIL,另一条是GOOD,这两条消息的哈希值相同。 ( 碰撞攻击 )

尽pipe如此,如果您需要预镜像电阻,目前的RSAbuild议不要使用MD5。 当涉及到安全algorithm的时候,人们倾向于谨慎行事。

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

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

在我之后重复这个, MD5碰撞没有机会 ,可以仔细devise恶意的碰撞。 即使在MD5上还没有发现任何已知的镜像前攻击,安全专家的观点是,在您需要防范镜像前攻击时,不应使用MD5。 SAME用于SHA1

请记住,并非所有的algorithm都需要防御预映像或碰撞攻击。 拿你的高清第一遍search重复文件的琐事。

  • 如果你想要一个密码安全的散列函数,使用基于SHA2XX的函数。

没有人发现任何SHA512碰撞。 EVER。 他们真的很努力 对于这个问题,从来没有人发现任何SHA256或384碰撞。 。

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

RIPMED没有收到SHAX和MD5收到的相同数量的审查。 SHA1和RIPEMD都容易受到生日攻击。 他们都比.NET上的MD5慢,并且有20个字节的大小。 它没有意义使用这些function,忘记它们。

SHA1碰撞攻击降至2 ^ 52,在SHA1冲突出现之前不会太长。

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

但等一下还有更多

有一个快速的哈希函数可以是一个诅咒。 例如:散列函数的一个非常常见的用法是密码存储。 本质上,你可以计算一个密码的哈希结合一个已知的随机string(阻止彩虹攻击)并将该哈希存储在数据库中。

问题是,如果攻击者得到数据库的转储,他可以用暴力猜测密码。 他所尝试的每一种组合只需要几毫秒的时间,而且他每秒可以尝试数十万个密码。

要解决这个问题,可以使用bcryptalgorithm,它的devise速度很慢,所以攻击者在使用bcrypt攻击系统时会大大减慢速度。 最近scrypt已经有了一些标题,被某些人认为比bcrypt更有效,但我不知道.Net的实现。

更新:

时代已经改变,我们有一个SHA3的赢家。 我build议使用SHA3​​竞赛的keccak (又名SHA3 )获胜者。

原始答案:

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

  1. RIPEMD BROKEN,永远不要使用, 因为可以在这个pdf中看到
  2. MD-5 BROKEN,不应该使用, 可以用笔记本电脑在2分钟内打破
  3. SHA-1 BROKEN,不应该被使用, 主要是破坏,攻击是由一个星期逐渐好转
  4. SHA-2弱点,未来几年可能会被打破。 有一些弱点被发现。 请注意,通常密钥越大,散列函数就越难破坏。 虽然关键尺寸=强度并不总是如此,但大多数情况是如此。 所以SHA-256可能比SHA-512弱。
  5. Skein NO KNOWN WEAKNESSES, 是SHA-3的候选人 。 这是相当新的,因此未经testing。 它已经在一堆语言中实现。
  6. MD6 NO KNOWN WEAKNESSES,是另一个SHA-3的候选人。 可能比Skien强,但在单核机器上速度较慢。 像Skien一样,它是未经testing的。 一些具有安全意识的开发人员正在使用它, 担任任务关键angular色 。

就我个人而言,我会使用MD6,因为从来没有太偏执。 如果速度是一个真正的问题,我会看看Skein,或者SHA-256。

你使用哪一个真的取决于你使用的是什么。 如果你只是想确保文件在传输过程中不被破坏,并且不关心安全性,那就快点小吧。 如果你需要数十亿美元的联邦救助协议的数字签名,并且需要确保他们没有被伪造,那就去拼命欺骗,慢下来。

我想在md5被拆解之前,尽pipe我们仍然使用md5,但是我们仍然使用了很多encryption技术。

只要你不在意碰撞的保护(你仍然可以安全地在hmac中使用md5)并且你需要速度(有时你想要一个较慢的散列),那么你仍然可以自信地使用md5。

在MD5的防御中,没有任何已知的方法来产生一个任意MD5散列的文件。 原作者必须提前计划进行工作碰撞。 因此,如果接收者信任发送者,MD5是好的。 如果签名者是恶意的,那么MD5被破坏,但是不知道它容易受到中间人攻击。

看看BLAKE2algorithm是一个很好的想法。

如上所述,它比MD5更快,至less和SHA-3一样安全。 它也通过几个软件应用程序来实现 ,包括WinRar。

我不是这方面的专家,但是我跟上了安全社区,那里的很多人都认为md5散列被破坏了。 我会说哪一个使用取决于数据的敏感程度和特定的应用程序。 只要关键是好的和强大的,你或许可以逃脱一个稍微不太安全的散列。

以下是我对你的build议:

  1. 如果您预计会发生攻击,您可能应该忘记MD5。 网上有许多彩虹表 ,像RIAA这样的公司已经知道能够产生具有相同散列的序列。
  2. 如果可以,请使用盐 。 在消息中包含消息长度可以使得很难做出有用的散列冲突。
  3. 作为一般的经验法则,更多的比特意味着更less的碰撞(通过鸽子的原理)和更慢,也许更安全(除非你是一个可以发现漏洞的math天才)。

在这里可以看到一篇文章,详细介绍了一个在台式机Intel P4计算机上31秒内创buildmd5冲突的algorithm。

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