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

公開日: : 最終更新日: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

関連記事

20140811-00

64ビット版のCentOSをVMwareにインストールできない場合の対処法

Linux で検証したい作業が多かったので VMware に検証環境を作りました。OS は Cent

記事を読む

icatch-back-scratcher_3553512020_mini-thumbnail

Sublime Text3 で JavaScript を書くために設定したプラグインとキーバインド

プロフィール にもあるように、ボクは Java をメインとしたプログラマです。 IDE には Ecl

記事を読む

icatch_5623339500-resized

Bundler を使ってプロジェクト用の Gem をインストールして Gemfile をバージョン管理ツールに登録するまでの流れ

Bundler を使い始める人向けにまとめた次の記事を書きました。 CentOSにRubyのBu

記事を読む

icatch-2015-002

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

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

記事を読む

icatch_442682895-resized

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

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

記事を読む

icatch-vagrant_box_customize

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

配布されている Vagrant の Box ファイルを使って検証環境を構築することが多くなってきた。

記事を読む

icatch-sublimetext_9222613858_mini-thumbnail

Sublime Text3 のインストール直後に行った設定メモ

突発的に自宅のマシンにインストールしてあった Sublime Text2 を 3 にアップデートしま

記事を読む

icatch-9214710040_822a4c3456_z-resized

ロードアベレージを監視するシェルスクリプトを作成してみた

このブログを運用している Linux サーバの負荷が高い状態になってました。 何か被害にあったとかで

記事を読む

icatch-markdown_14bd207bd7_mini-thumbnail

Markdown記法のテキストに書いたソースコードをシンタックスハイライトするプラグイン

SublimeText3 で拡張子が md のファイルを開いたときに、文章中に書かれたプログラムのソ

記事を読む

icatch_2385618390-resized

Linuxでmp3をお手軽に結合する

このブログを運用している Linux サーバで radiko.jp から番組を mp3 に録音して個

記事を読む

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 ↑