常用算法 之五 數據校驗(CRC 原理、LRC、奇偶校驗、校驗和)詳解

數據校驗

  數據在傳輸的過程中,會受到各種干擾的影響,如脈衝干擾,隨機噪聲干擾和人爲干擾等,這會使數據產生差錯。爲了能夠控制傳輸過程的差錯,通信系統必須採用有效措施來控制差錯的產生,並保證數據的完整性。如下所示的傳輸錯誤
在這裏插入圖片描述

奇偶校驗

  奇偶校驗是檢測錯誤的最古老的方法。用於檢查數據傳輸的完整性。校驗方法非常簡單,只需要在數據上添加一個額外的位, 這個額外的位稱爲奇偶校驗位。 該位簡單地表示原數據中 1 的數量是奇數還是偶數。基本算法如下:
在這裏插入圖片描述
通常,如果 1 的數量是奇數,則奇偶校驗位是 1,如果 1 的數量是偶數,則奇偶校驗位是 0。下面是一個通信流程圖
在這裏插入圖片描述
  雖然奇偶校驗足以保護單個字符或字節,但當應用於較大的消息時,其檢測能力不足:消息通常跨越數千位,如果僅翻轉兩位,就無法檢測到損壞。消息中出現多位錯誤的機率隨着消息長度呈指數級增加。

  1. 當一個字符中有 1 個位不正確時(如上面的 Single-bit error),它可以檢測錯誤,但是當字符中有 2 個錯誤時,它認爲沒有發生錯誤。
  2. 奇偶校驗會消耗大量開銷(通常每 8 個位就添加一個校驗位),因此它會減慢傳輸速度。

LRC

  縱向冗餘校驗(Longitudinal Redundancy Check,LRC)是一個逐字節奇偶校驗計算,將數據字的所有字節一起異或,創建一個字節的結果,也稱爲 XOR 校驗和。
在這裏插入圖片描述
縱向冗餘校驗就是對奇偶校驗的擴展形式。其只能檢測縱向奇數個錯誤。
在這裏插入圖片描述

校驗和

  校驗和(checksum)是指傳輸位數的“累加”(加法操作可能不是普通整數加法)。奇偶校驗和 LRC 可以說是校驗和的一種形式(嚴格意義上來說,他們是異或,而不是和)。將奇偶校驗的思想擴展,將消息中的字節彙總成一個校驗字節(而不是奇偶校驗的比特位),這個字節就是校驗和。
在這裏插入圖片描述
需要注意,校驗和算法有很多種(“累加”的方式不同)。

Integer Addition Checksum(整數加法校驗和)

在這裏插入圖片描述

  1. 最高位的進位被省略
  2. 可以檢測使兩個位變爲 0 -> 1或 1 -> 0 的錯誤(除了高的位)
  3. 無法檢測補償錯誤(一個位變爲0 ->1,另一個位變爲1 -> 0)

One’s complement “checksum”

與整數校驗和相同,但是要將進位加回去。
在這裏插入圖片描述

Fletcher Checksum

Use two running one’s complement checksums

  • For fair comparison, each running sum is half width
    • E.g., 16-bit Fletcher Checksum is two 8-bit running sums
    • Initialize: A = 0; B = 0;
    • For each byte in data word: A = A + Bytei; B = B + A;
      • One’s complement addition!
    • Result is A concatenated with B (16-bit result)
  • Significant improvement comes from the running sum B
    • B = ByteN-1 + 2ByteN-2 + 3ByteN-3 + …
    • Makes checksum order-dependent (switched byte order detected)
      • Gives HD=3 until the B value rolls over
  • For example, 256*ByteN-256 does not affect B

Adler Checksum

旨在改進 Fletcher Checksum。Adler校驗和使用素數作爲模數

  • 251 instead of 255 for Adler 16 (two 8-bit sums)
  • 65521 instead of 65535 for Adler 32 (two 16-bit sums)

ATN Checksum (AN/466)

