LASSIC Media らしくメディア

2026.10.09 らしくコラム

チェックサムでファイルが壊れていないか確かめる方法

監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)

ノートパソコン側面のUSBポートに赤と黒のUSBメモリを差し込み、パソコンとの間でファイルをやり取りしている場面の写真。

この記事の結論

  • チェックサムは、データから計算した短い値を添え、受け手が計算し直して比べることで途中の誤りを見つける仕組みです。
  • パリティや加算は並び順などの誤りを見逃しやすく、通信や記録媒体ではバースト誤りに強いCRCが広く使われています。
  • 配布ファイルはsha256sumなどで照合しますが、値の一致は改ざんがない証明にならず、作った人の確認には署名が要ります。

※ 本記事は2026年10月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。

チェックサムは、データが途中で壊れていないかを確かめるために、データから計算して添えておく短い値です。IPやTCPのヘッダ、圧縮ファイル、配布されるインストーラーなど、ふだん意識しない場所で使われています。

ただ、パリティ、加算、CRC、SHA-256のどれもがチェックサムと呼ばれることがあり、何をどこまで確かめられるのかは混同されがちです。本記事では、誤り検出の仕組みと計算例、配布ファイルの照合の手順、改ざん対策には署名が要るという限界までを、RFCと公式ドキュメントをもとに整理します。

チェックサムとは

チェックサムは、送る側や保存する側がデータから決まった手順で計算した値を添えておき、受け取る側が同じ計算をして一致するかを比べる仕組みです。一致しなければ、途中のどこかでデータが変わったと分かります。多くの方式は誤りを見つけるだけで直しはしないため、見つけたら送り直しや再ダウンロードで取り直します。

チェックサムの流れを示した図。送る側がデータから検査値を計算して添え、通信や保存の途中で1ビットが反転しても、受け取る側が計算し直して比べれば不一致で気づき、取り直せる。下段では、雑音や媒体の傷などの偶発的な誤りはチェックサムで見つけられるが、意図的な書き換えではデータと検査値を両方差し替えられるため、作った人の確認には署名が要ることを示している。

暗号学的ハッシュ関数の性質(一方向性や衝突耐性)は「ハッシュ関数とは」で、パスワードの保存は「パスワードハッシュの基本」で扱っています。本記事では、偶発的な誤りを見つけるためのチェックサムと、配布ファイルの検証、その限界に絞ります。

仕組み:パリティ・加算・CRC

誤り検出のためのチェックサムの主な方式(この記事の整理)
方式 計算のしかた 見逃しやすい誤り 本記事で扱う例
パリティ 1の数が偶数(または奇数)になるよう1ビットを足す 2ビットが同時に反転した誤り 下の計算例
加算 一定の長さに区切って足し合わせる 並び順の入れ替えなど、合計が変わらない変化 IP・TCP・UDPのインターネットチェックサム
CRC ビット列を多項式とみなし、生成多項式で割った余りを使う 検査値が短いほど、偶然の一致が起きやすい gzipのCRC-32、iSCSIのCRC32C

パリティは最も単純な方法です。たとえば1011001のように1が4個あるデータに偶数パリティを付けるなら0を足し、1の数を偶数に保ちます。受け取った側で1の数が奇数なら誤りです。ただし2ビットが同時に反転すると偶数のままなので、この誤りは見逃します。

加算は、データを一定の長さに区切って足し合わせる方法です。インターネットで使われるのはこの型で、足す順序を入れ替えても結果が変わらない性質のおかげで、まとめて速く計算できます。その反面、データの並び順が入れ替わっても合計は変わりません。

CRC(巡回冗長検査)は、データのビット列を多項式とみなし、あらかじめ決めた生成多項式で割った余りを検査値にします。割り算といっても、XORとシフトの組み合わせ(「ビット演算の基礎」を参照)で計算できるので、ハードウェアでもソフトウェアでも速く求められます。

具体例:インターネットチェックサム

