何时 CRC 比 MD5/SHA1更适合使用?

什么时候适合使用 CRC 进行错误检测,而不是使用更现代的散列函数(如 MD5或 SHA1) ?前者在嵌入式硬件上更容易实现吗?

108173 次浏览

CRC32速度更快,有时还有硬件支持(比如在 Nehalem 处理器上)。实际上,只有在与硬件接口时或者性能较差的 真的时才会使用它

CRC 代码更简单、更快。

你需要什么?

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

CRC 的计算复杂度远远低于 MD5或 SHA1。对于随机错误检测来说,使用像 MD5这样的散列函数可能有些过头了。然而,使用 CRC 进行任何类型的安全检查都不如使用更复杂的哈希函数(如 MD5)安全。

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

更新 是的,这个答案已经过时了。出于安全目的,请不要使用 SHA1或 MD5;)

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

当你只是想要一个快速和轻检查和使用它。 CRC 是用在以太网。

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

CRC 是针对数据中无意的更改而设计的。 也就是说,它有助于检测非故意的错误,但是作为确保数据没有被恶意处理的方法,它将毫无用处。

也请参阅 这个

只有在计算资源非常紧张(例如一些嵌入式环境)或者需要存储/传输许多输出值和空间/带宽很紧张的情况下才使用 CRC (因为 CRC 通常是32位的,其中 MD5输出为128位,SHA1为160位,其他 SHA 变体高达512位)。

永远不要使用 CRC 进行安全检查,因为 CRC 很容易“伪造”。

即使对于意外错误检测(而不是恶意变化检测)散列也比简单的 CRC 好。部分原因是由于计算 CRC 的简单方法(部分原因是由于 CRC 值通常比一般的散列输出短,所以可能值的范围小得多) ,在有两个或更多错误的情况下,一个错误会掩盖另一个错误,所以尽管有两个错误,最终得到相同的 CRC。

简而言之: 除非你有理由使用一个像样的哈希算法 没有,避免简单的 CRC。

你没说你想保护什么。

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

CRC 也可以以类似的方式用于保护存储在 FLASH 或 EEPROM 中的配置数据。如果 CRC 不正确,那么可以将数据标记为无效,并使用默认数据集或备份数据集。由于设备故障或用户在更新配置数据存储期间移除电源,CRC 可能无效。

有评论认为,散列提供了更大的可能性检测腐败比 CRC 与多位错误。这是事实,决定是否使用16位或32位 CRC 将取决于使用损坏的数据块的安全后果,以及是否可以证明数据块被错误声明为有效的1/2 ^ 16或2 ^ 32的可能性。

许多设备都有内置的 CRC 生成器用于标准算法。来自德克萨斯州的 MSP430F5X 系列具有 CRC-CCITT 标准的硬件实现。

有关 CRC 的实现、速度和可靠性的信息,请参阅 CRC 错误检测算法的无痛指南

除非有人试图恶意修改您的数据并隐藏更改 CRC 就足够了。只要使用“好的”(标准)多项式。

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

我发现一项研究显示 对于哈希表,CRC 哈希表是如何处理的。并说明了算法的实际特点。那个研究还包括其他哈希算法的评估,是一个很好的参考保存。

更新

网站好像瘫痪了,不过是 互联网档案馆有副本

更新2

哦,亲爱的。 结果表明,这项研究可能是错误的周围的结论 CRC 作为一个散列使用。谢谢@minexew 的链接。

我在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和 你根本不在乎安全。
  • 如果需要添加安全层,请使用“ sha256”(或更高版本)。

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

    1. 当你关心安全的时候会有一些安全问题
    2. 更长的哈希字符串和慢于“ crc32b”时,所有您需要的是 CRC

让我们从最基本的开始。

在密码学中,哈希算法通过摘要运算将许多位转换为较少位。散列用于确认消息和文件的完整性。

所有散列算法都会产生冲突。冲突是指多个多位组合产生相同的较少位输出。散列算法的加密强度是由个人无法确定给定输入的输出是什么来定义的,因为如果他们可以的话,他们可以用一个与合法文件匹配的散列构造一个文件,并损害假定的系统完整性。 CRC32和 MD5的区别在于 MD5生成的散列更大,更难预测。

当您想要实现消息完整性时——意味着消息在传输过程中没有被篡改——无法预测冲突是一个重要的属性。32位杂凑可以使用40亿个不同的惟一散列来描述 40亿条不同的信息或文件。如果您有40亿个文件和1个文件,那么肯定会有1次冲突。1 TB 位空间有可能产生数十亿次碰撞。如果我是一个攻击者,我可以预测32位散列将是什么,我可以构造一个受感染的文件,与目标文件冲突; 它具有相同的散列。

此外,如果我正在做10mbps 的传输,那么一个数据包被破坏的可能性正好绕过 crc32,并继续沿着目的地和执行是非常低的。让我们假设在10mbps 我得到 每秒10个错误。如果我把速度提高到1gbps,现在我得到的是 每秒1000个错误。如果我的内存达到1 exabit 每秒,那么我有一个错误率的 每秒1,000,000,000个错误。假设我们有一个 一千一百万传输错误的碰撞率,这意味着百万分之一的传输错误会导致无法检测到的损坏数据的传输。在10mbps 的速度下,每100,000秒发送一次错误数据,大约每天一次。每5分钟就会发生一次。以每秒1微位的速度,我们每秒要讲好几次。

