CRC32 是根據一連串位元組,使用固定的 多項式 和一組簡單的簿記規則所計算出來的 32 位元循環冗餘校驗值,而實務上「找出」CRC32 指的是產生該格式或通訊協定所預期的相同八位數小寫十六進位數值。gzip、ZIP、PNG 以及許多其他消費性檔案格式所採用的標準 CRC-32/ISO-HDLC 變體,對「123456789」這個 ASCII 位元組序列會回傳 cbf43926;如果你的結果與這個測試值不符,那麼你所使用的根本就不是同一個變體。由於此演算法是在位元組層級定義的,因此結果也取決於你實際輸入的位元組序列:文字的編碼方式、行尾符號的慣例,以及涵蓋範圍內是否包含任何標頭、長度欄位或儲存的校驗碼,都會改變輸出結果。本站的 CRC32 計算機 採用 CRC-32/ISO-HDLC 變體,反向 多項式 為 0xEDB88320,初始與最終 XOR 為 0xFFFFFFFF,標準檢查值為 cbf43926,這也是你在幾乎所有常見消費性檔案格式中會用到的變體。

為什麼「CRC32」並非單一公式
CRC32 所指的是一種 32 位元校驗碼,由一個確定性的演算法產生:該演算法會逐一走訪訊息的每個位元組,使用 多項式 將每個位元組混入一個固定寬度的暫存器,最後再將暫存器與一個常數進行 XOR 運算。最終結果為八個十六進位數字。它運算快速、資源需求低,並且非常適合用來偵測因雜訊通道、部分下載或磁碟區塊損壞所導致的意外資料損毀,這也是為什麼 ZIP、PNG、gzip 等檔案格式都會包含 CRC32 欄位。
問題在於,「CRC32」並不是單一公式。同一個名稱涵蓋了數十種變體,這些變體擁有不同的 多項式、不同的暫存器初始值、不同的位元反映旗標,以及不同的最終 XOR 值。gzip、ZIP 和 PNG 所使用的變體為 CRC-32/ISO-HDLC:寬度 32 位元,反向 多項式 為 0xEDB88320,初始值為 0xFFFFFFFF,輸入經過位元反映,最終 XOR 為 0xFFFFFFFF。而 iSCSI、SCTP 以及現代 CPU 所實作的 CRC32C 指令所使用的則是 Castagnoli 變體,其 多項式 與檢查值都不同。有些系統則採用 MPEG-2 或 BZIP2 變體,它們在位元反映或最終 XOR 上有所差異。如果你使用錯誤的變體來尋找 CRC32,即使計算機本身是正確的,所得到的答案仍然與你想檢查的檔案不符。
因此,第一步並不是計算,而是先確認該規格、檔案格式或程式所預期的是哪一種變體,然後確保你所輸入的位元組序列與該規格所涵蓋的位元組序列完全一致。
先確認變體與位元組範圍,再開始計算
在你能找到與參考值吻合的 CRC32 之前,有兩件事必須對應:變體與涵蓋的位元組範圍。
關於變體,請查閱發布預期值的該檔案格式說明文件。PNG、gzip 和 ZIP 所產生的是 CRC-32/ISO-HDLC 值,反向 多項式 為 0xEDB88320,對「123456789」的 ASCII 位元組而言,標準檢查值為 cbf43926。Btrfs、iSCSI 和 SCTP 則使用 CRC-32C(Castagnoli)。本站的 CRC32 計算機僅實作 CRC-32/ISO-HDLC;如果「123456789」的預期檢查值不是 cbf43926,你就需要使用其他工具。
關於位元組範圍,請明確確認校驗碼是針對哪些位元組進行計算。某些格式僅涵蓋原始酬載資料;其他格式則可能包含標頭、長度欄位、分隔符號或儲存的校驗碼欄位。即使使用了正確的變體,多涵蓋了額外的位元組或漏掉了必要的位元組,都會在不知不覺中產生與規格不符的數值。
下表列出幾種廣泛使用的 CRC-32 變體及其區分依據的參數。在計算之前,請先透過此表確認你的規格所要求的是哪一種變體。
| 變體 | 多項式 | 初始值 | 輸出 XOR | 「123456789」的檢查值 |
|---|---|---|---|---|
| CRC-32/ISO-HDLC(gzip、ZIP、PNG) | 0xEDB88320 | 0xFFFFFFFF | 0xFFFFFFFF | 0xCBF43926 |
| CRC-32C(Castagnoli,iSCSI、SCTP) | 0x82F63B78 | 0xFFFFFFFF | 0xFFFFFFFF | 0xE3069283 |
| CRC-32/MPEG-2 | 0x04C11DB7 | 0xFFFFFFFF | 0x00000000 | 0x0376E6E7 |
| CRC-32/BZIP2 | 0x04C11DB7 | 0xFFFFFFFF | 0xFFFFFFFF | 0x0FC89198 |
| CRC-32/JAMCRC | 0x04C11DB7 | 0xFFFFFFFF | 0x00000000 | 0x340BC6D9 |
本 CRC32 計算機僅實作第一列的變體。如果你的規格指定的是其他變體,則需要使用其他實作;由於演算法、表格與最終 XOR 都不同,單一計算機無法適用於所有變體。
輸入資料並取得八位數結果
一旦確認了變體與位元組範圍,剩下的工作就交給計算機處理。下列步驟可產生符合規格的 CRC32。
- 在瀏覽器中開啟 CRC32 計算機。整個頁面都在用戶端執行,因此輸入資料永遠不會離開你的電腦。
- 決定你的酬載是文字還是原始位元組。僅在規格將輸入定義為 UTF-8 字串時,才使用文字模式。當通訊協定提供的是明確的位元組序列、原始位元組來自檔案,或是編碼方式可能不明確時,請使用十六進位模式。
- 將酬載貼入輸入欄位。在十六進位模式下,請成對貼上數字;數字之間允許有空白,系統會自動去除。前綴(如 0x)、非空白的分隔符號、註解以及奇數長度的尾端半位元組都會被拒絕,以避免解析器必須進行猜測。
- 點擊計算。在文字模式下,工具會將文字編碼為 UTF-8;在十六進位模式下,則會將十六進位字串視為原始位元組,接著透過一個由反向 多項式 0xEDB88320、初始值 0xFFFFFFFF 與最終 XOR 0xFFFFFFFF 所建構的 256 項表格,逐位元組進行運算。此實作遵循 RFC 1952 中所描述的實務範例方法,而非依賴瀏覽器特有的數字格式。
- 讀取八位數小寫十六進位結果。頁面永遠會顯示完整的八位數字,保留前導零,並將該值視為無符號數,而不論瀏覽器如何格式化 32 位元帶正負號的數字。
- 使用複製按鈕複製結果。複製的內容僅包含精確的 32 位元值,不含任何周圍文字或格式。
整個計算過程完全在瀏覽器中以表格驅動的方式執行,並使用 Python 的 zlib 對多位元組 UTF-8 邊界進行交叉驗證。輸入上限為 5,000,000 位元組,以確保表格查詢在一般硬體上仍能保持順暢。
正確讀取輸出並進行比對
正確的 CRC32 結果永遠剛好是八個小寫十六進位數字。前導零是結果的一部分,而非可以去除的填充。值 00000000 對空酬載而言是一個有意義的校驗碼,雖然介面會要求輸入資料,以避免空白的誤點看似一次有效的驗證。
在比較兩個 CRC32 值時,唯一可靠的測試就是逐字元比對。大小寫不同、缺少前導零或額外的格式都會造成差異:「CBF43926」、「cbf43926」和「0cbf43926」是不同的字串,但代表相同的數值,而計算機僅會輸出八位小寫數字。請將它們當作文字進行比對,或將每個值轉換為整數後再進行比對。
如果你要與已發布的檢查值進行交叉驗證,CRC-32/ISO-HDLC 的標準測試輸入為「123456789」的 ASCII 位元組。預期值為 cbf43926。如果你的工具產生不同的數值,那麼一定是下列三種情況之一:你使用了不同的變體;你所輸入的位元組並非「123456789」的 ASCII 位元組;或所涵蓋的位元組範圍與規格不符。在將此不一致視為真正的軟體錯誤之前,請重新確認變體與位元組範圍。
空輸入是一項快速的健全性檢查。空位元組序列的標準 CRC-32/ISO-HDLC 值為 00000000,這是由於初始值與最終 XOR 同為 0xFFFFFFFF 所直接推得的結果。請透過 Python 的 zlib.crc32(b"") 等已知參考實作進行交叉驗證,以確認變體與位元組處理方式是否正確。你也可以使用「é」這類的 UTF-8 邊界字串或某個 CJK 字元來確認多位元組處理是否正確,這些字元會編碼成多個位元組,必須以 UTF-8 傳遞才能產生穩定的結果。
當 CRC32 不敷使用,你需要的是身分驗證
CRC32 一致只能作為兩個位元組序列在意外損毀情況下「可能」相同的證據。它並不能證明資料是可信的、來自可信任的發行者,也無法證明它未被攻擊者替換。由於 CRC32 演算法在其輸入上以及輸入長度上都具有線性特質,因此可以低成本地構造出能產生指定 CRC32 的酬載。zlib 手冊 明確區分了 CRC32 校驗碼與密碼學層級的身分驗證,並建議在涉及真實性的場合使用密碼學雜湊。
若需要對抗惡意攻擊的完整性保護,請使用例如 SHA-256 等密碼學雜湊函式,對相同的位元組序列進行運算,並透過你能驗證的管道、由你信任的發行者發布該雜湊值,接著同時對檔案本身以及預期雜湊值進行驗證。CRC32 適用於在非對抗性的環境中偵測雜訊通道造成的損毀:驗證下載的檔案是否遭截斷、傳輸的區塊是否損壞、儲存的區塊是否與當初寫入的內容相符,或自訂格式的完整性欄位是否正確。但在授權指令、保護憑證、驗證不受信任的軟體,或確立檔案來源時,它是錯誤的工具。
What Causes CRC32 Mismatches
Most failed CRC32 lookups come from a small number of recurring mistakes. Avoiding them is usually faster than debugging the algorithm.
The most common mistake is feeding in the wrong encoding. In text mode the calculator encodes the input as UTF-8. ASCII characters contribute one byte, while accented letters, CJK characters, and emoji contribute multiple bytes. A result computed over UTF-16 code units, a legacy character set, or normalized text will differ. If your spec hands you exact bytes, use hex mode instead of retyping them as visible text.
The second is the newline convention. LF and CRLF produce different bytes, so the same logical line produces a different CRC32 on Unix and Windows. If the spec does not specify, normalize the input and document which convention you used.
The third is hidden header or framing bytes. ZIP local file headers, gzip member headers, and PNG chunk headers are not always included in the covered range. If you compute CRC32 over the raw payload but the spec expects it over the header plus payload, the values will not match. Always confirm whether the target specification includes headers, length fields, delimiters, or a stored checksum field in the covered range.
The fourth is leading zeros. In hex mode, every two digits become one byte, and leading 00 bytes are preserved. Dropping a leading 00 byte shortens the input by one byte and changes the CRC32. If the hex entry rejects odd-length input, that is the parser refusing to guess which side a stray nibble belongs to.
The fifth is confusing CRC32 with a cryptographic hash. CRC32 is shorter, faster, linear, and unauthenticated. If you need forgery resistance, use SHA-256 or HMAC-SHA-256 and a trusted channel, and never rely on a CRC32 match to verify downloadable software.
Related reading: How to Generate CRC32 From Text or Hex Bytes.
Related reading: Base to Hex: Convert Encoded Bytes Without Losing a Zero.