IPv4、UDP、TCPのヘッダが使うチェックサムの計算方法は、RFC 1071にまとめられています。隣り合う2バイトを16ビットの整数とみなし、1の補数の足し算で合計します。送る側はチェックサム欄を0にして合計を求め、その1の補数を欄に入れます。受け取る側はチェックサム欄を含めて合計し、すべてのビットが1になれば正しいと判断します。*1

RFC 1071の計算例と同じ8バイトを使い、Pythonで確かめてみます。

import zlib

def inet_checksum(data: bytes) -> int:
    if len(data) % 2:
        data += b"\x00"                     # 奇数長は末尾に0を足して16ビットにそろえる
    s = 0
    for i in range(0, len(data), 2):
        s += (data[i] << 8) | data[i + 1]   # 隣り合う2バイトを16ビットの整数にする
        s = (s & 0xFFFF) + (s >> 16)        # あふれた桁を下位に足し戻す
    return ~s & 0xFFFF                      # 合計の1の補数がチェックサム

data = bytes.fromhex("0001f203f4f5f6f7")    # RFC 1071の計算例と同じ8バイト
c = inet_checksum(data)
print("checksum = %04x" % c)
print("verify   = %04x" % inet_checksum(data + c.to_bytes(2, "big")))
swapped = bytes.fromhex("f2030001f4f5f6f7") # 先頭の2語を入れ替える
print("swapped  = %04x" % inet_checksum(swapped))
print("crc32    = %08x / %08x" % (zlib.crc32(data), zlib.crc32(swapped)))

Python 3.12で実行すると、チェックサムは220dで、もとの合計ddf2はRFC 1071の計算例と一致しました。チェックサムを付けて計算し直すと0000になり、確認も通ります。一方、先頭の2語を入れ替えてもチェックサムは220dのままで、加算では並び順の誤りを見つけられません。同じ2つのデータのzlib.crc32は079b0750と0fd0ee3cで、CRCは入れ替えを見分けました。

IPv4のヘッダのチェックサムはヘッダだけが対象で、TTL(生存時間)のように中継のたびに変わる項目があるため、処理する地点ごとに計算し直します。*2 TCPは、ヘッダと本文に加え、IPアドレスなどを含む疑似ヘッダも合計に入れ、宛先を誤って届いたセグメントを見分けます。*3 IPv6のヘッダにはチェックサムがなく、UDPのチェックサムは、トンネルでの例外を除いて省略できなくなりました。*4

CRCが選ばれる理由

iSCSIの誤り検出方式を検討したRFC 3385は、続いた複数のビットがまとめて壊れる「バースト誤り」が、通信回線や記録媒体で主流の現象だと述べています。CRCはバースト誤りの検出に優れ、独立した複数のビット誤りにも強いため、通信や磁気記録で広く使われてきたと説明しています。*5

CRCには、検査値の長さと生成多項式の違う種類がいくつもあります。RFC 3385は、iSCSI向けのCRC32Cの多項式を11EDC6F41、IEEE 802のCRCを104C11DB7と示しています。検査値をrビットとすると、でたらめに壊れたデータが偶然一致する確率は、データが長くなるにつれて2のr乗分の1に近づくとされます。32ビットなら約43億分の1です。gzip形式では、圧縮前のデータのCRC-32をファイルの末尾に入れる決まりです。*6

Pythonのzlib.crc32とzlib.adler32について、公式ドキュメントは、暗号学的な強さはなく、認証やデジタル署名に使うべきではないと明記しています。*7 CRCは偶発的な誤りを見つける道具で、意図的な書き換えを防ぐものではありません。

配布ファイルをsha256sumで確かめる

ソフトウェアやOSのイメージは、SHA-256などのハッシュ値の一覧と一緒に配布されることがよくあります。SHA-256を定めたFIPS 180-4は、メッセージが変われば、非常に高い確率で異なるダイジェストになると説明しています。*8

Git BashやLinuxでは、GNU coreutilsのsha256sumを使います。-c(–check)を付けると、記録しておいた値を読み込んで照合します。