如果你打开 Wireshark,你会看到典型的以太网报头有一个 CRC32,你的 IP 报头有一个 CRC32,你的 TCP 报头有一个 CRC32,这是除了什么更高层的协议可以做,例如 IPSEC 可能使用 MD5或 SHA 完整性检查除了以上。在典型的网络通信中有几层错误检查,它们仍然时不时地以低于10mbps 的速度出错。

循环冗余校验(CRC)有几个常见的版本和几个不常见的版本,但通常被设计为只告诉消息或文件在传输过程中损坏(多位翻转)。CRC32本身不是一个非常好的错误检查协议,按照今天的标准,在大型、标量的企业环境中,因为碰撞率; 平均用户硬盘驱动器可以有超过10万个文件,一个公司的文件共享可以有数千万个。哈希空间与文件数量的比率太低了。实现 CRC32的计算成本很低,而 MD5则不然。

MD5的设计目的是停止故意使用冲突来使恶意文件看起来是友好的。它被认为是不安全的,因为散列空间已经被充分映射到允许发生一些攻击,而且一些冲突是可预测的。SHA1和 SHA2是新来的孩子。

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

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

下面是这些 散列函数算法之间的简短差异:

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

  • 没有是一种加密哈希算法(它使用基于循环冗余检查的线性函数)
  • 可以产生9位、17位、33位或65位
  • 不打算用于加密目的,因为没有加密保证,
  • 不适合在数字签名中使用,因为它很容易可逆 网址: http://sar.info-atik.hu-berlin.de/research/publications/SAR-PR-2006-05/SAR-PR-2006-05 _.pdf”rel = “ noReferrer”> 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的攻击,这表明它对于正在使用的 施奈尔可能不够安全。美国国家技术标准局建议,联邦机构应停止使用 SHA1-1的应用程序,需要抗碰撞,必须使用 SHA-2后,2010网站: http://csrc.NIST.gov/groups/ST/hash/policy _ 2006.html rel = “ norefrer”> NIST

因此,如果你正在寻找简单快速的解决方案来检查一个文件的完整性(防止损坏) ,或者为了一些简单的缓存目的在性能方面,你可以考虑 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

相关阅读:

在检测随机误差时,短 CRC 比相同长度的伪随机散列 好多了

多年来,这个问题已经积累了大量的答案,其中大部分是不必要的,但是还没有人指出这个关键的事实。即使可以支付计算成本,也不应该使用短的随机散列(比如截断的 MD5或 SHA-1)来捕获偶尔的翻转位,因为假负值率会很高。

这是一个成功的例子。假设您的消息是12个八位(96位)的有效负载加上1个八位用于错误检测。另外,假设每个位在传输过程中有1/10,000的机会被破坏(翻转)。注意,这意味着大约1% 的数据包将至少有一个翻转位,大约0.01% 的数据包将至少有2个翻转位,以此类推。

如果错误检测比特是一个伪随机散列(比如 MD5或 SHA-1被截断为8比特) ,那么仅限于检测比特的损坏将始终被检测到,而不限于这些比特的损坏将在255/256左右被检测到。总的来说,大约(12/13) × (1/256)≈0.36% 的受损数据包将逃避检测。

如果错误检测位是一个简单的校验和(其他字节 mod 256的总和) ,那么所有的单位翻转错误(总数的99%)将被检测到,剩下的1% ,好于7/8将被检测到。只有不到0.13% 的损坏数据包会被遗漏。因此,即使是一个简单的校验和也优于随机散列。

如果错误检测比特是 CRC-8,并且选择了适当的多项式(如 CRC-8-CCITT) ,那么1、2或3个翻转比特的所有错误将被检测到,大约127/128的其他错误将被检测到。丢失的损坏数据包少于0.00000002% 。

使用 CRC 不仅仅是因为它们计算速度快(尽管它们确实如此ーー特别是在硬件上) ,还因为它们是检测特定类型错误的 非常非常好。即使您使用的硬件计算截断的 MD5的速度比计算 CRC-8的速度要快,您可能仍然应该使用 CRC。


如果校验和的空间大得多——比如说128位——那么情况就不同了。CRC-128在理论上仍然比128位随机哈希有优势,但是随机哈希的假负率(大约2-128)已经很低了,可以认为它是零; 再低一点也没有什么实际好处。如果在这种情况下您可以使用 MD5散列,那么您也可以使用它。

如果您试图检测 恶意介绍错误,那么事情会变得更加复杂。在这种情况下,有必要使用某种加密散列(不是 CRC) ,但这远远不够。如果您真的需要设计一个能够安全抵御恶意干扰的协议,那么您应该在 Cryptography StackExchange 中询问它。不要以为使用 SHA-3或 BLAKE2这样的现代散列就足以保证您的安全。很可能不是。