より安全にパスワードを保存するために考えること

公開日: : 最終更新日:2014/01/26 プログラム ,

知ってる人にとっては当たり前のことだろうが、あまり深く考えたことがなかったので調べてみた。

前提

パスワードは平文で保存しちゃダメ。クレジットカード番号などの情報にもダメ。

加工手段に暗号化を採用してはならない

一般的な加工手段は暗号化ではなくハッシュが用いられている。暗号化が不採用な理由は、システムの root 権限が取られた場合に復号化されてしまうから。

そのため、ハッシュ関数の中でも暗号的な特性を満たす「暗号学的ハッシュ関数」を使って得られたハッシュをデータベースに保存する。暗号学的ハッシュ関数の特性の1つに、原像計算困難性、あるいは、一方向性というものがある(ハッシュ値から元の文字列を求めることが困難という性質)。この性質をパスワードの保存に利用している。

ハッシュを用いた認証方法

ハッシュから元の文字列を求めることは困難であるため、入力されたパスワードからハッシュを計算し、その結果とデータベースに保存してある値を比較する。一致すればパスワードも一致していると解釈する。

しかし、ハッシュだから安全だとは限らない

ハッシュからは元の文字列を求めることは困難であるが、時間をかければ求めることができるため絶対に安全だとは言えない。例えば、以下のような攻撃でパスワードを解析されてしまう。

  • オフライン辞書攻撃
  • オフライン総当たり攻撃
  • レインボーテーブルによる探索

ハッシュ関数に MD5 を採用するのは控えたほうがいいが、より安全な SHA-256, SHA-512 を採用したとしても時間をかければ解析されてしまうというのが現実のようだ。

アプリケーション側が取るべき対策その1:ソルト

とは言え、パスワードはハッシュして保存することには変わらない。それにプラスして、どのような対策を取るか、という話。

ソルトは必ず採用する。

ソルト化ハッシュ = hash(パスワード + ソルト)

ソルトによる効果は以下の通り。

  • 同じパスワードを付けていてもハッシュ値が異なる
  • ハッシュ値の元となる文字列を長くすることにより、レインボーテーブル探索を妨害する

また、これらの効果を得るために、ソルトには以下の要件が必要となる。

  • ユーザーごとに異なるソルトを使う
  • ある程度の長さ(20文字程度以上)を確保する

ソルトは乱数でなくてもよい。通常、ソルトはハッシュ値とともに保存するので秘密情報ではないから。また、ある程度長さが確保できれば、ユーザ ID そのものをソルトにすることもできる(ユーザ ID を後から変更できるサイトの場合は実装に工夫が必要)。

ソルトは「レインボーテーブルによる探索」に対して効果を発揮する対策である。

アプリケーション側が取るべき対策その2:ストレッチング

一般にハッシュ関数は高速性を求められるが、この高速性は総当たり攻撃に対しては脆弱な方向に働いてしまう(総当たりに要する時間も短縮されるため)。ハッシュ保存用にわざわざ低速なアルゴリズムを開発するのも手間が掛かるので、高速なハッシュを繰り返し用いることで速度を遅くするというのが、ストレッチングの考え方になる。

ストレッチングの回数は多いほど安全になるが、サーバ負荷が増えるというデメリットもある。あまりに負荷が高くなると、認証のページを同時にアクセスすることで DoS 攻撃に悪用されるリスクも生じてしまう。

仮にストレッチングを1万回とすると、「8文字英数字のパスワード」のハッシュ値をすべて求めるのには30万時間、約34年かかることになる。数字だけ見ると十分なようにも見えるが、GPU の処理速度の向上や並列処理による時間短縮を考慮すると、決して十分安全ともいえないのが実情である。

ストレッチングは総当たり攻撃に対して効果を発揮する対策である。

現状のベストプラクティスは「ソルト+ハッシュ+ストレッチング」

あくまで現状。将来にわたって安心というわけではない。

Googleアドセンス用(PC)

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

関連記事

icatch-2015-002

Optionalから値を取り出すにはorElseGet()を使う

「Optional が値を持っていない場合のみ ◯◯ を実行する」を実装するときは Optional

記事を読む

no image

CVS でタグ間で変更があったファイルを抽出するスクリプト

今どきバージョン管理ツールに CVS を使っているところは珍しいと思うし、あまり需要はないだろうけど

記事を読む

icatch-2015-005-1

ユニットテストの偏りを防ぐ命名規則の付け方

ユニットテスト名に以下の命名規則を付けるようにして二ヶ月ぐらい経った。 正常系テストの場合: 正

記事を読む

icatch-vacuum_9060011568_mini-thumbnail

GitHub にアップされているブランチをローカルに取り込む

GitHub に限らず、会社や自分で Git のサーバを使った場合にも当てはまりますが、毎回同じこと

記事を読む

no image

GoogleGuavaのRangeを使って範囲判定を簡潔に書く

次のような判定処理を if 文で書くことがよくある。 もし 100 よりも大きければ(=大小判定

記事を読む

icatch-8587724648_24926df337_z-resized

yum のリポジトリ ATrpms を参照できるように設定する

あるツールの動作検証をしようと調べたところ、そのツールは ATrpms リポジトリが提供しているとの

記事を読む

icatch_8626992930-resized

シェルスクリプトでcdしたいパスにスペースが入っている場合の対処法

cd したいパスにスペースが入っていると、パスの先頭からスペースまでを「移動したいパス」と解釈されて

記事を読む

icatch_442682895-resized

scp コマンドを yum を使って CentOS にインストールする

小ネタです。 yum install scp ではなかったのでメモしておきます。 photo

記事を読む

no image

no space left と表示されたときの対処法

タイトルの "no space left" とは「書き込みたいけど、ディスクの飽

記事を読む

no image

IE9 のキャッシュ対策

どのようなバグだったのか POST で送信した内容を確認する画面で、最新の内容が表示されないという

記事を読む

Googleアドセンス用(PC)

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


六 × 6 =

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Googleアドセンス用(PC)

icatch-jersey_multi_pathparams
Jerseyの@PathParamはスラッシュの間に複数指定できる

http://hoge-api/user/{id}.{format}

icatch-vagrant_box_customize
VagrantのBoxファイルをカスタマイズして独自のBoxファイルを作成する

配布されている Vagrant の Box ファイルを使って検証環境を

icatch-2015-006-1
バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)

Web アプリのバリデーションチェックにアノテーションを使うことが増え

icatch-2015-005-1
ユニットテストの偏りを防ぐ命名規則の付け方

ユニットテスト名に以下の命名規則を付けるようにして二ヶ月ぐらい経った。

icatch-2015-004-1
Vagrantで起動したCentOS上のOctopressをホストOSから確認する設定

タイトルの通りだが、Vagrant を使って起動した CentOS に

→もっと見る

PAGE TOP ↑