Algorithm:

  • Initialize C0, C1, C2 and C3 to zero
  • For each Data Word byte: C0 += Bytei; C1 += C0; C2 += C1; C3 += C2; (one’s complement addition, as with Fletcher checksum)
  • 32-bit check sequence is a particular formula of C0…C3

CRC

  循環冗餘校驗(Cyclic Redundancy Codes,CRC)試圖通過增加算法的複雜性來改進校驗和。與校驗和一樣,CRC 用於檢查大塊數據,而不是奇偶校驗中使用的單字符檢查。CRC在錯誤檢查方面比使用校驗和要有效得多。
  循環冗餘校驗(Cyclic Redundancy Check,CRC)是數據通訊中很常用的一種校驗方式。尤其是在嵌入式開發中,經常要用到 CRC 算法對各種數據進行校驗。通常用法爲在傳輸或者儲存之前計算出來的數字(稱爲校驗碼)附加到原數據後面,然後接收方進行檢驗確定數據是否發生變化。
  CRC 是數據流採用二進制除法(沒有進位,使用 xor 來代替減法)相除所得到的餘數,這個餘數通常被稱爲 CRC校驗碼,簡稱 CRC 碼 。其中被除數是需要計算校驗和的信息數據流;除數是一個長度爲 n+1 的預定義的二進制數(用多項式的係數來表示)。在做除法之前,要在信息數據之後先加上 n 個 0。當 CRC 的校驗值爲 n 位長時,CRC 稱爲 n 位CRC,通常寫爲 CRC-n
  CRC 由 W. Wesley Peterson 於 1961 年發明。CRC 經常被叫做“校驗和”,但是這樣的說法嚴格來說並不是準確的,因爲技術上來說,校驗“和”是通過加法來計算的,而不是 CRC 這裏的除法。

模 2 除法

  CRC 算法中使用的除法爲模 2 除法。模 2 除法與算術除法類似,但每一位除的結果不影響其它位,即不向上一位借位,所以實際上就是異或運算。模 2 除法:
假設被除數 X,除數 P,餘數 R

  1. 被除數 X 除以 P,被除數首位爲 1 時,商1;爲 0 時,商 0 。這裏與普通的算術除法不同!
  2. 所得餘數去除首位(左移一位):
    • R 第一位爲 0,將其作爲新的被除數,除以 0,此時其首位爲 0,商即爲 0
    • R 第一位爲 1,將其作爲新的被除數,除以 P,此時其首位爲 1,商即爲 1
  3. 重複第 2 步直到 R 位數少於 P 位數

關於模 2 除法,有篇博文寫的挺好:《 模2除法(CRC校驗碼計算) 》。有興趣的可以去看看!