$ printf 'release 1.0\n' > app.tar
$ sha256sum app.tar > SHA256SUMS
$ cat SHA256SUMS
7b4871e6b35405054627068a49669e601dc93c5201ec75105d5858b79aecea12 *app.tar
$ sha256sum -c SHA256SUMS; echo "exit=$?"
app.tar: OK
exit=0
$ printf 'release 1.1\n' > app.tar      # 中身を1文字だけ変える
$ sha256sum -c SHA256SUMS; echo "exit=$?"
app.tar: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
exit=1

Git for Windowsに付属するsha256sum 8.32で実行すると、一致すればOK、1文字変えただけでFAILEDになり、終了コードも0と1に分かれました。値の後ろの「*」はバイナリモードで読んだ印で、マニュアルは、GNUのシステムではバイナリモードとテキストモードに違いはないとしています。*9

同じGNU coreutilsのcksumは、既定では32ビットのCRCを出力し、coreutils 9.11では-aでsha2やcrc32bなども選べます。*10 Git for Windowsの8.32のcksumには-aがありません。変更前のファイルでは、cksumのCRCが3380559569、zlib.crc32が1390818262で、同じ32ビットのCRCでも値が違いました。比べるときは同じ方式どうしで比べます。

Windowsでは、PowerShellのGet-FileHashが使えます。アルゴリズムを指定しなければSHA256で計算し、SHA1、SHA384、SHA512、MD5も選べます。ただしマニュアルは、MD5とSHA1はもう攻撃に強いとはみなされないとしています。*11

PS> $expected = '7b4871e6b35405054627068a49669e601dc93c5201ec75105d5858b79aecea12'
PS> (Get-FileHash .\app.tar -Algorithm SHA256).Hash
7B4871E6B35405054627068A49669E601DC93C5201EC75105D5858B79AECEA12
PS> (Get-FileHash .\app.tar).Hash -eq $expected
True
PS> (Get-FileHash .\app.tar).Hash -ceq $expected
False

Windows PowerShell 5.1で試すと、Get-FileHashは16進数を大文字で出しました。PowerShellの-eqは大文字と小文字を区別しないのでTrueになりますが、区別する-ceqではFalseです。比べる前に大文字か小文字にそろえておきます。

チェックサムと署名の違い

チェックサムが一致しても、作った人が配ったものと同じとは言えません。RFC 3385は、攻撃者がデータを書き換えられる環境では、誤り検出の符号も新しいデータに合わせて書き換えられるため、これらの符号は攻撃から守るものではないと述べています。*5

SHA-256でも事情は同じです。ファイルとハッシュ値の一覧が同じサーバーにあれば、そのサーバーを書き換えられる人は両方を差し替えられます。ハッシュ値で確かめられるのは、手元のファイルが一覧の値と同じかどうかまでです。

そこで使われるのが電子署名です。FIPS 186-5は、デジタル署名がデータの不正な変更を検出し、署名者が誰かを確かめるために使われると説明しています。*12 Debianは、公式のインストールイメージに署名付きのチェックサムファイルを添えています。チェックサムはダウンロード中の破損の確認に、署名はDebianが公開したもので改ざんされていないことの確認に使うと案内し、署名はGnuPGなどのOpenPGPの実装で確かめます。*13

偶発的な誤りにはCRCなどのチェックサム、一覧と同じかの確認には暗号学的ハッシュ、作った人と改ざんの有無まで確かめるなら署名、と使い分けます。署名では、公開鍵が本物かどうかも別の経路で確かめておきます。

つまずきやすい点

1つ目は、方式の取り違えです。「CRC32」と書かれていても、cksumとzlib.crc32のように値の出し方が違う実装があります。ハッシュ値の一覧を配るときは、SHA256のように方式の名前を添えます。MD5やSHA-1の値しか示されていない場合は、改ざんの確認には使わず、署名などの別の手段を探します。

2つ目は、比べる前にファイルが変わってしまうことです。テキストのファイルは、改行コードがLFからCRLFに変わるだけで別の値になります。Gitの改行コードの変換やFTPのテキストモードの転送を通すと、見た目が同じでも一致しません。ハッシュ値を比べるファイルは、バイナリのまま受け渡します。

