返回筆記列表

2026/06/08

資料完整性與錯誤檢查基礎概念

本文介紹程式、通訊協定與嵌入式系統中常見的資料完整性檢查方法,包含 Parity、Checksum、LRC、CRC8、CRC16、CRC32、PEC、MD5、SHA-256、HMAC 與數位簽章,並說明它們分別適合用於「錯誤偵測」或「安全驗證」。

Data IntegrityError CheckingBasics

1. 為什麼需要資料完整性檢查?

在程式與硬體通訊中,資料可能因為各種原因發生錯誤:

  • 通訊線路受到雜訊干擾。
  • UART / I2C / SPI / CAN / RS-485 傳輸時發生 bit flip。
  • Flash、EEPROM 或檔案儲存時資料損壞。
  • 封包長度、位址、資料欄位解析錯誤。
  • 韌體更新檔下載不完整。
  • 惡意攻擊者刻意竄改資料。

因此,系統通常會在資料後面附加一段檢查值,例如 checksum、CRC 或 hash,用來確認資料是否正確。


2. 錯誤偵測 vs. 安全驗證

很多人會把 CRC、Checksum、MD5、SHA、HMAC 混在一起,但它們的目的不同。

最重要的分界是:

CRC / Checksum 主要用來偵測意外錯誤;HMAC / 數位簽章才適合用來防止惡意竄改。


2.1 錯誤偵測

錯誤偵測的目標是確認資料在傳輸或儲存過程中有沒有「不小心壞掉」。

常見例子:

  • Parity
  • Checksum
  • LRC
  • CRC8
  • CRC16
  • CRC32
  • PEC

這類方法通常計算速度快、實作簡單,適合低階通訊協定與嵌入式系統。

但它們沒有祕密金鑰。只要攻擊者知道演算法,就可以修改資料後重新計算檢查值,因此不適合拿來防止惡意竄改。


2.2 安全驗證

安全驗證的目標是確認資料是否遭到惡意竄改,以及資料是否來自可信來源。

常見例子:

  • HMAC
  • 數位簽章
  • 韌體簽章驗證
  • 憑證驗證

這類方法通常會使用祕密金鑰或私鑰,因此攻擊者即使知道演算法,也很難偽造合法結果。


3. 常見方法總覽

名稱類型主要用途可防意外錯誤可防惡意竄改
Parity同位檢查偵測簡單 bit 錯誤
Checksum檢查和快速檢查資料是否損壞
LRC縱向冗餘檢查簡單封包檢查
CRC8 / CRC16 / CRC32循環冗餘檢查通訊、儲存、封包錯誤偵測
PECPacket Error CodeSMBus / PMBus 封包錯誤檢查
MD5密碼學雜湊,已不安全舊系統 fingerprint、非安全性校驗不建議
SHA-256密碼學雜湊檔案完整性、簽章前摘要視使用方式而定
HMAC金鑰式訊息驗證碼API 驗證、訊息完整性與身分驗證
數位簽章非對稱密碼學驗證韌體更新、憑證、文件簽署

4. Parity:同位檢查

Parity 是最簡單的錯誤偵測方式之一,常見於 UART 等通訊設定中。

Parity 會在資料位元後面附加一個同位檢查位元,讓整筆資料中 1 的數量符合指定規則。

常見模式:

  • Even Parity:讓 1 的總數為偶數。
  • Odd Parity:讓 1 的總數為奇數。

優點

  • 實作非常簡單。
  • 硬體支援常見。
  • 適合偵測單一 bit 錯誤。

限制

  • 無法偵測所有錯誤。
  • 若有偶數個 bit 同時錯誤,可能無法發現。
  • 不適合用於高可靠度資料保護。

5. Checksum:檢查和

Checksum 是一種把資料內容加總後得到檢查值的方法。

最簡單的做法是將所有 byte 相加,只保留低 8-bit 或 16-bit 作為 checksum。

例如:

data = [0x12, 0x34, 0x56]
sum  = 0x12 + 0x34 + 0x56 = 0x9C
checksum = 0x9C

有些協定會使用補數形式,例如:

checksum = 0x100 - (sum & 0xFF)

這樣接收端把所有資料加上 checksum 後,低 8-bit 應該會等於 0。


優點

  • 實作簡單。
  • 計算速度快。
  • 適合非常低成本的資料檢查。

限制

  • 偵錯能力較弱。
  • 不同錯誤可能抵消,導致 checksum 一樣。
  • 不適合複雜通訊或高可靠度資料檢查。
  • 不能防止惡意竄改。

6. LRC:縱向冗餘檢查

LRC (Longitudinal Redundancy Check) 是一種常見的簡單錯誤檢查方式,常見於部分序列通訊與文字型協定。

LRC 通常會對一段資料做 XOR 或加總補數計算。

例如 XOR 型 LRC:

data = [0x12, 0x34, 0x56]
LRC = 0x12 XOR 0x34 XOR 0x56

優點

  • 比單純加總稍微好一些。
  • 實作簡單。
  • 適合簡單通訊協定。

