セキュアハッシュ関数 完全ガイド:原理・安全性・主要アルゴリズムと実務での運用ポイント

セキュアハッシュ関数とは何か — 概要と目的

セキュアハッシュ関数(cryptographic hash function)は、任意長の入力データを固定長のビット列(ダイジェスト)に変換する一方向性関数で、データの整合性検証や署名、パスワード保護、メッセージ認証など幅広い暗号用途で使われます。一般的なハッシュ関数と異なり、「セキュア」と呼ばれるためには暗号的な安全性を満たす必要があります。

要求される基本的性質

  • 一方向性(Preimage resistance):あるハッシュ値から元の入力を見つけるのが計算上困難であること(第一事前像耐性)。
  • 第二事前像耐性(Second-preimage resistance):特定の入力メッセージに対して同じハッシュ値を持つ異なるメッセージを見つけるのが困難であること。
  • 衝突耐性(Collision resistance):任意の2つの異なるメッセージが同じハッシュ値を持つ「衝突」を見つけるのが計算上困難であること(理想的には難度は2^(n/2)、nは出力ビット長)。
  • 効率性:ハッシュ計算は高速であり、実用的に利用できること。
  • 決定性:同じ入力なら常に同じ出力を返すこと。

出力長と安全性の関係

理論的には出力長がセキュリティ性に直結します。nビット出力のハッシュでは、単純な総当たりでは第一事前像攻撃が約2^n回、衝突攻撃は誕生日パラドックスにより約2^(n/2)回の計算が必要と見積もられます。したがって、今日の多くの用途では少なくとも256ビット相当(SHA-256 等)が推奨されています。

代表的なアルゴリズムと現状

  • MD5:脆弱。衝突が実用的に作成可能であり、暗号用途では廃止済み。
  • SHA-1:160ビット出力。理論的に弱点が指摘されており、実際に2017年に実用的な衝突(Shattered)が生成されました。現在は多くの用途で非推奨。
  • SHA-2(SHA-224/256/384/512):FIPS標準で広く使われている。SHA-256/SHA-512が代表的で、2024年時点では広範な実用攻撃は報告されていません(ただし長期的な安全余裕を考慮し適切な出力長を選ぶこと)。
  • SHA-3(Keccak):スポンジ構造を用いるNIST標準の別系統の関数。Merkle–Damgård構造で生じる長さ拡張攻撃に対する耐性など構造上の違いがあります。
  • BLAKE2 / BLAKE3:BLAKEは高速かつ安全性を重視した設計で、BLAKE2は実務でよく使われます。BLAKE3は並列化に優れた後継で、高速・低レイテンシを実現します。

歴史的な脆弱性と教訓

MD5やSHA-1の弱体化から得られる教訓は多く、単に「ハッシュを使えば安全」という誤解を避けることが重要です。特に衝突が実現されると、ファイルの改竄や偽署名、認証バイパスなど致命的な脅威が生じます。実際、MD5に基づく証明書偽造や、SHA-1の衝突実証(GoogleとCWIによる Shattered)は実務面でのリスクを示しました。

攻撃手法の代表例

  • 総当たり(Brute force):出力長に依存する単純な探索。
  • 誕生日攻撃(Birthday attack):衝突探索の計算量を約2^(n/2)に抑える手法。
  • 長さ拡張攻撃(Length extension):Merkle–Damgård構造のハッシュ(例:古いSHA系)で、ハッシュ値と長さ情報からハッシュを延長できることがある。HMACのような設計はこれを防ぎます。
  • 構造的攻撃:内部圧縮関数やメッセージスケジューリングの弱点を突く解析(例:現代の衝突攻撃)。

用途別の注意点とベストプラクティス

セキュアハッシュ関数を使う際は用途ごとの注意が重要です。

  • データ整合性/署名/TLS等のプロトコル:SHA-2やSHA-3、BLAKE2など標準かつ現状で安全性が確認された関数を使い、SHA-1やMD5は避ける。署名や証明書ではアルゴリズムの寿命を見越した選択をする(例:署名アルゴリズムの推奨リストを参照)。
  • パスワードハッシュ:一般的なセキュアハッシュ関数(SHA-256 など)をそのままパスワード保存に使うのは誤り。高速であるためブルートフォースに弱い。代わりに PBKDF2、scrypt、Argon2 のような専用の鍵導出・メモリハード関数を用い、必ずランダムなソルト(各ユーザー毎の一意値)を使い、必要であれば「pepper(サーバー側秘密値)」を導入する。
  • メッセージ認証(MAC):単純にハッシュ(m || k)のような使い方は避け、HMAC(Hash-based Message Authentication Code)や認証付き暗号(AEAD)を用いる。HMACは長さ拡張攻撃から安全に保護する設計です。
  • 構造化用途(ブロックチェーン、Gitなど):ハッシュの用途に合わせて出力長とアルゴリズムを選ぶ。既存システムのハッシュが弱体化した場合は移行計画(例:GitのSHA-1からSHA-256移行)を立てること。

実装でよくある落とし穴

  • パスワードにソルトを使わない、またはソルトを固定してしまう。
  • 高速ハッシュ(SHA-256など)をそのままパスワード保存に使う。
  • 不適切な乱数(擬似乱数生成器)でソルトやpepperを生成する。
  • ハッシュ出力を単純に切り詰めることで安全性を弱める(短くすると衝突しやすくなる)。
  • ハッシュのみで完全性を担保しようとし、認証やアクセス制御を怠る。

運用上の推奨事項

  • 新規設計では SHA-2(例えば SHA-256)か SHA-3、もしくは BLAKE2/BLAKE3 を選ぶ。用途に応じて出力長を決める。
  • パスワード保護には Argon2(特に最新版)や scrypt を優先し、パラメータ(メモリ量、反復回数、並列度)を定期的に見直す。
  • 既知の脆弱アルゴリズム(MD5、SHA-1)からの移行計画を持つ。証明書や署名など長期保存が想定される場合は保守的に上位のアルゴリズムを選ぶ。
  • ライブラリは信頼できる実装(OS/プラットフォームの標準ライブラリや広く監査された暗号ライブラリ)を使い、独自実装は避ける。
  • プロトコル設計では認証付き暗号(AEAD)やHMACを利用し、ハッシュだけに頼らない。

将来動向とまとめ

セキュアハッシュは暗号基盤の基本部材ですが、アルゴリズムの安全性は時間とともに変化します。実務では標準(NIST等)やコミュニティの勧告に従い、脆弱性報告や実用攻撃(衝突実証など)をウォッチして置換・移行を迅速に行うことが重要です。用途に応じた適切なアルゴリズム選択、パスワードには専用関数、ハッシュをそのまま認証に使わない、といった基本ルールを守ることで安全性を大幅に高められます。

参考文献