3つ目は、照合の手順が抜けることです。値を取得しただけで比べていない、CIで照合の失敗を無視している、といった形です。sha256sum -cの終了コードを見て、失敗したら後続の処理に進まないようにします。

4つ目は、ネットワークのチェックサムを頼りすぎることです。16ビットの合計は並び順の誤りを見逃し、IPv4のヘッダのチェックサムは中継のたびに計算し直されます。大事なファイルは、アプリケーションの側でもハッシュ値で確かめます。

外部に委託するときに確認しておきたい点

どの段階で何を確かめるかは設計で決まります。委託先には、まず、アップロード、システム間の連携、バックアップ、配布といった受け渡しの段階ごとに、どの方式の値をどこに保存し、誰が照合するのかを説明してもらいます。

次に、目的と方式が合っているかを見ます。偶発的な破損を見つけたいのか、改ざんまで防ぎたいのかで、CRC、SHA-256、署名のどれが必要かが変わります。改ざん対策を求めるなら、署名の鍵をどこで管理し、公開鍵をどう配るかまで決めてもらいます。

最後に、照合が自動で回り、失敗したときに止まるかを確かめます。CI/CD(継続的インテグレーションと継続的デリバリー)のジョブで照合し、失敗すれば後続の処理に進まない作りになっているか、保守の段階で照合の失敗を記録して監視しているかを見ます。

まとめ:チェックサムで確かめておきたい3つの点

第一に、パリティ・加算・CRCはどれも偶発的な誤りを見つける仕組みで、見逃しやすい誤りがそれぞれ違うこと。第二に、配布ファイルはsha256sum -cやGet-FileHashで照合し、方式の名前、大文字と小文字、改行コードの違いで取り違えないこと。第三に、ハッシュ値の一致は改ざんがないことの証明にはならず、作った人まで確かめるには署名が要ることです。

LASSICに相談するメリット

LASSICは、元請(プライムベンダー)としてシステムの開発と保守・運用を受託しています。データ連携や配布の仕組みでは、Pythonのzlibとhashlib、GNU coreutilsのsha256sum、PowerShellのGet-FileHash、GnuPGなどの署名ツールを、目的に合わせて使い分けます。設計の段階では、偶発的な破損を見つけたいのか改ざんまで防ぎたいのかを発注者と整理し、CRC・SHA-256・署名のどれを、受け渡しのどの段階で照合するかを決めます。検証と運用では、pytestで照合に失敗したときの動きを確かめ、GitHub ActionsなどのCI/CDでハッシュ値と署名の照合を自動で回し、失敗したら後続の処理に進まないようにします。本番では照合の失敗をPrometheusなどで監視します。

よくある質問

チェックサムとハッシュ値は、同じものですか

同じ意味で使われることがあり、sha256sumのマニュアルもSHA-256の値をチェックサムと呼んでいます。ただ、CRCのような誤り検出用の値は、同じ値になる別のデータを意図的に作りにくいようには設計されていません。改ざんの確認には、SHA-256のような暗号学的ハッシュ関数の値を使います。

CRCで、壊れた部分を直すことはできますか

本記事で扱った使い方のCRCは、誤りがあるかどうかを見つけるためのものです。誤りを見つけたら、データを送り直すか取り直します。誤りを直すには、誤り訂正符号という別の仕組みを使います。

ダウンロードしたファイルのハッシュ値が合わないときは、どうすればよいですか

まず、比べている方式(SHA256かSHA512かなど)と、対象のファイル名が合っているかを確かめます。それでも合わなければ、ダウンロードの途中で壊れたか、別のファイルを取得したおそれがあるので、使わずに公式の配布元から取り直します。

データの受け渡しと検証の設計のご相談

元請(プライムベンダー)として、データの受け渡しと検証の設計から、システムの保守・運用までご提案します。

Remoguとリラシクなら、データ連携や配布の仕組みの開発に加わるITエンジニアも探せます。

Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。

無料相談はこちら

