[Youtube] System Design: How to store passwords in the database? のメモ。
パスワードを平文でDBに保存すべきではない。データを盗まれたら即アウトだから。
パスワードはハッシュ値にして保存すべき。仮にハッシュ値が漏れてしまっても復号化して元のパスワードを割り出すのは困難なため、即座に悪用されることはない。
ハッシュ化のポイント
- 最新のパスワードに適してハッシュ関数を使うこと
- 計算速度が速ければ良いわけではない
- saltを含めること
ハッシュ関数は計算によりリソースを割くようになっている遅い関数が良い。これはブルートフォース攻撃に有効。ハッシュ値計算に時間がかかれば、総当たりするのにも時間がかかり、悪用されるまでの時間を稼げるから。例えば、MD5やSHA-1は高速なのでパスワードには適していない。bcryptの方が良い。
詳しくは下記の参考リンクにかかれているが、bcryptでハッシュ化すると英大文字小文字8文字のパスワードを総当り攻撃するのに61年8ヶ月かかるとのこと。
saltも漏洩したときにすぐに悪用されるのを防ぐ目的で使われる。saltとはオリジナルの文字列に任意の文字列を加えてハッシュ化する手法。
saltがなかったら
- 同じパスワードのユーザー間でハッシュ値も同じになってしまう
- レインボーテーブルという手法で比較的簡単にハッシュ値から元の値を割り出せちゃう
saltはユーザーごとに異なる値にすべきで、保存先はDB。保存しおかないとsaltがわからなくなって、ログイン時に検証できない。
「saltとハッシュ値が一緒に流出したらどうするの?」と思ってしまうが、saltを含めていることで辞書攻撃や総当たり攻撃が必要になり解読に相当な時間がかかる。saltは各ユーザー固有の値なので、saltを考慮してレイボーテーブルを作り直す必要がある。
登録・ログイン時の処理がどうなるかというと
登録時はユーザー固有のsaltを用意し、ハッシュ化する。saltとハッシュ値をDBに保存。
ログイン時は、DBからユーザーのsaltを取得し、リクエストされた入力値とsaltからハッシュ値を計算。DBにあるハッシュ値と一致するか検証する。