什么时候使用CRC比MD5 / SHA1更合适?


130

与更现代的哈希函数(例如MD5或SHA1)相比,何时使用CRC进行错误检测更合适?前者在嵌入式硬件上更容易实现吗?

Answers:


114

CRC可以很好地检测可能发生的数据中的随机错误,例如网络干扰,线路噪声,失真等。

CRC在计算上比MD5或SHA1复杂得多。使用MD5之类的哈希函数可能对于随机错误检测来说是多余的。但是,将CRC用于任何类型的安全检查将比更复杂的哈希功能(例如MD5)安全性低得多。

是的,CRC在嵌入式硬件上更容易实现,您甚至可以在IC上获得不同的打包解决方案。


1
@gili:您总是可以将双字异或在一起,以获得单个结果双字。
布林迪

2
@Dustin:您的回答是完全正确的,但是也许考虑将“ CRC在计算上更有效”改为“ CRC在计算上更容易”?MD5 / SHA-1算法很复杂,但并不是真正“低效”的IMO。
Coxy

1
@coxymla您是正确的,我应该使用的单词是“复杂”而不是“低效”。谢谢!
定义2010年

27
要将任何长哈希减少到32位,只需采用前32位即可。
Orip 2010年

1
如果您的目标是安全性,那么就永远不要使用MD5SHA-1也应该避免使用,建议使用的一些变体SHA-2
彼得

33

CRC旨在防止数据意外更改。也就是说,它对于检测意外错误很有用,但是作为确保未恶意处理数据的一种方式将毫无用处。

另请参阅


此答案中链接中最重要的部分:“(...)甚至2048位CRC的加密安全性也比128位MD5低得多”
Marc.2377

3
尽管答案仍然是正确的,但如今MD5和SHA1处于相同的安全级别。换句话说,仅对于检测意外错误有用。
Piskvor

21

我发现了一项研究,该研究表明哈希表的CRC哈希有多么不合适。它还说明了该算法的实际特征。该研究还包括对其他哈希算法的评估,并且可以作为很好的参考。

有关CRC哈希的相关结论:

CRC32从未打算用于哈希表。确实没有充分的理由为此目的使用它,我建议您避免这样做。如果决定使用CRC32,则必须从与密钥八比特组馈入相反的那一端使用哈希位,这一点至关重要。这取决于特定的CRC32实现。不要将CRC32视为“黑匣子”哈希函数,也不要将其用作通用哈希。确保测试其每个应用程序的适用性。

更新

看来该网站已关闭。在互联网档案馆有一个副本,但。


链接断开。也许您可以自己撰写说明?如果没有,答案是没有用的。
ceving 2014年

好的,我将结论包含在答案中。
Andre Luus 2014年

很奇怪,根据这里的基准,CRC实际上在速度和冲突数量方面做得很好。
ostrokach

确实很有趣。我不得不再次检查链接到的研究,但是如果我不得不猜测那一定是由于不同的测试实现。如果必须做出决定,我会从研究中寻求建议,这似乎更加科学合理。
Andre Luus 2015年

根据我对数百万个URL进行哈希处理的经验,CRC64冲突了8次,MD5冲突了5次。显然,MD5更好,但是CRC64是一个很棒的哈希表,速度更快,更简单。
J. Dimeo

18