出典

  1. *1 参考:R. Braden, D. Borman, C. Partridge「RFC 1071: Computing the Internet Checksum」(https://www.rfc-editor.org/rfc/rfc1071)。出典:1. Introduction(16ビットの1の補数の合計、チェックサムの生成と確認)と3. Numerical Examples(合計ddf2)を参照(2026年10月確認)
  2. *2 参考:IETF「RFC 791: Internet Protocol」(https://www.rfc-editor.org/rfc/rfc791)。出典:3.1 Internet Header FormatのHeader Checksum(ヘッダだけが対象、TTLなどの変化で処理する地点ごとに計算し直す)を参照(2026年10月確認)
  3. *3 参考:W. Eddy (Ed.)「RFC 9293: Transmission Control Protocol (TCP)」(https://www.rfc-editor.org/rfc/rfc9293)。出典:3.1 Header FormatのChecksum(ヘッダと本文、疑似ヘッダ、誤配送されたセグメントからの保護)を参照(2026年10月確認)
  4. *4 参考:S. Deering, R. Hinden「RFC 8200: Internet Protocol, Version 6 (IPv6) Specification」(https://www.rfc-editor.org/rfc/rfc8200)。出典:8.1 Upper-Layer Checksums(UDPのチェックサムは省略できない、トンネルのゼロチェックサムの例外、IPv6はインターネット層のチェックサムを持たない)を参照(2026年10月確認)
  5. *5 参考:D. Sheinwald ほか「RFC 3385: Internet Protocol Small Computer System Interface (iSCSI) Cyclic Redundancy Check (CRC)/Checksum Considerations」(https://www.rfc-editor.org/rfc/rfc3385)。出典:1. Introduction、2. Error Models and Goals(バースト誤り)、3. Background and Literature Survey(1/2^r、CRC32Cと IEEE 802の多項式、)、10. Security Considerationsを参照(2026年10月確認)
  6. *6 参考:P. Deutsch「RFC 1952: GZIP file format specification version 4.3」(https://www.rfc-editor.org/rfc/rfc1952)。出典:2.3.1 Member header and trailer(CRC32とISIZE)を参照(2026年10月確認)
  7. *7 参考:Python Software Foundation「zlib — Compression compatible with gzip」Python 3 ドキュメント(https://docs.python.org/3/library/zlib.html)。出典:zlib.crc32とzlib.adler32の説明(暗号学的な強さはなく、認証やデジタル署名に使うべきでない)を参照(2026年10月確認)
  8. *8 参考:NIST「FIPS 180-4: Secure Hash Standard (SHS)」(https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)。出典:Abstract(メッセージが変われば非常に高い確率で異なるダイジェストになる)を参照(2026年10月確認)
  9. *9 参考:GNU coreutils「sha256sum(1)」(man7.org掲載のマニュアルページ)(https://man7.org/linux/man-pages/man1/sha256sum.1.html)。出典:DESCRIPTION(-c/–check、「*」の表示、GNUのシステムではバイナリモードとテキストモードに違いがない)を参照(2026年10月確認)
  10. *10 参考:GNU coreutils「cksum(1)」(man7.org掲載のマニュアルページ、coreutils 9.11)(https://man7.org/linux/man-pages/man1/cksum.1.html)。出典:DESCRIPTION(既定は32ビットCRC、-a/–algorithmとDIGESTの一覧)を参照(2026年10月確認)
  11. *11 参考:Microsoft Learn「Get-FileHash (Microsoft.PowerShell.Utility)」(https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-filehash)。出典:Description と -Algorithm パラメーター(既定はSHA256、選べる値、MD5とSHA1は攻撃に強いとはみなされない)を参照(2026年10月確認)
  12. *12 参考:NIST「FIPS 186-5: Digital Signature Standard (DSS)」(https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf)。出典:Abstract(デジタル署名は不正な変更の検出と署名者の確認に使われる)を参照(2026年10月確認)
  13. *13 参考:Debian「Verifying authenticity of Debian images」(https://www.debian.org/CD/verify)。出典:署名付きのチェックサムファイル、チェックサムと署名の役割、OpenPGPの実装での確認を参照(2026年10月確認)




View