原理

  CRC 基於循環糾錯碼理論,是基於伽羅華域(Galois Field) GF(2)(即除以 2 的同餘)的多項式環。簡單的來說,就是所有係數都爲 0 或 1 的多項式係數的集合,並且集合對於所有的代數操作都是封閉的。
  在代數編碼理論中,將一個碼組表示爲一個多項式,碼組中各碼元當作多項式的係數。任意一個由二進制位串組成的代碼都可以和一個係數僅爲 ‘0’ 和 ‘1’ 取值的多項式一一對應。例如:代碼 1010111 對應的多項式爲 1 * x6 + 0 * x5 + 1 * x4 + 0 * x3 + 1 * x2 + 1 * x1 + 1 * x0,即: x6 + x4 + x2 + x + 1。而多項式爲 x5 + x3 + x2 + x + 1 對應的代碼 101111。

  • G(x): 表示 CRC 的生成多項式,是接收方和發送方的一個約定,也就是一個二進制數,由 CRC 規範給定。在整個傳輸過程中,這個數始終保持不變。例如 CRC-16-CCITT 的生成多項式爲 G(x) = x16 + x12 + x5 + 1。生成多項式應滿足以下條件:
    • ***生成多項式的最高位和最低位必須爲 1(因此,大多數生成多項式的簡記式中將生成多項式的最高位省略)***。
    • 當被傳送信息(CRC碼)任何一位發生錯誤時,被生成多項式做除後應該使餘數不爲 0。
    • 不同位發生錯誤時,應該使餘數不同。
    • 對餘數繼續做除,應使餘數循環。
  • C(x): 表示 發送的原始數據的多項式。例如 C(x) = x5 + x3 + x2 + x + 1 表示 發送的數據爲 101111。
  • R(x): 表示 CRC 碼的多項式。R(x) = C(x) * (x << R) % G(x)
  • T(x): 表示 發送的原始數據加上 CRC 碼之後的多項式。T(x) = C(x) * (x << R) + R(x)
  • K: 發送數據的長度。其等於 C(x) 中的最高次的冪 + 1。如上例子的 C(x) 中,K = 5 + 1 = 6
  • R: CRC 碼 的長度。CRC校驗碼位數 = 生成多項式位數 - 1。注意:最高位被省略了!!!。例如上例子的 G(x) 中,R = 16。

  在 K 位信息碼後再拼接 R 位的校驗碼,整個編碼長度爲 N 位。因此,這種編碼也叫 ( N,K ) 碼。對於一個給定的 ( N,K ) 碼,可以證明存在一個最高次冪爲 N - K = R 的多項式 G(x)。根據 G(x) 可以生成 K 位信息的校驗碼,而 G(x) 叫做這個 CRC 碼的生成多項式。基本就是下面這個樣子:
在這裏插入圖片描述
  校驗碼的具體生成過程爲:假設要發送的信息用多項式 C(x) 表示,將 C(x) 左移 R 位(可表示成 C(x) * 2R),這樣 C(x) 的右邊就會空出 R 位,這就是校驗碼的位置。用 C(x) * 2R 除以生成多項式 G(x) 得到的餘數就是校驗碼。
  下面來個例子,假設需要發送的信息 C(x) 爲 1010001101,產生多項式 G(x) 對應的代碼爲 110101,R=5。C(x) 左移 5 位後補 0,然後對移位後的數做模 2 除法運算,得餘數 R(x) 對應的代碼:01110。
在這裏插入圖片描述
故實際需要發送的數據是101000110101110。需要注意的是,餘數(R(x))不足 R 位時,高位補 0!

(1)Évariste Galois ,伽羅華(也譯作伽瓦羅),法國數學家,羣論的創立者。
(2)元素個數爲 p 的有限域一般記爲 GF( p )
(3)編碼理論: 研究信息傳輸過程中信號編碼規律的數學理論。編碼理論與信息論、數理統計、概率論、隨機過程、線性代數、近世代數、數論、有限幾何和組合分析等學科有密切關係,已成爲應用數學的一個分支。編碼是指爲了達到某種目的而對信號進行的一種變換。其逆變換稱爲譯碼或解碼。—— 陳魯生,沈世鎰 編.編碼理論基礎 :高等教育出版社,2010-07-31

生成多項式

CRC 算法原理很簡單,但是在實際使用中要面臨很多問題:

  • 位順序: 某些方案將每個字節的低位視爲“第一”位,這與我們對“低階”的習慣理解相反。當串行端口傳輸在硬件中進行 CRC 校驗時,這種約定是有意義的,因爲一些廣泛的串行端口傳輸約定首先傳輸字節最低有效位。CRC算法不只有軟件實現,還有硬件實現!例如,在英特爾處理器的Nehalem微體系結構中引入了CRC-32的實現。
  • 字節順序: 對於多字節 CRC,可能會混淆首先發送的字節(或存儲在最低尋址的存儲器字節中)是最低有效字節(LSB)還是最高有效字節(MSB)。例如,一些 16 位 CRC 方案交換校驗值的字節。
  • 高階位的遺漏除數多項式的: 由於高序位始終爲 1,並且由於一個 Ñ 位 CRC 必須由(被定義 Ñ + 1)位其中除數溢出的 Ñ 位寄存器,大多數 CRC 認爲沒有必要提到除數的高位,因此給出的 CRC 多項式通常省略高位的 1
  • 省略除數多項式的低階位: 由於低階位始終爲 1,因此像 Philip Koopman 這樣的多項式,其高位完整,但沒有低位(x 0 或 1)。
  • 某些專有協議中的 CRC 可能會通過使用特定的值和 CRC 結果進行 XOR 處理