我在1.000.000循环中运行了此PHP代码的每一行。结果以注释(#)表示。

hash('crc32', 'The quick brown fox jumped over the lazy dog.');#  750ms   8 chars
hash('crc32b','The quick brown fox jumped over the lazy dog.');#  700ms   8 chars
hash('md5',   'The quick brown fox jumped over the lazy dog.');#  770ms  32 chars
hash('sha1',  'The quick brown fox jumped over the lazy dog.');#  880ms  40 chars
hash('sha256','The quick brown fox jumped over the lazy dog.');# 1490ms  64 chars
hash('sha384','The quick brown fox jumped over the lazy dog.');# 1830ms  96 chars
hash('sha512','The quick brown fox jumped over the lazy dog.');# 1870ms 128 chars

我的结论是:

  • 当需要http://en.wikipedia.org/wiki/Cyclic_redundancy_check且不关心安全性时,请使用“ crc32b” 。
  • 需要添加安全层时,请使用“ sha256”(或更高版本)。

  • 不要使用“ md5”或“ sha1”,因为它们具有:

    1. 您关心安全性时的一些安全性问题
    2. 当您只需要CRC时,散列字串会更长,且比“ crc32b”慢

您的意思是位,而不是字符
esskar

并不是的。echo hash('crc32','那只敏捷的棕色狐狸跳过了那只懒狗。'); 回显“ 413a86af”,是8个字符长的字符串。顺便说一句,它是以HEX格式存储的32位数字。例如,“ sha256”具有256位哈希值,又存储为十六进制,即64个字符长的字符串。
马丁

45
这些结果非常具有欺骗性。将这些哈希算法应用于大型数据集(以War和Peace代替"The quick brown fox jumped over the lazy dog.")时,您会发现CRC比MD5快多少。
2012年

1
有一个中间情况(在库中重复检查),其中MD5 / Sha1是正确的解决方案:他们不需要处理对手精心打造几乎不可能消失的哈希冲突的情况,但确实需要处理意外冲突。因此:检测位错误和损坏:CRC32检测库中的冲突:MD5 / SHA1对抗应用程序:Sha256及更高版本。当然,如果您的图书馆有数十亿个条目,那么您可能还需要增加哈希位。
Dewi Morgan

PHP的?在ARM平台上,嵌入式代码为16MHz,46字节的CRC32,可能为12微秒。那有硬件协助。甚至硬件辅助的AES也会慢几百倍。无辅助查找表CRC仍应在50微秒左右。
ilgitano

11

有关实现,速度和可靠性的CRC信息,请参阅CRC错误检测算法的无痛指南。它具有CRC上的所有内容。

除非有人打算恶意修改您的数据并隐藏更改,否则CRC就足够了。只需使用“良好”(标准)政策即可。


9

这完全取决于您的要求和期望。

以下是这些哈希函数算法之间的简要区别:

CRC(CRC-8 / 16/32/64)

  • 加密的哈希算法(它使用基于循环冗余校验的线性函数)
  • 可以产生9、17、33或65位
  • 不能用于加密目的,因为不做任何加密保证,
  • 不适合用于数字签名,因为它很容易反转2006
  • 不应用于加密目的,
  • 不同的字符串会产生碰撞,
  • 于1961年发明,并用于以太网和许多其他标准,

MD5

  • 是一种密码哈希算法,
  • 产生一个128位(16字节)的哈希值(32位十六进制数字)
  • 它是一个加密哈希,但是如果您担心安全性,则认为它已弃用,
  • 已知的字符串具有相同的MD5哈希值
  • 可以用于加密目的,

SHA-1

  • 是一种密码哈希算法,

  • 产生一个160位(20字节)的哈希值,称为消息摘要

  • 它是一个加密哈希,自2005年以来,它不再被认为是安全的,

  • 可以用于加密目的,

  • 发现sha1碰撞的一个例子

  • 最早于1993年(以SHA-0的形式)发布,然后在1995年以SHA-1的形式发布,

  • 系列:SHA-0,SHA-1,SHA-2,SHA-3,

    综上所述,使用SHA-1不再被认为可以抵抗资金充裕的对手,因为2005年,密码分析家发现对SHA-1的攻击,这表明它对于持续使用Schneier可能不够安全。美国国家标准与技术研究院(NIST)建议,联邦机构应停止将SHA1-1用于要求抗碰撞的应用,并且必须在2010 NIST之后使用SHA-2 。

因此,如果您正在寻找一种简单,快速的解决方案来检查文件的完整性(针对损坏),或者出于性能方面的考虑,可以考虑使用CRC-32,对于哈希,您可以考虑使用MD5,但是,如果您正在开发专业应用程序(应该是安全且一致的),请避免使用任何碰撞概率-请使用SHA-2及更高版本(例如SHA-3)。

性能

PHP中的一些简单基准测试:

# Testing static text.

$ time php -r 'for ($i=0;$i<1000000;$i++) crc32("foo");'
real    0m0.845s
user    0m0.830s
sys     0m0.008s

$ time php -r 'for ($i=0;$i<1000000;$i++) md5("foo");'
real    0m1.103s
user    0m1.089s
sys     0m0.009s

$ time php -r 'for ($i=0;$i<1000000;$i++) sha1("foo");'
real    0m1.132s
user    0m1.116s
sys   0m0.010s

# Testing random number. 

$ time php -r 'for ($i=0;$i<1000000;$i++) crc32(rand(0,$i));'
real    0m1.754s
user    0m1.735s
sys     0m0.012s\

$ time php -r 'for ($i=0;$i<1000000;$i++) md5(rand(0,$i));'
real    0m2.065s
user    0m2.042s
sys     0m0.015s

$ time php -r 'for ($i=0;$i<1000000;$i++) sha1(rand(0,$i));'
real    0m2.050s
user    0m2.021s
sys     0m0.015s

有关:


8

您没有说您要保护的是什么。

CRC通常在嵌入式系统中用作检查意外数据损坏的方法,而不是防止恶意系统修改。CRC有用的地方的例子是在系统初始化期间验证EPROM映像,以防止固件损坏。系统引导加载程序将计算应用程序代码的CRC,并在允许代码运行之前将其与存储的值进行比较。这样可以防止程序意外损坏或下载失败的可能性。

CRC也可以类似的方式用于保护存储在闪存或EEPROM中的配置数据。如果CRC错误,则可以将数据标记为无效,并使用默认或备份数据集。由于设备故障或用户在更新配置数据存储期间断电,CRC可能无效。

有评论认为,与具有多个比特错误的CRC相比,散列提供更大的检测损坏的可能性。的确如此,是否使用16或32位CRC的决定将取决于使用损坏的数据块的安全后果,以及您是否可以证明2 ^ 16或2 ^ 32的机会是1。数据块被错误地声明为有效。

许多设备具有用于标准算法的内置CRC生成器。德州(TI)的MSP430F5X系列具有CRC-CCITT标准的硬件实现。


6

CRC32更快,散列长度只有32位。

仅在需要快速轻松的校验和时使用它。CRC用于以太网。

如果需要更高的可靠性,最好使用现代的哈希函数。


5

仅在计算资源非常紧张(例如某些嵌入式环境)或您需要存储/传输许多输出值且空间/带宽很紧凑的情况下才使用CRC(因为CRC通常为32位,而MD5输出为128位,SHA1 160位以及其他SHA变体(最高512位)。

切勿使用CRC进行安全检查,因为CRC非常容易“伪造”。

即使对于意外错误检测(而不是恶意更改检测),哈希也比简单的CRC更好。一方面是因为计算CRC的简单方法(另一方面,由于CRC值通常比普通哈希输出短,因此可能值的范围要小得多),在出现两个或多个错误的情况下,可能性更大,一个错误将掩盖另一个错误,因此尽管有两个错误,您仍然会得到相同的CRC。

简而言之:除非您有理由使用体面的哈希算法,否则请避免使用简单的CRC。


1
如果使用正确的多项式,CRC将捕获所有意外的数据更改。如果恰好更改了正确的多个位,则会丢失1/2 ^ 32的更改。
Gerhard

并且使用适当的多项式,它还将捕获某些常见类的所有错误,例如突发错误。
erikkallen

除了问题与嵌入式系统有关之外,我同意您的回答。在较小的嵌入式系统上,密码算法的性能可能会出现问题。
Craig McQueen

绝对不同意这一点。CRC错误多项式经过精心选择,因此在某些情况下,它们可以可证明地检测到1,2,3,5和突发错误,最高可达11位。加密哈希纯粹是统计性的,因此您必须使用较大的摘要值。8-32位对于密码哈希摘要是不现实的,并且在cpu循环和门中毫无意义地昂贵。如果您在嵌入式系统上工作,绝对不是要接受的答案。唯一不使用CRC的时间是您必须处理聪明的对手情况。
ilgitano '18

5

我最近发现使用CRC很聪明。的作者jdupe文件重复识别和删除工具(流行的EXIF工具的jhead的同一作者)第一次通过文件中使用它。在每个文件的前32K上计算CRC,以标记看起来相同的文件,而且文件的大小也必须相同。这些文件将添加到要进行完整二进制比较的文件列表中。它加快了检查大型媒体文件的速度。


这种方法的一个问题是,在其中包含嵌入式CRC32的文件上运行时,生成的CRC可能与文件中的数据无关(因为如果数据发生更改,则CRC32将被更改以抵消差异。 )。在计算CRC32之前以某种简单方式修改数据可以避免该问题。
超级猫

1
@supercat-我真的不相信这实际上是一个问题。如果文件包含的crc32标头(即文件其余部分的crc32),则在更新文件时,crc32标头中的每一位将有大约50%的机会不同。标头中的更改应遵循相当随机的分布。我看不到这将如何导致CRC32(header + data)始终相同,或者以任何方式不依赖于文件的数据部分。
2011年

@teratorn:我已经看到许多文件的末尾都有CRC32,其计算方式是,使用某些特定的种子常量计算出的整个文件的CRC32将始终是其他常量值。这在诸如二进制代码映像之类的事情中很常见。如果Acme 1000 DVD播放器使用固定大小的代码映像进行固件升级,并且希望每个代码映像都具有特定的CRC32,则计算各种文件的CRC32的例程将无法区分Acme 1000的不同代码映像。
supercat

在这种情况下,CRC的目的是快速识别文件是否不同。如果CRC恢复不变,那么您现在必须进行昂贵的二进制比较,因此嵌入式CRC不会破坏算法。可能会发生某些文件最终是二进制文件比较的情况,因为CRC第一次通过时说它们可能相同,但其中许多文件可能不大,因此您可以使用自定义多项式来避免这种情况。
ilgitano '18

4

CRC32速度更快,并且有时具有硬件支持(即在Nehalem处理器上)。确实,只有在与硬件接口或性能非常紧张时才使用它


4

让我们从基础开始。

在密码术中,哈希算法通过摘要操作将许多位转换为更少的位。哈希用于确认消息和文件的完整性。

所有哈希算法都会产生冲突。一个冲突是当几个多位组合产生相同的更少位输出时。散列算法的密码强度由个人无法确定给定输入的输出内容来定义,因为如果他们能够构建具有与合法文件匹配的散列并损害假定完整性的文件系统的。CRC32和MD5之间的区别在于MD5会生成一个较大的哈希,很难预测。

当您想要实现消息完整性时-意味着消息在传输过程中未被篡改-无法预测冲突是重要的属性。一个32位的哈希可以使用40亿个不同的唯一散列来描述40亿个不同的消息或文件。如果您有40亿个文件和1个文件,则可以确保发生1次冲突。1 TB的位空间有可能发生数十亿次碰撞。如果我是攻击者,并且可以预测32位哈希将是什么,则可以构造一个与目标文件冲突的受感染文件。具有相同的哈希值。

此外,如果我正在执行10mbps传输,则数据包被破坏的可能性恰好是绕过crc32并继续沿目的地到达并执行的可能性很小。假设以10mbps的速度出现10错误/秒。如果我将其提高到1gbps,现在每秒将收到1,000个错误。如果我每秒提高1 EB,那么我的错误率就是每秒1,000,000,000个错误。假设我们的碰撞率为1 \ 1,000,000传输错误,意味着百万个传输错误中的1导致损坏的数据无法通过检测。以10mbps的速度发送的错误数据每100,000秒或大约每天发送一次。以1gbps的速度每5分钟发生一次。以每秒1埃比特的速度,我们每秒谈论几次。

如果弹出Wireshark,您将看到典型的以太网头具有CRC32,IP头具有CRC32,TCP头具有CRC32,这是高层协议可能要做的工作;例如,除上述以外,IPSEC可能还使用MD5或SHA进行完整性检查。在典型的网络通信中,错误检查存在几层,并且仍然以低于10mbps的速度反复失误。

循环冗余校验(CRC)有几种常见的版本,有几种不常见的版本,但通常旨在仅告诉消息或文件在传输过程中已损坏(多位翻转)。在大型标量企业环境中,由于冲突率,CRC32本身并不是一种很好的错误检查协议。平均每个用户的硬盘驱动器可以拥有超过10万个文件,而公司的文件共享可以有数千万个文件。哈希空间与文件数的比率太低。CRC32在计算上实现起来很便宜,而MD5则不是。

MD5旨在阻止故意使用冲突以使恶意文件看起来良好。之所以认为这是不安全的,是因为哈希空间已被充分映射以允许发生某些攻击,并且某些冲突是可预测的。SHA1和SHA2是新手。

对于文件验证,Md5开始被许多供应商使用,因为您可以使用它快速处理多千兆字节文件或多兆字节文件,并将其堆叠在通用操作系统的使用和对CRC32的支持之上。如果在未来十年内文件系统开始使用MD5进行错误检查,请不要感到惊讶。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.