行は「アルゴリズム 値」の形式で、その下にインデントされたパラメータ行が続きます。コピー&ペーストした結果が常に、どのパラメータセットで生成されたかを語ります。
CRC — 巡回冗長検査をゼロから解説
一文で言うと:CRC はデータをひとつの巨大な 2 進数とみなし、減算の代わりに XOR を使って固定の「生成多項式」で割り、その余りを報告します — 入力の 1 ビットでも反転すれば激しく変化するコンパクトな指紋であり、だからこそ PNG ファイルから Modbus 回線まで、あらゆるものがこれを運んでいます。
CRC とは実際には何か
除算のイメージ。バイト列をひとつの長い 2 進数として並べます。除数 — 多項式(CRC-32 なら 0x04C11DB7 など)— を選び、「減算」が XOR である 2 進長除算を実行します:走行余りレジスタの先頭ビットが 1 になるたびに除数を XOR し、左シフトして繰り返す。メッセージ全体が通し終わったときレジスタに残っているものが CRC です。定義上、鍵もテーブルもありません — 割り算の余りだけです。
5 つのパラメータ。2 つのシステムがどちらも「CRC-32」と言って食い違うことがあります。名前だけでは何も確定しないからです。完全なレシピには 5 つの値が必要です:poly(除数)、init(レジスタの初期値 — ゼロ初期化だと先頭のゼロバイトが消えてしまい、1 初期化だと消えない)、refin/refout(各入力バイトと最終レジスタをビット反転するか。最下位ビットから送るシリアルハードウェアの名残)、xorout(末尾にゼロが続いても結果が変わるようにする最終 XOR マスク)。このページがすべての結果の隣に 5 つすべてを表示するのは、まさにそのためです。
なぜエラーを検出できるのか。よく選ばれた除数は、メッセージの余りと数ビット反転した同じメッセージの余りが圧倒的な確率で異なるようにします:優れた CRC-32 は 1 ビット・2 ビットエラーすべて、奇数個のビットエラーすべて、32 連続ビットまでのバーストエラーすべてを捕捉します — 確率的ではなく保証付きです。この保証は偶発的破損に関するものであり、CRC をノイズの多い回線や不安定なディスクに適したツールにしているのはこれです。
CRC が「ではない」もの
暗号学的ハッシュではない。秘密も一方向性もありません:パラメータを知る者は誰でも、4 バイトの修正バイトを付加するだけで、ミリ秒で任意の CRC を持つメッセージを偽造できます。CRC は事故を検出するもので、敵を検出するものではありません。見知らぬ相手とのダウンロード検証には署名が重要です — ハッシュ生成(MD5/SHA/BLAKE2)を参照してください。あのページでは、MD5 と SHA-1 が敵対的環境から引退し SHA-256 が生き残っている理由も説明しています。
誤り訂正符号ではない。CRC は何かが変わったことは教えますが、何が変わったかは教えません。その場で修復するのは Reed–Solomon や Hamming のような符号の仕事で、それらはデコーダーが反転できる冗長構造を意図的に保存します。
圧縮でも暗号化でもない。余りは入力サイズにかかわらず数バイトであり、そこから入力を復元することはできません — しかし暗号学的ハッシュと違い、それは単に情報が捨てられたからで、反転が困難だからではありません。
このページのファミリー
CRC-32 の四つ子。このページのエントリのうち 4 つは poly 0x04C11DB7 を共有しながら、異なる値を生成します:ISO-HDLC(反転、init/xorout すべて 1)が zlib、gzip、PNG、ZIP の「あの」CRC-32 です。BZIP2 は同じ計算の非反転版。MPEG-2 は最終 XOR のない BZIP2。POSIX はゼロ初期化で、cksum コマンドの基礎です(cksum はさらにファイル長を除算に付加するため、ファイルの cksum と同じバイトの CRC-32/POSIX は一致しません)。CRC-32C(Castagnoli、poly 0x1EDC6F41)は 5 番目の兄弟:より良い誤り検出性能のために選ばれた異なる poly で、近年の x86・ARM CPU が 1 命令でメモリ速度で計算できるものです。
CRC-64 の四重奏。XZ は ECMA-182 多項式を反転形で、1 初期化の init と xorout とともに使います。ECMA-182 自身は DLT-1 テープ規格由来の非反転・ゼロ初期化の原形です。GO-ISO は Go の crc64.ISO、poly は小さな 0x1B、これも反転形。REDIS はハッシュスロット割り当てに良いアバランチを持つよう選ばれた poly を使います。64 ビットは、CRC が純粋なチェックサムではなくハッシュ関数(バケット化)として使われ始めるサイズです。
Adler-32 は異端児です:まったく除算ではありません。バイトの和(A、1 から開始)と、その和の和(B)を、どちらも 65521 を法として計算し、2 つの 16 ビット和を連結します。ソフトウェアでは CRC-32 より速く、zlib は deflate ストリームにこれを使います — しかし短い入力(数百バイト未満)では和が運ぶ情報が少なすぎるため、zlib が小さなブロックで CRC-32 に戻すのはまさにこのためです。
CRC-8 と CRC-16 はバイトが高価な場所で生き残ります:CRC-8/CCITT(poly 0x07)は SMBus や携帯無線プロトコルの単一ヘッダーバイトを保護し、CRC-16/CCITT-FALSE はスマートカードのブロックを守り、CRC-16/MODBUS は世界中の工場のあらゆる Modbus RTU フレームのチェックサムです。
それぞれの使われ場所
| パラメータセット | 使われている場所 |
| CRC-32/ISO-HDLC | zlib、gzip、PNG、ZIP、Ethernet(FCS)、多くのアーカイブ形式 |
| CRC-32C | iSCSI、ext4、btrfs、ZFS、SSE4.2/ARMv8 の CRC32C ハードウェア命令 |
| CRC-32/BZIP2 | .bz2 アーカイブストリーム |
| CRC-32/MPEG-2 | MPEG-2 トランスポートストリーム |
| CRC-32/POSIX & cksum | POSIX cksum コマンドの出力(cksum file.txt) |
| CRC-16/MODBUS | Modbus RTU フレーム(産業用 PLC、メーター、インバーター) |
| CRC-16/CCITT-FALSE | スマートカード、X.25 系のリンク、一部の GPS プロトコル |
| CRC-8/CCITT | SMBus(PEC バイト)、携帯無線ヘッダー |
| CRC-64/XZ | .xz コンテナの整合性チェック |
| CRC-64/ECMA-182 | ECMA-182 / DLT-1 テープ規格 |
| CRC-64/GO-ISO | Go 標準ライブラリ crc64.ISO |
| CRC-64/REDIS | Redis クラスターのハッシュスロット割り当て |
| Adler-32 | zlib ストリーム(deflate)、その他の高速チェックサム用途 |
アンカー表 — check(“123456789”)
CRC カタログの慣例は、ASCII 文字列 123456789(9 バイト)の結果を公表することです。下のすべての値はこのページで再現できます:テキストボックスに 123456789 と入力し、アルゴリズムにチェックを入れ、計算をクリックしてください。
| パラメータセット | 幅 | チェック値(16 進) |
| CRC-8/CCITT | 8 | 0xf4 |
| CRC-16/CCITT-FALSE | 16 | 0x29b1 |
| CRC-16/MODBUS | 16 | 0x4b37 |
| CRC-32/ISO-HDLC | 32 | 0xcbf43926 |
| CRC-32C | 32 | 0xe3069283 |
| CRC-32/BZIP2 | 32 | 0xfc891918 |
| CRC-32/MPEG-2 | 32 | 0x0376e6e7 |
| CRC-32/POSIX | 32 | 0x765e7680 |
| cksum (POSIX command) | 32 | 0x377a6011 |
| CRC-64/XZ | 64 | 0x995dc9bbdf1939fa |
| CRC-64/ECMA-182 | 64 | 0x6c40df5f0b497347 |
| CRC-64/GO-ISO | 64 | 0xb90956c775a41001 |
| CRC-64/REDIS | 64 | 0xe9c6d914c4b8d9ca |
| Adler-32 | 32 | 0x091e01de |
出典:各値は独立したビット演算のリファレンス実装で相互検証し、存在する場合はアルゴリズムを提供するシステムライブラリ(CRC-32 と Adler-32 は zlib、残りは Greg Cook の CRC カタログ)とも照合しています。
よくある間違い
- パラメータなしの「CRC-32」。ISO-HDLC、BZIP2、MPEG-2、POSIX、CRC-32C の間で、同じ名前の下に 5 つの異なる値が出回っています。結果とともに必ず poly/init/refin/refout/xorout を記録してください — このページがそれを表示します。
- ファイルの CRC-32 と
cksum 出力の比較。別のアルゴリズムです:cksum は長さを付加し、異なる init を使います。数値は一致しませんが、どちらも「正しい」のです。
- 改ざんへの耐性を CRC に期待する。一致する CRC の偽造は教科書レベルの練習問題です(末尾 4 バイトをパッチ)。相手が敵対的かもしれない場合は、キー付き MAC(HMAC)か署名を使ってください。
- アバランチを期待する。CRC は線形です:似たメッセージは似た CRC を与えます。ノイズには良く、ハッシュには不向き — バケット化が必要なら、CRC-32 より CRC-64 か本物のハッシュが安全です。
- 16 進テキストとバイト。文字列
"123456789"(9 ASCII バイト、31 32 33 34 35 36 37 38 39)と数値 0x123456789 は、異なる CRC を持つ異なる入力です。ソースデータが本当にバイナリなら 16 進バイトタブを使ってください。
よくある質問
私の CRC-32 が ZIP ファイル内のものと一致しないのはなぜ?ZIP の CRC-32 は未圧縮データに対する ISO-HDLC です。同じバイト(圧縮ストリームではなく)、同じモード(テキスト vs 16 進)、同じパラメータセットを扱ったか確認してください — 各結果の下に表示されるパラメータ行は、この確認を一瞬で済ませるためのものです。
CRC-32C と CRC-32 はどちらが良い?偶発エラーの検出としては、どちらも 32 ビットまでのバーストをすべて捕捉します。CRC-32C は一部のエラーパターンで性能が良く、CPU 命令を持つのはこちら — ギガビット速度で実質無料です。CRC-32/ISO-HDLC が生き残っている理由は互換性です:30 年分のアーカイブがこれを話しています。
CRC-64 は CRC-32 より強い?より長いバースト(64 ビットまで)を検出し、バケット化用途での衝突ははるかに少ないですが、偽造の容易さは同じです — 幅が買うのは検出保証で、安全性ではありません。
CRC は逆算して入力を明かせる?いいえ — 無限に多くの入力が同じ CRC を共有します。しかし暗号学的ハッシュと違い、攻撃者は任意の CRC を持つ入力を構成できます。一方向性がまったくないというのはこの意味です。