MD5とは?ハッシュ関数の仕組み・衝突リスクと正しい使いどころ

大きなファイルをダウンロードすると、ダウンロードページに d41d8cd98f00b204e9800998ecf8427e のような謎の文字列と「MD5」という表記を見かけることがあります。これは何を意味するのでしょうか?本記事ではハッシュ関数の基本概念から始め、MD5の動作原理・セキュリティの現状、そして各シーンに適したハッシュアルゴリズムの選び方を詳しく解説します。

1. ハッシュ関数とは?

ハッシュ関数(Hash Function)とは、任意長の入力データを固定長の出力値(「ハッシュ値」「ダイジェスト」とも呼ぶ)に変換する数学的な関数です。優れたハッシュ関数は以下の性質を持ちます:

  • 決定論的:同じ入力からは常に同じ出力が得られる
  • 固定長出力:入力の長さに関係なく出力長は固定(MD5は128ビット=32桁の16進数)
  • 雪崩効果:入力の1ビットが変わると、出力の約50%のビットが変化する
  • 一方向性(原像困難性):ハッシュ値から元の入力を逆算することは計算上ほぼ不可能
  • 衝突耐性:同じ出力を生む2つの異なる入力を見つけることが困難
ハッシュ ≠ 暗号化
暗号化は可逆(正しい鍵があれば復号できる)、ハッシュは一方向(復元不可能)です。用途が根本的に異なり、混同するとセキュリティ上の重大なミスにつながります。

2. MD5の動作原理

MD5(Message Digest Algorithm 5)はRon Rivestが1991年に設計したMD4の改良版です。128ビット(16バイト)の出力を生成し、通常32桁の小文字16進数で表記されます。

2.1 処理フローの概要

  1. パディング:入力データの長さが512で割って448ビット余るよう調整し、末尾に元の長さを64ビットで付加
  2. 初期化:4つの32ビット状態値(A、B、C、D)を固定定数で初期化
  3. ブロック処理:パディング済みデータを512ビットのブロックに分割し、各ブロックに4ラウンド・計64回の非線形演算を適用
  4. 出力:最終的な4つの32ビット値を連結して128ビットのダイジェストを生成

2.2 例

同じ入力からは常に同じMD5が得られます:

MD5("") = d41d8cd98f00b204e9800998ecf8427e
MD5("hello") = 5d41402abc4b2a76b9719d911017c592
MD5("Hello") = 8b1a9953c4611296a827abf8c47804d7

「hello」と「Hello」は大文字・小文字が1文字違うだけですが、MD5値は全く異なります——これが「雪崩効果」の現れです。

3. MD5のセキュリティ上の問題

3.1 衝突攻撃(Collision Attack)

2004年、王小雲教授のチームがMD5の衝突——つまり異なる2つの入力から全く同じMD5値を生成すること——に成功しました。これは攻撃者が正規のファイルと同じMD5を持つ悪意あるファイルを作成し、整合性検証を突破できることを意味します。

2008年には研究者がMD5衝突を利用して偽のSSL証明書を作成し、現実世界での攻撃の可能性を実証しました。

3.2 レインボーテーブル攻撃

MD5の計算は非常に高速で、現代のGPUは1秒あたり数十億のMD5を計算できます。攻撃者は「平文→MD5値」の大規模な対照表(レインボーテーブル)を事前に構築し、容量と引き換えに高速でパスワードの平文を逆引きできます。

これが、現代のパスワード保存にMD5(またはSHA-1・SHA-256)を直接使ってはいけない理由です——ソルトを加えても、パスワード専用設計の関数ほど安全ではありません。

3.3 長さ拡張攻撃(Length Extension Attack)

MD5(SHA-1・SHA-256も同様)は長さ拡張攻撃に脆弱です。攻撃者は元のデータを知らなくても有効なMAC(メッセージ認証コード)を偽造できる可能性があります。SHA-3とHMAC構造はこの攻撃の影響を受けません。

4. MD5 vs 他のハッシュアルゴリズム

