
「計算檔案的 CRC32」實際涵蓋的內容
檔案的 CRC-32/ISO-HDLC 是一個 8 位數的小寫十六進位值,產生方式是將檔案涵蓋的位元組,透過反射多項式 0xEDB88320 進行運算,並使用初始暫存器 0xFFFFFFFF 與最終 XOR 值 0xFFFFFFFF。對於 ASCII 位元組 123456789,標準化的檢查值為 cbf43926,這正是不同實作之間辨識同一變體的方式。因此,「計算檔案的 CRC32」意指決定檔案中哪些位元組屬於涵蓋範圍、將這些位元組轉換為 UTF-8 文字或原始十六進位配對,並產生一個格式化為恰好 8 個十六進位數字(保留前導零)的無符號 32 位元結果。
大多數讀者來到這裡,是因為某個下載頁面、建構腳本或同事在某個檔案旁邊公布了一個像 cbf43926 這樣的值,並要求他們確認是否相符。困難點幾乎從來不是運算本身,而幾乎都是位元組範圍的問題:所公布的值涵蓋的是原始位元組、是標頭加上主體,還是去除了長度欄位的精簡主體?弄錯這一點會產生一個與其他所有工具都不一致的結果,即便每個工具本身都是正確的。
如何使用瀏覽器工具計算檔案的 CRC32
CRC32 計算機接受 UTF-8 文字或精確的十六進位位元組,並以 8 位數小寫十六進位字串的形式回傳 CRC-32/ISO-HDLC 值。運算完全在瀏覽器中進行,輸入內容不會被上傳,而複製動作只會複製 32 位元的值,這讓機密資料不會經過網路傳輸。
- 確認所需的 CRC 變體與精確的位元組範圍。本頁面僅實作 CRC-32/ISO-HDLC,亦即 gzip、ZIP、PNG 以及大多數通用封存檔與影像格式所使用的反射多項式 0xEDB88320 變體。
- 透過檢查標準值來確認變體:對於 ASCII 位元組 123456789,結果必須為 cbf43926。若預期值不同,表示該系統使用的是不同的 32 位元公式,例如 CRC-32C、Koopman、MPEG-2、BZIP2 或 JAMCRC。
- 選擇輸入模式。僅在規格將涵蓋的承載資料描述為字串時,才選擇 UTF-8 文字;當規格將承載資料描述為精確的位元組、標頭、長度欄位或儲存的 CRC 位元組時,則選擇十六進位位元組。
- 準確輸入承載資料。十六進位模式會忽略位元組配對之間的空白,但要求位數為偶數、拒絕 0x 前綴與奇數的尾端半位元組,並保留前導的 00 位元組。
- 進行計算,然後將結果的全部 8 位數與預期值進行比對,包括前導零。比對相符只能證明在偶發錯誤方面的一致性,而非真實性。
各檔案格式涵蓋位元組的起點與終點
不同檔案格式涵蓋的位元組並不相同。兩個正確的實作結果不一致,最常見的原因就是其中一個包含了標頭或長度欄位,而另一個則沒有。下表列出使用 CRC-32/ISO-HDLC 的格式之標準涵蓋範圍。
| 格式 | 涵蓋的位元組 | 儲存位置 |
|---|---|---|
| gzip (RFC 1952) | 未壓縮的原始位元組,於壓縮前計算 | 結尾區,小端序,位於 ISIZE 之前 |
| PNG | 區塊類型代碼加上區塊資料,適用於每個使用 CRC 的 IDAT 與輔助區塊 | 每個區塊末端的 4 位元組大端序結尾 |
| ZIP 本地檔案標頭 | 從簽章到檔名與延伸欄位之間的位元組,不含資料描述子 | 本地標頭中的 4 位元組小端序欄位 |
| ZIP 中央目錄項目 | 從中央目錄標頭簽章到檔案註解結尾之間的位元組 | 中央目錄項目中的 4 位元組小端序欄位 |
| ZIP 資料描述子 | 選擇性的 4 位元組簽章,接著是 CRC32,再來是壓縮與未壓縮大小 | 當一般用途旗標的第 3 位元被設定時,位於檔案資料之後 |
在驗證下載的檔案時,請先找出儲存的值,再確認規格所指定的涵蓋位元組,然後只將這些位元組輸入計算機。如需關於 ZIP、PNG 與 gzip 等格式特定位元組範圍的更深入指引,請參閱如何計算 ZIP、PNG 與 gzip 檔案的 CRC32。
正確比對 8 位數結果
輸出會格式化為恰好 8 個小寫十六進位數字,且該值會被視為無符號,因此前導零一律會顯示。前導的 0x00 位元組會在輸入時保留,並影響最終的 8 位數輸出,而額外的前導 0x00 位元組也會持續影響結果。因此,刪除前導零或將結果改為大寫,是「幾乎相符」回報中常見的原因。
此計算機使用一個由反射多項式 0xEDB88320 建構成的 256 項表格,從最低有效位元開始處理每個位元組,並在格式化前以 0xFFFFFFFF 對暫存器進行補數運算。這是 RFC 1952 中針對 gzip 所描述的實用查表驅動方法,並與 zlib 檢查碼手冊中記錄的演算法相符。在相同的位元組序列上與 zlib 的 crc32 函式進行交叉比對,是確認差異出在位元組範圍而非演算法的快速方法。
常見的變體與位元組範圍錯誤
數種 32 位元 CRC 公式存在著不同的多項式、初始值或最終 XOR 常數。其區別性參數列示如下。
| 變體 | 反射多項式 | 初始值 | 最終 XOR | 「123456789」的檢查值 |
|---|---|---|---|---|
| CRC-32/ISO-HDLC(本工具) | 0xEDB88320 | 0xFFFFFFFF | 0xFFFFFFFF | cbf43926 |
| CRC-32C(Castagnoli) | 0x82F63B78 | 0xFFFFFFFF | 0xFFFFFFFF | e3069283 |
| CRC-32/MPEG-2 | 0x04C11DB7 | 0x00000000 | 0x00000000 | 0376E6E7 |
| CRC-32/BZIP2 | 0x04C11DB7 | 0xFFFFFFFF | 0xFFFFFFFF | FC891918 |
| CRC-32/JAMCRC | 0xEDB88320 | 0xFFFFFFFF | 0x00000000 | 340BC6D9 |
若 123456789 的預期值不是 cbf43926,表示來源使用了不同的 32 位元公式。同樣常見的問題還有:將涵蓋的位元組重新輸入為可見文字,因而遺失了 CR LF 與 LF 之間、UTF-8 與 UTF-16 之間、NFC 與 NFD 正規化之間,或原始位元組與其 Base64 表示之間的差異。當協定交給你的是位元組,請貼上位元組;當交給你的是文字,請確認編碼恰好為 UTF-8,沒有 BOM 也沒有經過任何換行字元的正規化轉換。
CRC32 並非安全性或真實性檢查
CRC-32 是一種循環冗餘檢查,設計用於偵測資料中常見的偶發變更,例如不穩定磁碟上的位元翻轉或下載被截斷。它具有線性特性且極易被操控:任何想要讓承載資料的雜湊值符合所選 32 位元值的人,都可以在不知道原始資料的情況下構造出來。CRC32 既不是加密、也不是密碼雜湊、訊息驗證碼,更不是數位簽章。
它的用途在於確認你解壓縮出來的封存檔與旁邊公布的數值一致,或是確認寫入磁碟的檔案仍與記憶體中的內容相符。請勿將它用於驗證不受信任的軟體、授權指令、保護憑證,或是用於證明檔案來自可信的發行者。若需對抗性環境下的完整性保護,請透過經過驗證的管道傳輸檔案,並同時公布 SHA-256 或更強的密碼學摘要。
檔案大小限制與處理較大檔案的作法
瀏覽器工具最多可處理 5,000,000 位元組的輸入,以確保查表驅動迴圈在頁面上仍能保持回應速度。輸出絕不會被靜默截斷:永遠會顯示 8 個十六進位數字,且該值被視為無符號,因此任何被接受輸入的結果都是完整的 32 位元檢查值。空白的程式化輸入其 CRC 為 00000000,雖然介面會要求輸入資料以避免不小心按到空白鍵時,看起來像是進行了一次有意義的驗證。
若承載資料較大,請將輸入切割為不超過上限的區塊,分別計算每個區塊自身位元組的 CRC32,然後利用該演算法的串流特性將各區塊的值合併起來。若下游消費者已提供參考值,建議優先選擇能直接從磁碟讀取檔案或以串流方式讀取的工具,這樣整個檔案就能在不需手動分塊的情況下一次完成雜湊運算。