尽管在错误检测中非常有用,CRC并不能可靠地验证数据完整性(即数据没有发生任何变化),这是因为CRC多项式是线性结构,可以非常容易地故意改变数据而维持CRC不变,参见CRC and how to Reverse it (页面存档备份,存于互联网档案馆)中的证明。可以用讯息鉴别码验证数据完整性。
CRC发生碰撞的情况
编辑
与所有其它的散列函数一样,在一定次数的碰撞测试之后CRC也会接近100%出现碰撞。CRC中每增加一个数据位,碰撞机率就会减少接近50%,如CRC-20与CRC-21相比。
理论上来讲,CRC64的碰撞概率大约是每18×1018个CRC码出现一次。
由于CRC的不分解多项式特性,所以经过合理设计的较少位数的CRC可能会与使用较多数据位但是设计很差的CRC的效率相媲美。在这种情况下CRC-32几乎同CRC-40一样优秀。
设计CRC多项式
编辑
生成多项式的选择是CRC算法实现中最重要的部分,所选择的多项式必须有最大的错误检测能力,同时保证总体的碰撞概率最小。多项式最重要的属性是它的长度,也就是最高非零系数的数值,因为它直接影响著计算的校验和的长度。
最常用的多项式长度有
9位(CRC-8)
17位(CRC-16)
33位(CRC-32)
65位(CRC-64)
在构建一个新的CRC多项式或者改进现有的CRC时,一个通用的数学原则是使用满足所有模运算不可分解多项式约束条件的多项式。
这种情况下的不可分解是指多项式除了1与它自身之外不能被任何其它的多项式整除。
生成多项式的特性可以从算法的定义中推导出来:
如果CRC有多于一个的非零系数,那么CRC能够检查出输入消息中的所有单数据位错误。
CRC可以用于检测短于2k的输入消息中的所有双位错误,其中k是多项式的最长的不可分解部分的长度。
如果多项式可以被x+1整除,那么不存在可以被它整除的有奇数个非零系数的多项式。因此,它可以用来检测输入消息中的奇数个错误,就像奇偶校验函数那样。