限制

  • 偵錯能力仍有限。
  • 不如 CRC 適合偵測 burst error。
  • 不具備安全性。

7. CRC:循環冗餘檢查

CRC (Cyclic Redundancy Check) 是通訊協定與儲存系統中非常常見的錯誤偵測方法。

CRC 不是單純加總,而是把資料視為二進位多項式,透過指定的生成多項式進行除法運算,最後得到餘數作為檢查值。

常見 CRC 類型:

  • CRC-8
  • CRC-16
  • CRC-32

7.1 CRC 的特點

CRC 很適合偵測:

  • 單一 bit 錯誤
  • 多 bit 錯誤
  • 連續 burst error
  • 常見通訊雜訊造成的資料損壞

因此 CRC 常用於:

  • 通訊封包
  • Flash / EEPROM 資料區塊
  • 檔案格式
  • 壓縮格式
  • 網路封包
  • Firmware image 檢查

7.2 CRC 常見參數

討論 CRC 時,不能只說「CRC16」或「CRC8」,因為不同協定可能使用不同參數。

常見參數包含:

參數說明
WidthCRC 長度,例如 8、16、32 bit
Polynomial生成多項式
Initial Value初始值
RefIn輸入資料是否 bit reflection
RefOut輸出結果是否 bit reflection
XorOut最後輸出前是否再 XOR 指定值
Input RangeCRC 計算涵蓋哪些欄位
Byte Order結果放入封包時使用 little-endian 或 big-endian

所以工程實作時,應該明確寫出完整規格,例如:

CRC-16/CCITT-FALSE
Width  = 16
Poly   = 0x1021
Init   = 0xFFFF
RefIn  = false
RefOut = false
XorOut = 0x0000

只寫「用 CRC16」通常是不夠的。


7.3 CRC8

CRC8 產生 8-bit 檢查值,常見於短封包或低成本通訊協定。

常見應用:

  • SMBus PEC
  • 一些感測器封包
  • 短距離低速通訊

優點是檢查值短、成本低;缺點是保護能力有限,不適合很長的資料區塊。


7.4 CRC16

CRC16 產生 16-bit 檢查值,常見於工業通訊、Modbus、儲存資料區塊等場景。

常見變體包含:

  • CRC-16/IBM
  • CRC-16/MODBUS
  • CRC-16/CCITT-FALSE
  • CRC-16/XMODEM

這些雖然都叫 CRC16,但 polynomial、initial value、reflection 等參數可能不同,結果也會不同。


7.5 CRC32

CRC32 產生 32-bit 檢查值,常見於檔案、壓縮格式、網路與大量資料檢查。

常見應用:

  • Ethernet FCS
  • ZIP
  • PNG
  • gzip
  • 檔案完整性校驗

CRC32 對一般意外錯誤的偵測能力比 CRC8 / CRC16 更強,但仍然不是安全驗證機制。


8. PEC:封包錯誤碼

PEC (Packet Error Code) 是 SMBus / PMBus 中常見的封包錯誤檢查碼。

PEC 通常是基於 CRC-8 計算,常見 polynomial 為:

x^8 + x^2 + x + 1

也常表示為:

0x07

PEC 的用途

PEC 用來檢查 SMBus / PMBus 封包在傳輸過程中是否發生錯誤。

常見涵蓋內容包含:

  • Slave address
  • Read / Write bit
  • Command code
  • Data bytes
  • Repeated start 後的 address
  • 其他協定定義的欄位

實際計算範圍必須依照協定規格確認。


PEC 與 CRC8 的關係

可以簡單理解為:

PEC 是特定協定中使用的一種 CRC8 檢查碼。

但寫程式時不能只知道「CRC8」,還要確認:

  • polynomial
  • initial value
  • 是否 reflection
  • 計算涵蓋哪些 byte
  • PEC byte 是否包含在計算內
  • address 與 R/W bit 是否包含在計算內

9. MD5 與 SHA:雜湊函數

雜湊函數 (Hash Function) 會把任意長度的輸入資料轉成固定長度的輸出值。

例如:

  • MD5:輸出 128-bit
  • SHA-1:輸出 160-bit
  • SHA-256:輸出 256-bit

9.1 MD5

MD5 曾經是常見的密碼學雜湊函數,但現在已經不安全,因為已知存在碰撞攻擊。

不建議用 MD5 做:

  • 密碼儲存
  • 數位簽章
  • 安全驗證
  • 憑證或韌體可信驗證

MD5 仍可能出現在舊系統或非安全用途,例如快速 fingerprint,但新系統通常應避免使用。


9.2 SHA-256

SHA-256 是目前常見且仍被廣泛使用的密碼學雜湊函數。

常見用途:

  • 檔案完整性驗證
  • 數位簽章前的訊息摘要
  • 區塊鏈
  • 安全協定中的資料摘要

但要注意:

只有 SHA-256 本身,不能證明資料來源可信。

如果攻擊者可以同時替換檔案與 SHA-256 值,那使用者仍可能被騙。因此,若要驗證來源,需要搭配 HMAC、數位簽章或可信下載通道。


