2013-02-05

パスワードハッシュ値のイテレーション回数は随時更新可能

あるユーザーが事前に設定したパスワードを入力したこと確認するための情報を安全に保管するには、保管する際に 一方向性関数 を通せばよいことは誰もがご存知だと思います。この一方向性関数をより強力 (より計算時間がかかる) なものに更新しようとする際、ユーザーからの生のパスワードが必要なのかについて議論します。ソルトの有効性については議論しません。

いまもしイテレーション回数を増やすことができるならば、パスワード用ハッシュ関数のストレッチ度を上げることでパスワードハッシュ値へのオフライン攻撃を企む攻撃者に必要となる計算能力を世の中の進歩に合わせて増やしていくことができるので、安心してユーザーのパスワードを預かることができそうです。

例えば素朴なところで f(x) = sha256(sha256(sha256(x))) (ただし x をユーザーが入力した生のパスワードとする) のように sha256 関数に n 回通すような関数を用いているとします。この関数はユーザーからの生のパスワードを得ずとも、既に n 回通したハッシュ値にさらに m 回 sha256 に通してイテレーション回数 n + m のより強固なハッシュ値にアップグレードできるので、イテレーション回数は好きなだけ更新可能と言えます。

次に既にパラメータにイテレーション回数を持っているような鍵導出関数 PBKDF2 を使う場合でも、f(x) = PBKDF2(PBKDF2(x, salt, 100), salt, 10000) のような一方向性関数を考えれば先ほどと同様に、イテレーション回数 100 から、10100 ほどにハッシュ値の強度を強化できると言えます。

残念なことに PBKDF2(PBKDF2(x, salt, 100), salt, 10000) = PBKDF2(x, salt, 10100) みたいにはならないようですが、どの一方向性関数を通したハッシュ値なのかという情報は保持するべきで (例えば $1$saltsalt$hashhashhashhashhash の形式の 1 はハッシュ関数の種類)、保持すれば関数の使い分けに問題は無いでしょう。

またもしユーザーから入力されたパスワードを既知とするならば、ユーザー認証後に好きな一方向性関数でハッシュ値を導出しなおすことができます。

リンク
エフセキュアブログ : いや、パスワードをしっかりSaltingしても十分ではない、CUDA Accelerated PBKDF2を使用すべし
本当は怖いパスワードの話(3/4) - @IT
Webアプリでパスワード保護はどこまでやればいいか
パスワード保存とソルトの話
Jun Mukai - Google+ - 昨日のパスワードとソルトの話の続き。 …

追記 (2013/2/11)
sha256(sha256(sha256(x))) よりも、salting が可能なように、hmac_sha256(hmac_sha256(hmac_sha256(x, salt), salt), salt) とする方が断然良いです。
参考 HMAC