はじめに
英語の技術動画で学ぶシリーズ。今回は ByteByteGo から、データベースにパスワードを安全に保存する方法。
System Design: How to store passwords in the database? (3:44)
動画が立てる問いは2つ。どう保存するかと、ログイン時にどう照合するか。3分台と短く、OWASP のガイドラインに沿って「ハッシュ化」と「ソルト」の2本柱で説明している。
パスワード保存とは
目標は「DBが漏れても、攻撃者がパスワードを手にできない状態にしておくこと」。
やってはいけない例として、動画はまず平文(plain text)保存を挙げる。DBに内部アクセスできる人なら誰でも見えてしまい、DBが侵害されれば全員分のパスワードがそのまま漏れる。
指針:OWASPの2つの推奨
動画が拠り所にしているのは OWASP(Open Web Application Security Project)のガイドライン。推奨は次の2つ。
| 推奨 | 一言でいうと | 防ぎたいもの |
|---|---|---|
| 1. 現代的なハッシュ関数を使う | 元に戻せない形に変換して保存する | 総当たり攻撃(brute force) |
| 2. ソルトを付ける | パスワードごとにランダムな文字列を混ぜてからハッシュする | 事前計算攻撃(pre-computation attack) |
以下、それぞれを分解する。
推奨1:現代的なハッシュ関数
ハッシュは一方向の変換(one-way function)。ハッシュ値から元のパスワードは復元できない。
そのため攻撃者がハッシュ値を盗んでも、それをそのままアプリに入力してログインすることはできない。
ポイントは「パスワード保存用に設計された関数」を選ぶこと。動画はこれをあえて"遅い"関数と表現している。
- 計算に多くのリソースを使う
- だから大量の候補を試す総当たり攻撃が割に合わなくなる
動画では具体的な関数名は挙げていない。(※動画外の補足:OWASP の Password Storage Cheat Sheet では Argon2id、scrypt、bcrypt、PBKDF2 などが挙がっている)
使ってはいけない:レガシーなハッシュ関数
逆に、MD5 や SHA-1 のような古いハッシュ関数は「速い」。
速い=総当たりで試しやすい、ということなので、パスワード保存には使うべきではないと動画は言い切っている。
| 現代的なハッシュ関数 | レガシーなハッシュ関数 | |
|---|---|---|
| 速さ | 遅い(意図的) | 速い |
| 例 | 動画では名前なし | MD5, SHA-1 |
| パスワード保存 | 使う | 使わない |
推奨2:ソルト
ソルトは、パスワードごとに作るランダムな文字列。ハッシュ計算のときにパスワードへ混ぜ込む。
なぜ要るのか。ハッシュ化だけでは「正しい方向への一歩だが不十分」だから。攻撃者は事前計算攻撃で一方向ハッシュを破れる。
- 動画が挙げる例:レインボーテーブル(rainbow table)、データベースを使った照合(database-based lookup)
- これらを使えば、パスワードを数秒で割り出せることもある
ソルトを混ぜると、同じパスワードでもユーザーごとにハッシュ値が変わる。結果として、事前に作った表が使えなくなる。
保存の流れ
- ユーザーが入力したパスワードと、ランダムに生成したソルトを組み合わせる
- その組み合わせを適切なハッシュ関数でハッシュ化する
- ハッシュ値をソルトと一緒にDBへ保存する
保存するもの = ( salt, hash(password + salt) )
ソルトは秘密ではない。ハッシュを一意にするための材料なので、平文のままDBに置いてよいと動画は明言している。
ログイン時の照合の流れ
保存の逆をたどる。
- そのユーザーのソルトをDBから取り出す
- 入力されたパスワードにソルトを付けてハッシュ化する
- 計算したハッシュ値と、DBに保存されたハッシュ値を比べる
- 一致すればパスワードは正しい
ハッシュは元に戻せないので、「復号して比べる」のではなく「同じ手順でもう一度ハッシュして比べる」のがポイント。
まとめ
パスワードは「遅いハッシュ関数 + ユーザーごとのソルト」で保存し、照合は同じ手順で再計算して比べる。これが動画の結論。
自前で認証を実装するとき、または既存システムのパスワード保存方式をレビューするときに、MD5/SHA-1 を使っていないか・ソルトがあるかを確認する、という使い方になる。
(※動画外の補足:コメント欄では、DBの外に置く追加の秘密値「ペッパー(pepper)」の話も出ている。動画本編では扱っていないので、また別途まとめたい)
覚えておきたい英単語
| 英語 | 意味 | 動画での使われ方 |
|---|---|---|
| compromised | (システムが)侵害された・乗っ取られた | If the database is compromised, an attacker could easily get all the passwords. |
| one-way function | 一方向関数(元に戻せない変換) | Hashing is a one-way function. |
| brute force attack | 総当たり攻撃 | This makes brute force attacks unattractive. |
| pre-computation attack | 事前計算攻撃(あらかじめ計算した表で照合する攻撃) | An attacker can defeat one-way hashes with pre-computation attacks. |
| rainbow table | レインボーテーブル(ハッシュ値から元の値を引くための事前計算表) | Some common attacks are rainbow tables and database-based lookups. |