10. HMAC:金鑰式訊息驗證碼

HMAC (Hash-based Message Authentication Code) 是將雜湊函數與共享祕密金鑰結合,用來驗證訊息完整性與來源。

常見形式:

HMAC-SHA256(secret_key, message)

只有知道 secret_key 的雙方,才能產生正確的 HMAC。

適合用途

  • API request 驗證
  • webhook 驗證
  • 裝置與伺服器之間的訊息驗證
  • 防止封包被不知道金鑰的人偽造

與 CRC 的差異

CRC 不需要金鑰,所以任何人都能重新計算。

HMAC 需要祕密金鑰,因此攻擊者即使知道資料內容與演算法,也無法在不知道金鑰的情況下偽造合法 HMAC。


11. 數位簽章:驗證來源與不可否認性

數位簽章 (Digital Signature) 使用非對稱密碼學。

基本概念是:

  • 使用私鑰簽署。
  • 使用公鑰驗證。

常見用途:

  • 韌體更新檔驗證
  • 軟體安裝檔驗證
  • TLS 憑證驗證
  • 文件簽署
  • 安全開機 (Secure Boot)

與 HMAC 的差異

項目HMAC數位簽章
金鑰類型雙方共享同一把 secret key私鑰簽署,公鑰驗證
驗證者能不能產生合法結果可以,因為驗證者也知道 secret key不行,驗證者只有公鑰
適合場景雙方都可信的系統內部驗證對外發布、韌體更新、不可否認性
不可否認性較弱較強

12. 韌體與嵌入式系統常見使用場景

12.1 通訊封包錯誤檢查

常見選擇:

  • UART 簡單協定:Checksum、LRC、CRC8、CRC16
  • I2C / SMBus:PEC
  • RS-485 / Modbus:CRC16
  • CAN:協定本身有 CRC 欄位

目標是偵測通訊過程中的意外錯誤。


12.2 儲存資料完整性檢查

例如設定值存在 Flash 或 EEPROM:

struct config {
    uint32_t magic;
    uint16_t version;
    uint8_t  payload[128];
    uint32_t crc32;
}

開機時重新計算 CRC32,確認設定資料是否損壞。


12.3 韌體更新檔檢查

韌體更新通常會有兩層概念:

  1. CRC / Hash:確認檔案下載或傳輸過程沒有損壞。
  2. 數位簽章:確認韌體確實來自可信來源,沒有被惡意替換。

只做 CRC 不夠安全,因為攻擊者可以改韌體後重新計算 CRC。


12.4 Bootloader 驗證

常見設計:

Bootloader

讀取 firmware image

檢查長度、版本、CRC

驗證數位簽章

驗證通過後才跳轉執行

CRC 可用於快速檢查資料是否壞掉,但是否允許執行,應以簽章驗證結果為準。


13. 選用建議

使用情境建議方法
UART 短封包簡單檢查Checksum、LRC、CRC8
Modbus RTUCRC16
SMBus / PMBusPEC
大型檔案非安全性完整性檢查CRC32、SHA-256
韌體傳輸過程檢查CRC32 或 SHA-256
韌體是否可信數位簽章
API / Webhook 驗證HMAC-SHA256
密碼儲存Argon2、bcrypt、scrypt、PBKDF2
防止惡意竄改HMAC 或數位簽章
只防通訊雜訊CRC 通常比 checksum 更適合

14. 常見誤解

誤解 1:CRC 可以防止資料被惡意修改

不行。

CRC 沒有祕密金鑰,攻擊者知道演算法後,可以修改資料並重新計算 CRC。


誤解 2:MD5 可以用來做安全驗證

不建議。

MD5 已有碰撞攻擊,不適合密碼學安全用途。


誤解 3:有 SHA-256 就一定安全

不一定。

SHA-256 可以檢查資料是否變動,但如果攻擊者能同時替換資料與 hash 值,就無法保證來源可信。

若要確認來源,應使用 HMAC 或數位簽章。


誤解 4:CRC16 都是一樣的

不是。

CRC16 有很多變體,必須確認 polynomial、initial value、reflection 與計算範圍。


誤解 5:Checksum、CRC、Hash 都是加密

不是。

它們都不是「加密」。加密的重點是讓資料變成未授權者無法讀取的密文,並且可由合法持有人解密。

Checksum、CRC、Hash 的重點是產生檢查值,不是隱藏資料內容。


15. 總結

可以用一句話區分:

Checksum / CRC / PEC 用來抓資料有沒有壞掉;HMAC / 數位簽章用來防資料被惡意偽造或竄改。

簡單判斷方式:

  • 只怕通訊雜訊或儲存損壞:使用 CRC、Checksum、PEC。
  • 需要確認資料來源可信:使用 HMAC 或數位簽章。
  • 需要隱藏資料內容:使用加密。
  • 需要儲存密碼:使用 password hashing / KDF,不要直接用 SHA-256 或 MD5。

相關概念延伸閱讀