パスワードの保存とハッシュ化
パスワードを平文で保存してはいけない
サービスの [[認証と認可]] で使うパスワードを、データベースにそのまま(平文で)保存するのは重大な設計ミスです。データベースが漏えいした瞬間に全利用者のパスワードが流出し、同じパスワードを使い回している他サービスへのなりすましログイン(パスワードリスト攻撃)につながります。
そこでパスワードはハッシュ化して保存するのが鉄則です。
ハッシュ化とは
ハッシュ化は、元のデータから固定長の値(ハッシュ値)を計算する一方向の変換です([[電子署名とハッシュ]])。
- 同じ入力からは常に同じハッシュ値が得られる
- ハッシュ値から元のパスワードを逆算することはできない
ログイン時は「入力されたパスワードをハッシュ化し、保存済みのハッシュ値と比較」します。サーバーは元のパスワードを知らないままでも認証できるわけです。
なお、[[暗号化の基礎]] で扱う暗号化は鍵があれば復号できる双方向の変換です。「元に戻せない」ハッシュ化とは目的が異なり、パスワード保存にはハッシュ化を使います。
ソルトとストレッチング
単純なハッシュ化だけでは、よく使われるパスワードのハッシュ値を事前計算した表(レインボーテーブル)と突き合わせる攻撃が成立します。そこで2つの工夫を加えます。
| 工夫 | 内容 | 効果 |
|---|---|---|
| ソルト | 利用者ごとに異なるランダム値をパスワードに付けてからハッシュ化 | 事前計算表が無効になり、同じパスワードでも別のハッシュ値になる |
| ストレッチング | ハッシュ計算を意図的に何千回も繰り返す | 総当たり攻撃にかかる時間を大幅に引き延ばす |
実務では、これらを組み込んだパスワード専用のハッシュ関数(bcrypt、Argon2 など)を使います。高速な汎用ハッシュ関数(MD5 や SHA-256 単体)をパスワード保存に使うのは、総当たりに弱いため不適切です。
初学者向けポイント
- 「パスワードを忘れたら再発行しかできない」サービスは正しい実装です。運営者にも元のパスワードは分からないからです
- 逆に「あなたのパスワードは○○です」とメールで送ってくるサービスは平文保存の疑いがあります
- 自作のハッシュ処理を書かず、bcrypt / Argon2 などの実績あるライブラリを使いましょう
- パスワードが漏れても [[多要素認証]] があれば突破されにくくなります。ハッシュ化とセットで導入を検討しましょう
関連技術とのつながり
- [[暗号化の基礎]] — 「戻せる」暗号化と「戻せない」ハッシュ化の違いを押さえる
- [[認証と認可]] — パスワード認証の安全性を支える土台
- [[多要素認証]] — パスワード漏えい時の最後の砦
- [[電子署名とハッシュ]] — ハッシュ関数そのものの性質を詳しく知る
Q: パスワードの保存方法として正しいのはどれ?
- [ ] 平文のままデータベースに保存する
- [ ] 鍵で復号できるように暗号化して保存する
- [x] ソルトを付けてハッシュ化して保存する
解説: ハッシュ化は一方向の変換で元に戻せないため、漏えい時の被害を抑えられます。ソルトで事前計算攻撃も防ぎます。
Q: ソルトの役割はどれ?
- [x] 利用者ごとに異なる値を混ぜ、事前計算表による攻撃を無効化する
- [ ] ハッシュ計算を高速化する
- [ ] パスワードを暗号化して復号可能にする
解説: ソルトにより同じパスワードでも利用者ごとに異なるハッシュ値になり、レインボーテーブルが使えなくなります。
Q: パスワード保存に適したハッシュ関数はどれ?
- [ ] MD5(高速な汎用ハッシュ関数)
- [x] bcryptやArgon2(パスワード専用のハッシュ関数)
- [ ] Base64(エンコード方式)
解説: bcrypt や Argon2 はソルトとストレッチングを組み込み、総当たり攻撃に時間がかかるよう設計されています。