PostgreSQL 18 の macOS DMG を 12 分かけてダウンロードし終わる。リリースページには SHA-256 が添えてある。インストーラーを叩く前にハッシュを確認したいが、今手元にあるのは借り物の Mac で shasum$PATH に通っていない。フッターに「we don’t store your file」と書かれた怪しいオンラインハッシャーに 320 MB の DMG を投げ込むのは賢い選択ではない。ローカルでファイルを読み、1 バイトもネットに出さないブラウザベースのハッシャー — それが正解だ。

日本の開発現場でも似たケースは多い。Qiita や Zenn の記事から配布物のリンクを踏んだ後、本文に貼られた SHA-256 を突き合わせたい場面。あるいは社内プロキシ環境で HTTPS の再暗号化が走り、転送中にバイナリの一部が書き換わっている疑いがあるとき。どちらも、ハッシュ照合は数秒で答えを出す。

ファイルを今すぐ検証する →

なぜチェックサムが必要なのか

暗号学的ハッシュ関数は、任意のバイト列を短く固定長の指紋に圧縮する。ダウンロード検証で役立つのは次の 2 つの性質だ。

  • 決定性 — 同じバイト列は常に同じハッシュを返す。
  • アバランシェ効果 — 入力を 1 ビット変えるだけで、出力は全面的に別物になる。

合わせると、CDN プロキシがインストーラーに広告 iframe を 1 枚埋め込んだだけで SHA-256 は変わる。社内プロキシが透過的にペイロードを書き換えても同じ。ダウンロードが最後の 1 MB で切れても同じ。配布元が公開したハッシュと自分の機械で計算したハッシュを照合する — 再ダウンロードせずにこれら全部を検出できる最安手段だ。

ただしハッシュ単体は 真正性の証明にはならない。それには署名が必要だ。だが「自分の手元にあるファイルが配布元の出したファイルと同一である」というのは、署名検証も含む後続のすべての前提条件である。

SHA-256 とレガシーアルゴリズムの違い

ZeroTool の File Hash Checker は 5 つのアルゴリズムを 1 パスで計算する。これらは互換ではない。簡易対照表を以下に示す。

アルゴリズム出力長衝突耐性現実の用途
MD5128 bit破られている(2004)互換性チェックサム専用
SHA-1160 bit破られている(2017、SHAttered)互換性チェックサム専用
SHA-256256 bit強い現代の標準:npm registry / Docker Hub digest / GitHub Releases / Homebrew formula の sha256 / 各種 Linux ディストリのミラー
SHA-384384 bit強いTLS 1.3 一部の暗号スイートとコード署名
SHA-512512 bit強いLinux カーネル tarball、一部の BSD ports、衝突余裕を厚く取りたい場面

MD5 と SHA-1 が「破られている」とは、攻撃者が 異なる 2 ファイルで同じハッシュ値を意図的に作れる ということだ。この性質が失われると、ハッシュは「誰もこのファイルに手を入れていない」を証明できなくなる。「転送中に偶発的な破損が起きていない」ことしか言えない。これが ZeroTool が UI 上で MD5 と SHA-1 を legacy とラベリングしている理由のすべて — まだ有用な情報を返すが、「配布元が署名したファイル」を保証する役割は終わっている。

新たに方針を決めるなら SHA-256 で固定。配布元が MD5 しか公開していない場合は MD5 も算出するが、結果は「転送が無事だった」という弱いヒントとして扱い、安全保証ではないと割り切る。そして相手にはアップグレードを促す。

ブラウザはどうハッシュを計算しているのか

ツールは File.arrayBuffer() でファイルを 1 度メモリに読み込む。そこから二手に分かれる。

  • SHA-1SHA-256SHA-384SHA-512crypto.subtle.digest() に直接渡す。この呼び出しはブラウザ組み込みの暗号サブシステムへ直行し、現代の主流デスクトップブラウザではすべて OS レベルで加速される。プラットフォームがサポートする場合は CPU のハードウェア SHA アクセラレーションも使う — x86 なら Intel SHA-NI、Apple Silicon と近年の ARM チップなら ARMv8 Cryptography Extensions。
  • MD5 は Web Crypto API がそもそも提供していない。ページに組み込まれたコンパクトなパブリックドメイン MD5 実装が、同じ Uint8Array を純粋な JavaScript で処理する。同じ入力に対して SHA 系より遅く、100 MB を超えるファイルでは 5〜10 倍の差が出る。ハードウェアアクセラレーションの恩恵を受けられないからだ。

アップロード処理は一切ない。バックエンドに同期する Service Worker もない。IndexedDB への永続化もない。ファイルはタブのメモリに置かれ、リロードすれば消える。Clear を押せばそのコピーすら破棄される。

