本内容不讨论任何关于CRC如何计算以及验证的问题,仅仅讨论CRC是如何实现检测错误的。对于仅仅需要备考的朋友们就可以选择忽视该文章了。
错误类型 | CRC 检测能力 |
---|---|
单比特错误 | 100% 可检测 |
双比特错误 | 100%(当 G(x)适当选择) |
短突发错误 | 100%(长度 ≤ r) |
长突发错误 | 几乎 100% |
特殊模式错误 | 可能检测不到 |
后文中,我们将按照如下的变量来定义所需公式:
原始数据对应的二进制位序列(待发送数据):
M ( x ) = m n x n + m n − 1 x n − 1 + . . . + m 1 x + m 0 M(x)=m_{n}x^n+m_{n-1}x^{n-1}+...+m_{1}x+m_{0} M(x)=mnxn+mn−1xn−1+...+m1x+m0
生成多项式:
G ( x ) = g n x n + . . . + g 0 G(x)=g_{n}x^n+...+g_{0} G(x)=gnxn+...+g0
校验位:
R ( x ) R(x) R(x)
发送端发送的数据:
T ( x ) = M ( x ) + R ( x ) T(x)=M(x)+R(x) T(x)=M(x)+R(x)
接收端接收到的错误比特位:
E ( x ) E(x) E(x)
接收端通过计算T(x) mod G(x)=0
来判断是否出现的差错(=0则表示没出错,≠0表示出错)
因为是单比特出错,所以:
E ( x ) = x i E(x)=x^i E(x)=xi
那么接收到的错误数据是:
T ′ ( x ) = T ( x ) + E ( x ) T'(x)=T(x)+E(x) T′(x)=T(x)+E(x)
通过T'(x) mod G(x)
得到如下:
( T ( x ) + E ( x ) ) m o d G ( x ) (T(x)+E(x)) mod G(x) (T(x)+E(x))modG(x)
因为T(x)
必然整除G(x)
,所以只需要判断E(x) mod G(x)
是否=0,即可判断能否检测出单比特错误(=0则表示检测不出来,≠0表示能检测出来)。即只要x^i
不被G(x)
整除,CRC就能检测出这个错误:
如果
x^i
能被G(x)
整除,则意味着存在某个多项式Q(x)
使得:x^i=G(x)⋅Q(x)
但这在 有限域 F2[x] 上是不可能的:
x^i
只包含一个单独的x^i
项,而G(x)
至少有两个项。- 由于
G(x)
的最低次项是 1,所以G(x)
不能整除任何单项式x^i
。
直观理解-想象一下:
x^i
表示在某个位置上的 1,而其他地方都是 0。G(x)
是一个“复杂的”多项式(至少二次)。- 如果
G(x)
整除了x^i
,那么x^i
必须包含G(x)
的全部因子,而x^i
只有一个项,显然做不到。
所以x^i mod G(x) ≠ 0
必然成立,则必然能检测出单比特错误
接收端通过计算T(x) mod G(x)=0
来判断是否出现的差错(=0则表示没出错,≠0表示出错)
因为是双比特出错,所以:
E ( x ) = x i + x j E(x)=x^i+x^j E(x)=xi+xj
那么接收到的错误数据是:
T ′ ( x ) = T ( x ) + E ( x ) T'(x)=T(x)+E(x) T′(x)=T(x)+E(x)
接收端进行 CRC 计算:
( T ( x ) + E ( x ) ) m o d G ( x ) (T(x)+E(x)) mod G(x) (T(x)+E(x))modG(x)
同前,若**E(x)
不是G(x)
的倍数,即G(x)
不能够整除x^i + x^j
**,CRC 便能检测到错误。
为了确保 CRC 能够检测到尽可能多的双比特错误,通常选择不可约多项式,并且至少包含 3 个或更多项。
(1) 为什么选不可约多项式?
- 不可约多项式类似于素数,它不能被低阶因子分解,因此更难整除单独的错误模式
x^i + x^j
。- 如果
G(x)
可分解,例如G(x)=(x^a+1)(x^b+1)
,那么它可能会整除特定的x^i + x^j
,导致 CRC 漏检某些错误。(2) 为什么要求
G(x)
至少有 3 个或更多项?
- 设想
G(x)
只有 2 项,比如x^n + 1
,那么:x^i + x^j = x^j (x^(i-j) + 1)
可能会被G(x)
整除,从而导致 CRC 无法检测到部分双比特错误。- 但如果
G(x)
至少有 3 项,比如x^n + x^m + 1
,它就更难整除这样的结构,从而提高错误检测能力。
首先需要明确一点,标准 CRC(如 CRC-16、CRC-32)几乎总能检测所有双比特错误。所以使用的时候完全不用担心检测失效的问题。
如果攻击者特意选择一个G(x)
使其能整除某些x^i + x^j
,那么这些特定的错误模式将无法被检测到。但在实际使用中,标准的 CRC 生成多项式已经过广泛验证,确保它们能检测几乎所有双比特错误,因此无需过度担心这一问题。
CRC 的检测能力与其阶数r相关,通常能够检测间距小于1-2^(r−1)
的双比特错误(这一点将在后续讨论)。
在进一步探讨多比特错误检测前,我们先理解一个突发错误的概念:
突发错误(Burst Error)是指数据传输过程中,连续的多个比特发生错误,而不是单个或分散的比特错误。例如,在某些情况下,一个数据块的某部分可能会因噪声、干扰或硬件故障导致多个比特翻转。(多个比特连续发生错误才是使用中最常发生的情况,,此处不对其产生的原因进行进一步的讨论)
对于许多编码以及发送的数据,都少不了针对减少突发错误的产生,进行了调整,如:
接收端通过计算T(x) mod G(x)=0
来判断是否出现的差错(=0则表示没出错,≠0表示出错)
如果多个比特翻转,则错误模式可以表示为:
E ( x ) = x i + x j + x k . . . E(x)=x^i+x^j+x^k... E(x)=xi+xj+xk...
只要E(x)
不能被G(x)
整除,CRC 就能检测到该错误。
CRC 生成多项式一般设计成能检测 长度 ≤ r 的所有突发错误(r 是生成多项式的阶数)。
例如:
如果突发错误长度大于 r,则 CRC 仍然有很高的概率检测到,错误检测失败的概率约为:1 - 2^(-r)
在这种情况下,突发错误的长度大于生成多项式的阶数,CRC虽然会有一定的检测失败,但整体还是能够高效地检测到这种错误。
假设突发错误错误模式如下: E ( x ) = m 0 x p + m 1 x p − 1 + . . . + n x q 假设生成多项式的阶数为 r : G ( x ) = x r + . . . + 1 l = p − q + 1 > r 假设突发错误错误模式如下:\\E(x)=m_{0}x^p+m_{1}x^{p-1}+...+nx^q \\假设生成多项式的阶数为r:\\G(x)=x^r+...+1\\l=p-q+1>r 假设突发错误错误模式如下:E(x)=m0xp+m1xp−1+...+nxq假设生成多项式的阶数为r:G(x)=xr+...+1l=p−q+1>r
其中p > q是错误位的位置范围,长度是
l=p−q+1
生成多项式的阶数为r,表示它的最高次幂是
x^r
,因此它是一个r+1
次的多项式。
错误率的计算公式如下:
P e r r o r = E ( x ) 中可以被 G ( x ) 整除的多项式 E ( x ) 的所有多项式 P_{error}=\frac{E(x)中可以被G(x)整除的多项式}{E(x)的所有多项式} Perror=E(x)的所有多项式E(x)中可以被G(x)整除的多项式
对于一个l
位的突发错误模式,只有大约2^(l−r)
个错误模式可以被G(x)
完全整除(分子是2^(l−r)
,分母是2^l
)。因此,误检率可以近似为:
P e r r o r = 2 − r P_{error}=2^{-r} Perror=2−r
P≈2^(−16)
P≈2^(−32)
所以可见的,对于已经成熟的CRC生成多项式,我们完全不需要担心它的检测错误概率
在这种情况下,突发错误的长度小于生成多项式的阶数,CRC能够高效地检测到这种错误。
E ( x ) = m 0 x p + m 1 x p − 1 + . . . + n x q G ( x ) = x r + . . . + 1 l = p − q + 1 ≤ r E(x)=m_{0}x^p+m_{1}x^{p-1}+...+nx^q\\ G(x)=x^r+...+1\\ l=p-q+1\leq r E(x)=m0xp+m1xp−1+...+nxqG(x)=xr+...+1l=p−q+1≤r
因为生成多项式的阶数足够大,能涵盖长度为 l 的错误模式,所以 误检的概率为零。
总结:
2^(−r)
,因为生成多项式可能无法检测到某些特定的长错误模式,这些模式可能与生成多项式存在整除关系。对于产生比特错误,通常有如下两种情况:
例如,某些恶意的 比特翻转 或 特定模式(例如连续的零或一)如果恰好符合生成多项式的某种结构,就可能绕过 CRC 校验。这个情况在特定的攻击下有可能发生,尤其是如果攻击者了解 CRC 的实现方式和多项式结构。
所以在面对人为干扰时,除了使用 CRC 外,还可能需要 更复杂的安全机制(如加密、哈希校验、签名等)来防止攻击者篡改数据并绕过错误检测机制