はじめに
セキュリティ関係気になったので調べてみた。
簡単なパスワードのイメージはこんな感じ
昔のセキュリティでは
とりあえずパスワードをハッシュ値にしておけ!
みたいな時代があったらしいが色んな攻撃方法が出来てこれだけでは不十分らしい。
例えば
レインボー攻撃
レインボーテーブルと呼ばれる、ハッシュ値からパスワードを特定するための逆引き表を用いて、パスワードを高速に解読する手法。
こんな攻撃されたらハッシュ化してるだけやとリスクある。
現状の対策
saltの付与
ハッシュ値にするメッセージをm、ハッシュ値の関数をh(x)、saltをsとしたときに、ハッシュ値=h(m||s)として、saltを追加したメッセージをハッシュ化することで、元のメッセージの解析を難しくする手法。
saltをどうするべきかについて
(メッセージの前に付与する?後ろに付与する?saltはユーザごとに作成すべき?など)
は、いろいろな方法がありますが、計算機の進化でハッシュ値計算も時間がかからなくなってしまってきているので、しないよりした方がいいよ!という観点で深く考えないでいい。
「パスワードにはsalt(塩)を振って使いましょう」とかっていうことばあるらしい
ストレッチング
ストレッチングは関数でハッシュ値にした結果を、さらに関数でハッシュ値にするという手法
弱いパスワードや文字数が長くないパスワードは、時間をかければ総当り攻撃(ブルートフォース攻撃)で元データを推測される。この時間を事実上不可能といえる時間にするためにストレッチングを行う。何回関数を実行したらいいか?については、多くした方が解析が困難ですが毎回ログイン認証のたびに、数十回も関数を実行しているとCPUを多く消費するのでサーバスペックと相談。
この両方に対応できるのがbcrypt
bcryptが生成するハッシュ値の構造
例
$2y$10$1QVmWNzk.TsaZQLQ/zeI9OAZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG
ハッシュアルゴリズム
$2y$10$1QVmWNzk.TsaZQLQ/zeI9OAZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG
先頭の「$2y$」の「2y」は、ハッシュアルゴリズムのバージョンを示す。bcryptには2, 2a, 2b, 2x, 2yなどのバージョンがある。
ストレッチング回数
$2y$10$1QVmWNzk.TsaZQLQ/zeI9OAZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG
次に「$10$」の「10」はストレッチング回数を示します。この数字は2のn乗のn部分を示しているので、今回は2の10乗で1024回ストレッチングされています。
ソルト
$2y$10$1QVmWNzk.TsaZQLQ/zeI9OAZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG
ストレッチング回数の後の128ビット(22文字)はソルトを表す。上記例では「1QVmWNzk.TsaZQLQ/zeI9O」。
結果のハッシュ値
$2y$10$1QVmWNzk.TsaZQLQ/zeI9OAZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG
ソルトの後の184ビット(31文字)は結果のハッシュ値を示します。上記例では「AZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG」が結果のハッシュ値。