// SHA 系に対するツールの最小等価実装
async function sha256(file) {
  const buf = await file.arrayBuffer();
  const digest = await crypto.subtle.digest('SHA-256', buf);
  return Array.from(new Uint8Array(digest))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

同じ結果をシェルで欲しい場合、3 プラットフォームで大半をカバーできる。

# Linux(coreutils)
sha256sum postgresql-18.0.dmg

# macOS(BSD utils)
shasum -a 256 postgresql-18.0.dmg

# Windows(Vista 以降に標準搭載)
certutil -hashfile postgresql-18.0.dmg SHA256

出力フォーマットは異なる(Linux/macOS は連続した小文字 hex、Windows は空白入りの大文字)が、根底のハッシュ値は同じだ。ツールの照合フィールドは すべての空白文字を除去して小文字化 してから比較するので、certutil の生出力(AA BB CC …)をそのまま貼り付けても、sha256sum のトリム済み hex を貼り付けても、どちらでも ✓ を返す。

実例:Linux ディストロ ISO を検証する

直近の Debian 13 testing 週次 ISO を例に取る。ミラーページには SHA256SUMS ファイルが置かれ、ISO ごとに 1 行ずつ並ぶ。

4e3a1c...d2  debian-13.0.0-amd64-netinst.iso

日本国内の場合 JAIST や山形大学などのミラーから引くことも多いが、SHA256SUMS も同じミラーディレクトリから取ること — ハッシュだけ別ソースから持ってきて本体と突き合わせるのは、よくある自爆パターンだ。

ISO を File Hash Checker にドラッグし、デフォルトの SHA-256 のまま Compute Hashes を押す。1 行の結果が返る。SHA256SUMS から該当行の hex をコピー、照合フィールドに貼り付け、Matches SHA-256 ✓ を確認する。最近のラップトップで 700 MB の ISO なら 2 秒未満で終わる — crypto.subtle.digest の SHA-256 はそれくらい速い。

No match against any computed hash ✗ が返る場合、機械的に対処する。

  1. コピーした SHA-256 が完全な 64 文字 hex であることを再確認。途中で途切れていたり、別ファイルの行を取っていないか。
  2. 別のミラーから再ダウンロードする。一時的な転送破損が最大の原因だ。とくに弱回線やプロキシ経由ではよく起きる。
  3. ミラーが分離署名(SHA256SUMS.gpg)も公開しているなら、まずプロジェクトのリリース鍵で gpg --verify をかける。改ざんされた SHA256SUMS 上のハッシュが一致しても無意味だ — 署名のステップなしには、ハッシュは「ダウンロードが壊れていない」以上を保証しない。

この最後の点こそが、ZeroTool の File Hash Checker がハッシュ計算で範囲を区切る理由だ。署名検証には配布元の GPG または Sigstore 鍵が必要で、正しい実行場所は自分の端末上の gpg --verify または cosign verify である。秘密鍵の貼り付けを要求するブラウザツールは、はるかに信頼しにくいものになる。

ツールが解決しないエッジケース

このブラウザハッシャーが守備範囲外とする場面を列挙しておく。別の道具を使うべき判断材料に。

  • 約 1 GB を超えるファイル。ブラウザは単一の ArrayBuffer の確保を 2 GB 付近で打ち切り、それよりずっと早い段階でスワップが始まる。1 GB を超えるとツールはソフト警告を出すが、30 GB のゲームパッチはこのウィジェットの仕事ではない。sha256sum / shasum -a 256 / certutil -hashfile を使うこと。
  • ディレクトリ/アーカイブのハッシュ。ディレクトリには正規のバイトストリームがない。ツリー全体を検証したいなら、まずアーカイブ化(.tar.gz.zip)してからハッシュする。ディレクトリ単位で指紋を取りたい場合は b3sum --recursive(BLAKE3)のようなツールがある。
  • ネットワーク入力をストリーミングしながらのハッシュ。ダウンロードしながらハッシュを蓄積するのはサーバー側か CLI の仕事(curl … | sha256sum のような)。Web Crypto は完全に読み込み終わった ArrayBuffer を必要とする。
  • HMAC、パスワードハッシュ、または新しい木構造ハッシュ(BLAKE3 / SHA-3)。これらは別系統の問題だ:HMAC Generator は共有鍵付きの完全性検証、Bcrypt Generator はパスワード保管、Hash Generator は短いテキスト(パスワード、ペイロード、サンプル文字列)のハッシングを担当する。

なぜスタンドアロンのツールが多くの場面で sha256sum より勝つのか

CLI を流暢に扱う開発者は、迷わず sha256sum を叩く。だが PostgreSQL DMG、YubiKey ドライバー、Tailscale インストーラーをダウンロードする動作の多くは、ユーザーがシェルにいない、Windows 主力で WSL を入れていない、あるいは同僚を横で手伝っているという場面で起きる。ブラウザツールはこういう場面のために存在する。

  • macOS / Windows / Linux / ChromeOS で同じ操作感。
  • 何かをインストールするための管理者権限が要らない。
  • すでにディスク上にあるファイルに対して計算するので、再ダウンロード不要。
  • ドラッグ&ドロップが使える。多くの CLI にはない機能だ。
  • 期待ハッシュを貼り付けて比較できる。これは diff <(sha256sum file | cut -d' ' -f1) <(echo "expected") の暗記より親切だ。
  • 日本では特に「macOS で Homebrew 経由ではない単発バイナリ」「Windows 主力の開発者が一時的に検証したいケース」で差が出る。

明示的に 担当しない 範囲:TB 級アーカイブのストリーミングハッシュ、署名検証、CI の完全性チェックの代替。これらはパイプラインに置くべきもので、ブラウザタブで完結させるものではない。

さらに読む

  • Hash Generator — 同じアルゴリズム群を短いテキスト入力(パスワード、ペイロード、サンプル文字列)に対して使う場合。
  • HMAC Generator — 共有秘密鍵がある状況で、裸のハッシュではなく鍵付き完全性検証が必要なとき。
  • SSL Certificate Decoder — TLS エンドポイント背後の署名アイデンティティを検証する。ファイルペイロードそのものではない。
  • SubtleCrypto.digest on MDN — ツールの SHA パスが依拠する仕様文書。
  • SHAttered:実用的な初の SHA-1 衝突 — 2017 年に SHA-1 を新規セキュリティ用途から退役させた論文。