単純チェックサム
単純チェックサム
このレッスンで分かること
mod 256を取らずに合計だけ返す実装もありますが、1 バイトに収める のが「単純チェックサム」の定義としては一般的です- ネットワークやストレージで「データが途中で化けていないか」を検知するために使われるのが チェックサム です
- ファイルをダウンロードしたあとに
MD5やSHA-256の値を比べた経験があるかもしれません
単純チェックサム とは
バイト配列の各要素を 256 (1 バイト) の範囲で足し合わせ、単純なチェックサムを計算します。本レッスンでは、単純チェックサム の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
ネットワークやストレージで「データが途中で化けていないか」を検知するために使われるのが チェックサム です。本レッスンでは、バイト配列の合計を 256 で剰余を取る最もシンプルなチェックサムを実装します。
チェックサムの役割
ファイルをダウンロードしたあとに MD5 や SHA-256 の値を比べた経験があるかもしれません。これは「同じビット列か」を素早く確認する仕組みで、ハッシュ系のチェックサムです。今回扱うのは、もっと単純で軽量な 8bit チェックサム です。
- 計算が
O(n)で速い - 値域が
0〜255の 1 バイトに収まる - 衝突しやすいが、
シリアル通信やバーコード、UARTのような単純なプロトコルで広く使われる
例えば
IPv4ヘッダのチェックサム、Modbusの LRC、バーコードのチェックディジット、クレジットカード番号の Luhn アルゴリズムなど、用途は多岐にわたります。
計算式
バイト配列 bytes のチェックサムは次の式で求まります。
checksum = (b0 + b1 + ... + bn-1) mod 256
つまり全部足して 256 で割った余りです。1 バイトの範囲 (0 〜 255) に収めるための剰余演算 (% 256) がポイントです。
図のポイント (テキスト併記)
-
mod 256を取らずに合計だけ返す実装もありますが、1 バイトに収める のが「単純チェックサム」の定義としては一般的です
mod 256を取らずに合計だけ返す実装もありますが、1 バイトに収める のが「単純チェックサム」の定義としては一般的です。
具体例
[](空配列) →0[0]→0[1, 2, 3]→6[100, 100, 100]→300 % 256 = 44[255, 1]→256 % 256 = 0[255, 255, 255, 255]→1020 % 256 = 252
5 番目の例で
[255, 1]のチェックサムが0になるのは、わざと足して256ぴったりになる組み合わせを選んだからです。実データではこれが「衝突」の典型例です。
Python 実装
Python
def checksumSum(bytes_list):
total = 0
for b in bytes_list:
total += b
return total % 256sum(bytes_list) % 256 の 1 行でも書けますが、ループ版のほうが他言語との対応がわかりやすいです。bytes という変数名は Python の組み込みと衝突するので、bytes_list のように別名にしています。
JavaScript 実装
JavaScript
function checksumSum(bytes) {
let total = 0;
for (const b of bytes) total += b;
return total % 256;
}Array.prototype.reduce を使えば bytes.reduce((a, b) => a + b, 0) % 256 の 1 行で書けます。可読性の好みで選んでください。
より高度なチェックサム
単純チェックサムには弱点があります。[1, 2] と [2, 1] のチェックサムは同じ 3 になり、並び順の入れ替え を検知できません。これを解決するために、実用的なプロトコルでは次の改良版が使われます。
CRC-32(Cyclic Redundancy Check) — 32bit の値で、ビット反転やバースト誤りの検出力が高いFletcher/Adler-32— 順序を考慮した軽量チェックサムMD5/SHA-1/SHA-256— 暗号学的ハッシュ、衝突確率が極めて低い
通信路の信頼度が低い場合は
CRC-32以上、改ざん検知が目的ならSHA-256以上を使うのが現代の定石です。単純チェックサムは学習用と理解しておきましょう。
送信側と受信側
プロトコル設計では、送信側がチェックサムをデータの末尾に付け、受信側が自分で再計算して比較する、という流れが一般的です。一致しなければ「壊れた」と判断して 再送要求 を出します。チェックサムは「同じか違うか」しか教えてくれない一方向の検査ですが、再送 という素朴な仕組みと組み合わせるだけで信頼性のあるプロトコルが構築できます。
また、チェックサム自身もデータの一部とみなして「全体のチェックサムが 0 になる」ように設計するテクニックもよく使われます。IPv4 ヘッダのチェックサムフィールドもこの考え方(チェックサム込みで検算する)を採用していますが、方式は16bitの1の補数和であり、単純な mod 256 の加算とは異なります。
よくある間違い
% 256を忘れ、値が1024のような 1 バイトを超えた値を返す- 空配列のときに
totalを初期化せず、エラーになる - バイト値が
0〜255の範囲外 (負数や 256 以上) でも受け付けて、剰余が正しく出ない bytesという変数名を Python の組み込み型と衝突させてしまう- 浮動小数点の足し算になってしまい、
%の結果が小数になる
やってみよう
関数 checksumSum(bytes) を実装してください。bytes はバイト値 (0 〜 255 の整数) の配列で、合計を 256 で割った余りを整数で返します。空配列のときは 0 を返します。
よくある質問
Q. このトピックを覚える意味は何ですか?
A. チェックサムは「データが途中で化けていないか」を軽量に検知する仕組みです。TCP/IPヘッダーやファイル転送プロトコルなど、あらゆる通信・保存の基盤で使われている考え方なので、仕組みを一度理解しておくと、より高度なハッシュ関数(MD5, SHA-256)の理解にも繋がります。
Q. 実務でこの知識を使う場面は?
A. ファイルダウンロード後の整合性検証、ネットワークパケットのエラー検出、シリアル通信でのデータ破損チェックなど、軽量な破損検出が必要な場面で使われます。より強固な改ざん検知が必要な場合はMD5やSHA-256のような暗号学的ハッシュ関数が使われますが、考え方の原点は単純チェックサムと同じです。
Q. 他の章とどう繋がりますか?
A. 前の章で扱ったビット演算・バイト単位の処理がそのまま計算の基礎になります。次のCIDRマスクのレッスンでも、32bit整数をビット単位で扱う視点を引き続き使います。
次のレッスン
次は 第6章まとめクイズ に進みましょう。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- チェックサム の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. チェックサム とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- 全バイトを合計する
- 合計を 256 で割った余りを返す
- 空配列のときは 0 を返す
入出力例
test-cases.txt
checksumSum([]) → 0
checksumSum([0]) → 0
checksumSum([1,2,3]) → 6
checksumSum([100,100,100]) → 44
checksumSum([255,1]) → 0
checksumSum([255,255,255,255]) → 252
checksumSum([10,20,30,40,50]) → 150
checksumSum([128,128]) → 0