暗号ハッシュの基礎と実務活用ガイド:設計原理・代表的ハッシュ関数・パスワード保護のベストプラクティス
暗号ハッシュとは
暗号ハッシュ(cryptographic hash)は、任意長の入力データを固定長の短い値(ダイジェスト、ハッシュ値)に一方向的に変換する関数のことです。入力がわずかに変わるだけで出力が大きく変わる(アバランチ効果)性質を持ち、元のデータをハッシュ値から実用的に復元できないように設計されています。暗号学的に安全なハッシュ関数は、整合性検証やデジタル署名、パスワード保護、メッセージ認証など幅広い用途で使われます。
暗号ハッシュの基本的性質
- 決定性:同じ入力は常に同じハッシュを出力します。
- 固定長出力:入力長に依らず出力は一定のビット長(例:SHA-256は256ビット)です。
- 効率性:計算は高速で効率的に行えること。
- 一方向性(Pre-image resistance):ハッシュ値から元の入力を見つけることが実用的に不可能であること。nビット出力なら理想的には約2^nの計算が必要。
- 第二原像抵抗(Second pre-image resistance):ある入力に対して同じハッシュを持つ別の入力を見つけることが難しいこと(理想的には2^nの計算)。
- 衝突耐性(Collision resistance):異なる2つの入力が同じハッシュになる「衝突」を見つけることが難しいこと。nビット出力では誕生日攻撃により理想的には約2^(n/2)の計算量。
- アバランチ効果:入力のわずかな変化が出力を大きく変える。
代表的なハッシュ関数と歴史
- MD5:1990年代に広く使われたが、衝突が実用的に発見されており、整合性やデジタル署名用途では既に非推奨。
- SHA-1:米国標準。長らく使われたが、2017年にGoogleとCWIが公表した「SHAttered」攻撃などにより衝突が現実的になり、非推奨。
- SHA-2(SHA-224/256/384/512 等):現在広く使われる。十分な出力長(例:SHA-256は256ビット)により高い安全性が提供されている。
- SHA-3(Keccak):SHA-2とは異なるスポンジ構造を採用した標準。設計が根本的に異なるため、耐性の多様化として選択される。
ハッシュ関数の内部構造(代表的な設計)
- Merkle–Damgård 構造:入力をブロックに分割して逐次圧縮する方式。多くの古典的なハッシュ(MD5、SHA-1、SHA-2)がこの構造を採用。長さ拡張攻撃に対して脆弱となることがある。
- スポンジ関数(Sponge):Keccak(SHA-3)のように吸収(absorb)と絞り出し(squeeze)操作を持つ構造。Merkle–Damgårdとは異なる性質があり、長さ拡張攻撃に対する強さなど利点を持つ。
主要な攻撃手法と注意点
- 衝突攻撃:誕生日のパラドックスに基づき、nビットの出力では約2^(n/2)の計算で衝突が見つかる可能性がある。したがって実用的な安全性を得るには十分な出力長が必要(例:256ビット出力は衝突耐性が高い)。
- 第一原像攻撃/第二原像攻撃:特定の入力から元のメッセージや別のメッセージを見つける攻撃。理想的にはそれぞれ2^nの困難さ。
- 長さ拡張攻撃:Merkle–Damgård 構造の関数では、ハッシュ(h(m)) と元のメッセージ長等の情報から h(m || pad || m2) を計算される恐れがある。HMAC のような構成はこれを防ぐ。
- サイドチャネル/実装脆弱性:ハッシュ関数自体が安全でも、実装のタイミングやメモリの扱いにより情報が漏れることがある。
実務での使われ方(ユースケース)
- データ整合性検証:ファイルの改ざん検出やダウンロードの整合性確認にハッシュが使われる。
- デジタル署名:大きなデータをそのまま署名する代わりにハッシュを署名することで効率化。署名対象がハッシュであるため、ハッシュの衝突耐性が重要。
- メッセージ認証(HMAC):鍵付きハッシュ(HMAC)により、メッセージの認証と整合性検証を行う。HMAC は長さ拡張攻撃に対して安全。
- パスワード保存:生パスワードを直接保存するのではなく、ソルトとともにハッシュ(できれば専用のKDF)を保存する。詳細は下記。
- ブロックチェーンとマークルツリー:トランザクションの整合性証明やブロックのチェーン化にハッシュが利用される。ハッシュの一方向性と衝突耐性がチェーンの安全性に直結。
パスワード保存のベストプラクティス
単にSHA-256のような汎用ハッシュをパスワードにかけるだけでは不十分です。推奨される対策は以下の通りです。
- ソルト(salt)を使用:ユーザーごとにランダムなソルトを付与してからハッシュ処理を行うことで、同一パスワードのハッシュ一致やレインボーテーブル攻撃を防止します。
- ストレッチング(反復):ハッシュ計算を多数回(あるいは時間・メモリコストを大きくする)行い、総当り攻撃のコストを増やす。
- パスワード専用KDFを使用:bcrypt、scrypt、Argon2など、パスワード保護向けに設計された関数を利用する。Argon2はメモリ負荷をかけられるためGPUやASICに対する耐性が高い。
- レート制限と多要素認証:総当り攻撃への対策として認証試行の制限やMFAを組み合わせる。
例:PythonでSHA-256を計算する簡単な一行(実運用でのパスワード保存にはKDFを使うこと):import hashlib; hashlib.sha256(b"password").hexdigest()
実務上の推奨と禁止事項
- 禁止:MD5やSHA-1をセキュリティ用途(デジタル署名、ファイル整合性、パスワード保存)で使わない。
- 推奨:データ整合性や署名ではSHA-2(例:SHA-256)かSHA-3を利用。パスワード保存にはArgon2/bcrypt/scryptなどのKDFを使用。
- HMAC:メッセージ認証にはHMAC(例:HMAC-SHA256)を使う。HMACは鍵付きであり、長さ拡張攻撃の影響を避ける。
- 将来性:量子コンピュータの影響は主に公開鍵暗号に深刻だが、ハッシュ関数の第一原像攻撃コストを平方根程度に削るGroverの影響を考慮すると、ハッシュ出力長に余裕を持たせる(例えば現行の256ビット程度は量子の影響を考えても実務上安全域があるとされるが、選択は慎重に)。
具体例:ブロックチェーンとマークルツリーでの利用
ブロックチェーンではトランザクション集合をマークルツリーにまとめ、ルートハッシュをブロックヘッダに入れることで効率的な整合性検証を実現します。各ノードは自分の持つ部分だけを検証することで全体の一貫性を確認できます。ここでもハッシュの衝突が破壊的な影響を与えるため、強力なハッシュが使われます(BitcoinはSHA-256を2回適用した形式などを用いる)。
まとめ
暗号ハッシュは、情報セキュリティの基礎的かつ不可欠な技術です。正しい理解と適切な選択(用途に応じた関数やKDFの採用、ソルトやストレッチングの実装)はシステム全体の安全性に直結します。一方で、MD5やSHA-1のように理論的・実用的に破られた関数もあり、常に最新の攻撃研究や標準勧告を参照してアルゴリズムを更新していくことが重要です。
参考文献
- FIPS 180-4: Secure Hash Standard (SHS) — NIST (SHA-2)
- FIPS 202: SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions — NIST
- RFC 2104: HMAC — Internet Engineering Task Force (IETF)
- SHAttered: Practical collision for SHA-1 (Google/CWI)
- OWASP Password Storage Cheat Sheet
- scrypt: Password-Based Key Derivation — Tarsnap (scrypt paper)
- Argon2 specification — Password Hashing Competition
- Bitcoin: A Peer-to-Peer Electronic Cash System — S. Nakamoto (例:ブロックチェーンでのハッシュ利用)
- Merkle–Damgård construction — Wikipedia(参考)
- Sponge function — Wikipedia(参考、Keccakの設計原理)


