要產生 CRC32,請將輸入位元組透過 CRC-32/ISO-HDLC 演算法處理,使用反轉多項式 0xEDB88320、初始暫存器 0xFFFFFFFF、反轉位元組處理,以及最終 XOR 值 0xFFFFFFFF,然後將產生的 32 位元暫存器格式化為八個小寫十六進位數字。該公式是 gzip、ZIP、PNG、Ethernet 以及許多其他儲存和傳輸格式所使用的公式,也是 CRC32 計算機 所產生的變體。32 位元暫存器被視為無符號值,結果在左側補零直到填滿八個字元,標準參考檢查是 "123456789" 的九個 ASCII 位元組會產生八位數值 cbf43926。如果您的目標格式列出任何其他多項式、初始值、反轉設定或最終 XOR,那麼您面對的是不同的 32 位元 CRC 變體和不同的工具。

一般而言,CRC32 是一種快速的、以查表驅動的總和檢查碼,設計用來捕捉位元組序列的意外損壞。它不是加密,不是加密雜湊函數,也不是簽章。在產生之前了解這個區別很重要:CRC32 確認您輸入的位元組與發送者預期的位元組相符,但無法證明是誰送出的。本文接下來會說明應選擇哪個變體、使用哪種輸入模式,以及如何讀取和複製八位數結果,而不會漏掉前置零或比較錯誤的位元組範圍。

how to generate crc32
how to generate crc32

在產生之前選擇正確的 CRC-32 變體

在一般對話中,「CRC32」一詞幾乎都指 CRC-32/ISO-HDLC,也稱為 CRC-32/ISO 3309,或簡稱 gzip 總和檢查碼。還有其他幾種 32 位元 CRC 公式經常使用,它們無法互換,這是產生值與預期值不符最常見的原因。在懷疑其他錯誤之前,選擇錯誤的變體是第一個必須排除的失敗模式。

常見的 32 位元 CRC 變體 出現位置 與 CRC-32/ISO-HDLC 相同嗎?
CRC-32/ISO-HDLC(也稱為 CRC-32) gzip、ZIP、PNG、Ethernet、SSH、ITU-T V.42 是 — 這是計算機所實作的版本
CRC-32C(Castagnoli) iSCSI、SCTP、ext4、BTRFS、FCoE 否 — 多項式不同
CRC-32/MPEG-2 MPEG-2 傳輸串流、H.264 否 — 多項式相同,但無反轉、無最終 XOR
CRC-32/BZIP2 bzip2 封存格式 否 — 多項式相同,但無反轉
CRC-32/JAMCRC 建置系統雜湊、某些遊戲檔案 否 — 多項式相同,但無最終 XOR
CRC-32/Koopman DVB、某些電信格式 否 — 多項式不同

當您依循的規格僅標示 CRC-32 而無後綴、標示為 CRC-32/ISO-HDLC,或列出 "123456789" 九個 ASCII 位元組的 gzip 檢查值 cbf43926,那麼您來對地方了。當規格標示為 CRC-32C、Castagnoli、Koopman、MPEG-2、BZIP2 或 JAMCRC 時,本計算機的結果將無法相符,您需要不同的工具。第二個快速檢查是格式本身:若您正在驗證 PNG 檔案或 gzip 成員,您需要的是 ISO-HDLC;若您正在驗證 ext4 磁碟結構,您需要的是 Castagnoli。

如何從文字或十六進位位元組產生 CRC32

開啟 CRC32 計算機,選擇符合您酬載的輸入模式,貼上或輸入位元組,進行計算,然後將完整的八位數結果與您的預期值比較。介面刻意精簡,使每個步驟只有單一決策。以下程序涵蓋一般情況;後續章節會說明造成大多數不符的邊緣情況。

  1. 確認所需的 CRC 變體以及要涵蓋的確切位元組範圍。對 ISO-HDLC 而言,"123456789" 的 ASCII 位元組標準檢查值為 cbf43926;若您的預期參考值為其他值,則您要求的不是同一個變體,結果將無法相符。
  2. 根據規格描述,在 UTF-8 文字模式與十六進位位元組模式之間選擇:當酬載確實是將以 UTF-8 編碼的文字字串時選擇文字模式,當規格指定確切位元組或您擁有來自檔案或封包擷取的原始位元組序列時選擇十六進位模式。
  3. 完全依照應進行總和檢查的方式輸入酬載。在文字模式中,請使用確切的字元以及目標所使用的任何行尾字元輸入字串。在十六進位模式中,貼上成對的十六進位數字,位元組對之間可有可無的空白字元;工具會去除內部空白,並將每對視為一個位元組。
  4. 進行計算。瀏覽器會從反轉多項式 0xEDB88320 建立一個 256 項的查表,將暫存器初始化為 0xFFFFFFFF,從最低有效位元開始處理每個位元組,最後將暫存器與 0xFFFFFFFF 進行 XOR,並將無符號 32 位元結果格式化為八個小寫十六進位數字。
  5. 比對全部八個數字與您的預期值,包括前置零。使用複製控制項以複製恰好顯示的八個字元;複製動作不會加上前綴、分隔符或周圍空白字元。
  6. 判斷相符是否足夠。相符的 CRC32 可證明位元組未意外變更;它並非安全性證明。若涉及惡意修改的疑慮,請改用加密摘要與經認證的散布管道。

