暗号化・安全な通信

ハッシュ関数 (Hash Function)

約 5 分で読めます

ハッシュ関数とは

ハッシュ関数 (Hash Function) とは、任意の長さのデータを入力すると、固定長の値 (ハッシュ値、ダイジェストとも呼ぶ) を出力する関数です。同じ入力からは常に同じハッシュ値が得られますが、ハッシュ値から元のデータを復元することは計算上不可能です。この性質を「一方向性」と呼びます。

たとえば SHA-256 で hello をハッシュすると、2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 という 64 文字の 16 進数が得られます。入力が 1 文字でも変わればハッシュ値はまったく異なる値になり (雪崩効果)、元の入力を推測する手がかりにはなりません。

ハッシュ関数は暗号化とは異なります。暗号化は鍵を使って元のデータに復号できますが、ハッシュは不可逆です。この違いが、パスワード保存やデータ改ざん検知といった用途でハッシュ関数が選ばれる理由です。

主要アルゴリズムの比較

ハッシュアルゴリズムは用途と安全性によって使い分けます。

MD5 (128 ビット)
1991 年に設計。高速だが衝突耐性が破られており、セキュリティ用途には使用禁止。ファイルのチェックサム (破損検知) 程度にしか使えない。
SHA-1 (160 ビット)
2005 年に理論的な衝突攻撃が示され、2017 年に Google が実際の衝突を実証 (SHAttered)。電子証明書や Git の内部ハッシュなど一部で残存するが、新規採用は非推奨。
SHA-256 (256 ビット)
SHA-2 ファミリーの代表格。現時点で衝突攻撃は知られておらず、TLS 証明書、ブロックチェーン、ファイル検証など幅広く使われる。汎用ハッシュの標準的な選択肢。
bcrypt
パスワード保存に特化した設計。意図的に計算を遅くする「コストファクター」を持ち、GPU による高速な総当たり攻撃に耐性がある。ソルトを自動的に付与する仕組みも内蔵。

汎用的なデータ検証には SHA-256、パスワード保存には bcrypt (または Argon2) を選ぶのが現在のベストプラクティスです。MD5 と SHA-1 はセキュリティ目的では使わないでください。

パスワード保存での役割

Web サービスがユーザーのパスワードを保存する際、パスワードそのものをデータベースに格納してはなりません。万が一データベースが漏洩した場合、全ユーザーのパスワードが平文で流出するからです。

正しい方法は、パスワードをハッシュ化して保存することです。ログイン時には、入力されたパスワードを同じアルゴリズムでハッシュ化し、保存済みのハッシュ値と比較します。一致すれば正しいパスワードと判定できます。サーバー側は元のパスワードを知る必要がありません。

ただし、単純なハッシュ化だけでは不十分です。同じパスワードは同じハッシュ値になるため、攻撃者は事前に計算した「パスワード → ハッシュ値」の対応表 (レインボーテーブル) を使って、ハッシュ値から元のパスワードを逆引きできます。

この対策が「ソルト」です。ソルトとは、パスワードごとに付与するランダムな文字列で、ハッシュ化の前にパスワードに結合します。同じパスワードでもソルトが異なればハッシュ値が変わるため、レインボーテーブルが無効化されます。bcrypt や Argon2 はソルトの生成と付与を自動的に行うため、開発者が手動でソルトを管理する必要がありません。

ブロックチェーンでの利用

ブロックチェーンはハッシュ関数の特性を巧みに活用した技術です。各ブロックには前のブロックのハッシュ値が含まれており、チェーン状に連結されています。

あるブロックのデータを改ざんすると、そのブロックのハッシュ値が変わり、次のブロックに記録された「前のブロックのハッシュ値」と一致しなくなります。つまり、1 つのブロックを改ざんするには、それ以降のすべてのブロックを再計算する必要があり、ネットワーク全体の計算能力を上回らない限り事実上不可能です。

ビットコインのマイニング (Proof of Work) では、SHA-256 のハッシュ値が特定の条件 (先頭に一定数のゼロが並ぶ) を満たす入力値を見つける競争が行われています。ハッシュ関数の一方向性により、条件を満たす入力を見つけるには総当たりで試すしかなく、この計算コストがブロックチェーンの安全性を支えています。

レインボーテーブル攻撃とソルト

レインボーテーブル攻撃は、よく使われるパスワードのハッシュ値を事前に大量計算しておき、漏洩したハッシュ値と照合して元のパスワードを特定する手法です。「password123」「qwerty」「abc123」といった頻出パスワードは、主要なハッシュアルゴリズムごとにテーブルが公開されています。

  • ソルト (Salt): パスワードごとにランダムな値を付加してからハッシュ化する。同じパスワードでもソルトが異なればハッシュ値が変わるため、事前計算テーブルが使えなくなる。
  • ペッパー (Pepper): ソルトに加えて、アプリケーション全体で共通の秘密値をパスワードに付加する。データベースが漏洩してもペッパーが別の場所に保管されていれば、ハッシュ値の解読がさらに困難になる。
  • ストレッチング: ハッシュ計算を数千〜数万回繰り返し、1 回のハッシュ計算にかかる時間を意図的に増やす。bcrypt のコストファクターや PBKDF2 の反復回数がこれに該当する。

パスワードマネージャーを使って長くランダムなパスワードを生成すれば、レインボーテーブルに載っている可能性は極めて低くなります。ブルートフォース攻撃に対しても、パスワードの長さと複雑さが最大の防御です。

よくある誤解

ハッシュ化と暗号化は同じもの
暗号化は鍵を使って元のデータに復号できる可逆的な処理ですが、ハッシュ化は不可逆です。パスワード保存にはハッシュ化を使い、通信の保護には暗号化を使います。用途に応じた使い分けが重要です。
SHA-256 でハッシュすればパスワードは安全
SHA-256 は汎用ハッシュとしては優秀ですが、パスワード保存には向きません。高速すぎるため GPU で毎秒数十億回の試行が可能です。パスワード保存には bcrypt や Argon2 など、意図的に低速化されたアルゴリズムを使うべきです。
共有する
B!

関連用語

関連記事