因此,在 CRC 標準中,有許多種 CRC 算法!
  CRC 的規範要求定義所謂的生成多項式。該多項式成爲多項式長除數中的除數,該除數將消息作爲被除數,並且其中商被丟棄而餘數成爲結果。多項式係數是根據有限域的算法計算的,因此加法運算總是可以按位並行執行(數字之間沒有進位)。實際上,所有常用的 CRC 都使用兩個元素的伽羅瓦域 GF(2)。這兩個元素通常稱爲 0 和 1,非常適合計算機體系結構。
  當 CRC 的校驗值爲 n 位長時,CRC 稱爲 n 位CRC,通常寫爲 CRC-n 。對於給定的 n,也可能有多種 CRC ,因爲每個 CRC 具有不同的多項式。這樣的多項式具有最高階數 n,這意味着它具有 n + 1 項。換句話說,多項式的長度爲 n + 1 ; 其編碼需要 n + 1位。下面給出了常用的 CRC 生成多項式:
在這裏插入圖片描述
下面是上表中一些字段的含義:

  • 初始值: 這是算法開始時的初始化預置值
  • 輸入值反轉: 待測數據的每個字節是否按位反轉。 默認:高位在前,低位在後;反轉後:低位在前,高位在後!
  • 輸出值反轉: 在計算後之後,異或輸出之前,整個數據是否按位反轉。
  • 結果異或值: 計算結果與此參數異或,異或後得到值當做最終的 CRC 值。

  大多數多項式規範要麼省略 MSB,要麼省略 LSB,因爲它們始終爲 1。最簡單的錯誤檢測系統,即奇偶校驗位,實際上是 1 位 CRC:它使用生成多項式爲 x + 1,並且名稱爲 CRC-1

安全性

  CRC 的錯誤檢測能力依賴於關鍵多項式的階次以及所使用的特定關鍵多項式。儘管在錯誤檢測中非常有用,CRC 並不能可靠地驗證數據完整性(即數據沒有發生任何變化),這是因爲 CRC 多項式是線性結構,可以非常容易地故意改變數據而維持 CRC 不變。
  與所有其它的散列函數一樣,在一定次數的碰撞測試之後 CRC 也會接近100%出現碰撞。CRC 中每增加一個數據位,碰撞機率就會減少接近50%。例如 CRC-20 與 CRC-21相比。

  • 理論上來講,CRC64 的碰撞概率大約是每 18×10 18 個 CRC 碼出現一次。
  • 由於 CRC 的不分解多項式特性,所以經過合理設計的較少位數的 CRC 可能會與使用較多數據位但是設計很差的 CRC 的效率相媲美。在這種情況下 CRC-32 幾乎同 CRC-40 一樣優秀。
      CRC-16 可以檢測99.998%的錯誤,因此它可以檢測任何4KBytes及以下數據塊中的每個錯誤。 CRC-32 可以檢測99.999999977%的所有錯誤,並用於較大的文件。

程序實現

暫時先引用一下 https://segmentfault.com/a/1190000018094567

參考

  1. Tutorial:Checksum and CRC Data Integrity Techniques for Aviation
  2. https://blog.csdn.net/qq_35118894/article/details/73548329
  3. https://en.wikipedia.org/wiki/Cyclic_redundancy_check
  4. https://baike.baidu.com/item/CRC校驗/3439037?fr=aladdin
  5. https://segmentfault.com/a/1190000018094567
  6. https://blog.csdn.net/u012923751/article/details/80352325
  7. https://blog.csdn.net/wangweitingaabbcc/article/details/6768613
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章