ゆるテックノート

ハッシュ値とは?

ハッシュは、データから比較に使う値を計算する仕組みです。ここでは主にセキュリティ用途の暗号学的ハッシュを扱います。内容を秘密にする暗号化とは役割が異なります。

ハッシュ関数の基本

SHA-256は入力したバイト列から256ビット(32バイト)の値を計算します。16進数では64文字です。同じバイト列とアルゴリズムなら結果は同じですが、見た目が同じ文章でも文字コードや改行が異なれば入力は変わります。

ハッシュの性質を区別する

  • 原像計算困難性:ハッシュ値に対応する入力を見つけることが難しい性質です。短いパスワードなど候補が少ない入力は、候補を計算して照合できます。
  • 第二原像計算困難性:与えられた入力と同じハッシュ値になる別の入力を見つけにくい性質です。
  • 衝突耐性:同じハッシュ値になる異なる入力の組を見つけにくい性質です。衝突が存在しないという意味ではありません。
  • 入力の小さな変更が出力の多くのビットに影響する性質は雪崩効果と呼ばれます。これだけで暗号学的な安全性は証明できません。

SHA-256を計算する

Python 3の標準ライブラリで、改行を含まない3バイトのabcを計算します。ハッシュは復号して元に戻すための方式ではありません。

import hashlib

print(hashlib.sha256(b"abc").hexdigest())
# ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

代表的なアルゴリズム

名前や出力長だけで安全性の優劣を決めず、利用する仕様と目的に合わせて選びます。

MD5

衝突への耐性が必要な署名や改ざん検知の新しい設計には使いません。偶発的な破損検出と、攻撃者による偽造への対策は区別します。

SHA-1

衝突が実証されているため、衝突耐性を必要とする新しい用途には選びません。古い仕様との互換性が必要な場合は、その仕様の移行方針を確認します。

SHA-2

SHA-256やSHA-512などの系列です。SHA-256はファイル照合などに広く使われます。ただし鍵のないハッシュだけでは、ファイルを誰が配布したかまでは証明できません。

SHA-3

SHA-2とは異なる構造を持つ標準です。SHA3-256などは固定長ですが、同じFIPS 202にあるSHAKEは出力長を指定できる別の関数です。「すべてのハッシュは必ず固定長」とは限りません。

パスワードを安全に保存する

SHA-256をそのまま使ったり、自作の繰り返し処理で保存したりせず、パスワード保存用のライブラリを使います。

ソルトと計算コストを設定する

  • 保存するパスワードごとにランダムなソルトを生成し、ハッシュと一緒に保存します。ソルトは秘密鍵ではありません。
  • Argon2idなどのパスワード専用方式を使い、処理時間とメモリ使用量を実環境で調整します。適用する規格や認証要件がある場合は、それに適合する方式を選びます。
  • 方式、ソルト、コスト設定も保存します。ライブラリの検証機能を使い、設定を更新した際は正常なログイン時などに再ハッシュします。
  • 高いコストは漏えい後の推測を遅らせますが、弱いパスワードを推測不能にはしません。ログイン試行の制限なども必要です。

ハッシュ・HMAC・暗号化の使い分け

目的に合った仕組みを選びます。

用途を比較する

攻撃者がファイルと比較用ハッシュの両方を差し替えられるなら、ハッシュ一致だけでは防げません。HMACも、共有鍵を持つ全員が生成できます。再送攻撃への対策には、認証するメッセージに時刻や一度だけ使う値を含めて検証するなど、別の設計が必要です。

目的 必要な仕組み
破損を検出する 受信ファイルのハッシュを、期待する値と照合する。
配布元も確認する 信頼できる経路の比較値、または信頼する鍵で検証できる電子署名を使う。
共有鍵を持つ相手を認証する HMACなどのメッセージ認証方式を使う。
内容を秘密にする 用途に合う認証付き暗号化を使う。ハッシュやHMACでは内容は隠れない。

関連する説明を読む

仕様・一次資料