選擇正確的輸入模式:文字與十六進位

兩種輸入模式看起來可以互換,但對同一字串而言,幾乎永遠不會產生相同的值。原因在於位元組編碼。在文字模式下,計算機會先將您的字串以 UTF-8 編碼後再送入 CRC 演算法。ASCII 字元各佔一個位元組,而帶腔調的拉丁字母、多數 CJK 字元以及表情符號則每個可見字元佔用多個位元組。同樣的邏輯字串在 Windows 機器上以「歸位字元加換行字元」結尾輸入,再貼到將行尾正規化為僅有換行字元的工具中時,將產生與原始字串不同的 CRC。

問題 UTF-8 文字模式 十六進位位元組模式
您輸入或貼上的內容 可讀字串 成對的十六進位數字,可含空白
對輸入套用的編碼 UTF-8(ASCII 字元每個 1 位元組,腔調字元和表情符號更多) 無 — 數字會被解讀為原始位元組
最適用情境 目標格式將酬載描述為文字 目標格式指定確切位元組或您擁有原始位元組
最常見的錯誤 跨工具比較而工具對行尾字元定義不同 加入了 0x 前綴、殘留分隔符或奇數個數字
前置零位元組 無法表示 — 它們沒有可列印的形式 必須以「00」對輸入,並會影響結果

若某個協定、檔案格式或文件提供了字面意義上的位元組序列,請以十六進位貼上而非重新輸入為可見文字。十六進位模式會去除位元組對之間的空白,且其他情況下要求偶數個十六進位數字;前綴(例如 0x)、非空白的分隔符、註解以及奇數個尾端半位元組都會被拒絕,以使錯誤是顯而易見而非悄然發生。請確認 CRC 所涵蓋的位元組範圍是否包含任何標頭、長度欄位、分隔符或儲存的總和檢查碼欄位,因為新增或移除其中任何一項都會改變該值。

讀取、比較和複製八位數結果

輸出永遠恰好是八個小寫十六進位數字,當高位元為零時會以前置零補齊。這個統一寬度很重要:CRC 值 0x0A1B2C3D 會顯示並複製為 0a1b2c3d,而非 a1b2c3d 或 A1B2C3D,且前置零會被保留。當您與預期值比較時,請檢視全部八個位置。常見的失敗模式是工具傳回十進位整數、縮寫的十六進位字串,或位元組順序相反的 32 位元值;即使底層計算正確,這些情況看起來都會是錯誤的。

計算機上的複製動作僅複製顯示的八個數字。它不會加上「0x」前綴、冒號、空格、換行字元或尾端的總和檢查碼欄位。若您的下游工具需要這些內容,請在複製後自行加上。結果全程視為無符號,因此 0x7FFFFFFF 以上的值不會進行符號延伸,而值 00000000 保留給真正的空輸入;介面會要求輸入資料,使意外的空白點擊不會看起來像是有意義的驗證。

限制、輸入大小及工具不做的事

輸入上限為 5,000,000 位元組,以使查表驅動的處理在瀏覽器中保持回應速度。對於更大的酬載,請先使用串流工具對檔案進行雜湊,或將輸入分割;無論輸入長度為何,八位數輸出的格式完全相同。結果絕不會被靜默截斷:若計算成功,您會得到恰好八個十六進位數字;若輸入被拒絕,計算機會回報原因,而非產生看起來錯誤的值。

八組外部檢查字串涵蓋空輸入情況、短訊息、常見的訊息摘要與字母套組、「123456789」的標準數值檢查,以及「quick-brown-fox」句子。多位元組 UTF-8 邊界使用 Python zlib 進行交叉檢查。這些參考值證明了所宣告的變體和位元組處理是正確的,而不僅僅是顯示某個編碼器與其自身的解碼器一致——那種自我一致性無法捕捉任何真正的錯誤。若您希望逐步理解演算法而非僅僅取得答案,如何逐步計算 CRC 總和檢查碼 中的逐步說明展示了以手動方式將相同的反轉多項式方法套用於一個短字串的過程。

當 CRC32 不足以用於安全性時

相符的 CRC32 告訴您所擁有的位元組就是進行總和檢查的位元組,這足以捕捉磁碟上、傳輸線上或部分下載檔案中的意外損壞。但這不足以捕捉惡意修改。CRC32 是線性的且易於操控:想要讓特定檔案產生選定 CRC32 值的攻擊者,無需知道原始檔案即可產生出該檔案。相同的特性也意味著 CRC32 無法用作訊息驗證碼、數位簽章,也無法證明下載來自受信任的發布者。

請勿使用 CRC32 來驗證不受信任的軟體、授權命令、保護憑證,或證明檔案來自受信任來源。對於這些任務,請使用 SHA-256 等加密摘要,並透過經認證的管道確認該摘要。若需要在訊息層級進行經認證的完整性保護,請使用 HMAC-SHA-256 或等效的經認證加密機制。CRC32 計算機對於意外錯誤的一致性會給出正確答案;更廣泛的安全性主張則須由您使用更強的基元與可信的比較路徑自行建立。

相關閱讀:Gzcompress 線上批次壓縮 UTF-8 文字