アルゴリズム出力長安全性速度適用場面
MD5128 bit破られている(衝突既知)非常に速い非セキュリティ用途のチェックサムのみ
SHA-1160 bit破られている(2017年に実際の衝突)速い新システムへの使用は非推奨
SHA-256256 bit安全(既知の衝突なし)中程度デジタル署名・証明書・一般的なセキュリティ用途
SHA-3可変安全(異なる設計原理)やや遅い高セキュリティ要件
bcrypt固定パスワード専用設計・ブルートフォース耐性遅い(意図的設計)パスワード保存
Argon2可変PHC 2015優勝遅い(意図的設計)パスワード保存(推奨)

5. MD5の正しい使いどころ

5.1 ✅ セキュリティ目的ではないファイル整合性の確認

ダウンロードや転送中にファイルが破損していないか確認するため(注意:悪意ある改ざんは防げません)。悪意ある改ざんが心配な場合はSHA-256を使ってください。

5.2 ✅ 重複排除とキャッシュキー

コンテンツの一意な識別子としてMD5を使い、2つのデータが同一かどうかを判定したり、キャッシュシステムのキーとして使います。セキュリティとは無関係で、MD5の決定論的な性質と速度を活用するだけです。

5.3 ✅ 非パスワード目的のデータインデックス

大量のテキストのMD5をデータベースのインデックスキーとして計算し、固定長・均等分布の特性を活かして検索効率を上げます。

5.4 ❌ パスワード保存

MD5(または任意の汎用ハッシュ関数)でパスワードを保存することは絶対に避けてください。bcrypt・Argon2・scryptなどパスワード専用設計の関数を使いましょう。

5.5 ❌ デジタル署名と証明書

MD5の衝突脆弱性により、X.509証明書署名・コード署名・偽造防止が必要なあらゆる場面での使用は不適切です。SHA-256以上を使ってください。

5.6 ❌ HMACの基礎ハッシュ

HMAC-MD5は理論上は素のMD5より安全ですが、現代システムではHMAC-SHA256への移行を推奨します。

6. MD5の計算方法

# コマンドライン(Linux/macOS)
md5sum file.txt          # Linux
md5 file.txt             # macOS

# PHP
md5('hello')             // 5d41402abc4b2a76b9719d911017c592
md5_file('file.txt')     // ファイルのMD5を計算

# Python
import hashlib
hashlib.md5(b'hello').hexdigest()

# JavaScript(crypto-jsライブラリを使用)
CryptoJS.MD5('hello').toString()

または本サイトのMD5ツールを使えば、ブラウザ上でインストール不要でテキストのMD5値を計算できます。

7. よくある質問

7.1 MD5とBase64は何が違うのですか?

MD5はハッシュ(一方向・不可逆)、Base64はエンコーディング(双方向・可逆)です。性質が根本的に異なり、混同するとセキュリティ上の問題が生じます。

7.2 ソルトを加えればMD5をパスワード保存に使えますか?

ソルトはレインボーテーブル攻撃を防げますが、MD5が速すぎるという根本的な問題は解決しません。ソルトを加えても、現代のGPUは1秒あたり数十億回の試行が可能です。bcryptかArgon2を使ってください。

7.3 「MD5衝突」とは何ですか?なぜ重要なのですか?

衝突とは、異なる2つの入力が同じMD5値を生成することです。現在では数秒でMD5衝突を生成するツールが存在し、攻撃者は正規ファイルと同じMD5を持つ悪意あるファイルを作成し、MD5検証に依存するシステムを欺ける可能性があります。

8. まとめ

MD5は優れた設計を持ち広く普及したハッシュアルゴリズムですが、暗号学的なセキュリティはすでに破られています。その限界を理解することはすべての開発者の基本知識です:非セキュリティ目的の整合性確認やデータ識別には今も有用ですが、パスワード保存・デジタル署名・悪意ある攻撃への耐性が必要な場面では使うべきではありません。そのような場面では、SHA-256(汎用)またはArgon2(パスワード)が適切な選択肢です。