安全なパスワードハッシュ
この節では、なぜハッシュ関数を使ってパスワードを守るのかについての理由と、 ハッシュ処理を効率的に行う方法について説明します。
- なぜ、アプリケーションのユーザーが登録したパスワードをハッシュしなければならないのですか?
-
パスワードのハッシュは、最も基本的なセキュリティ要件のひとつです。 ユーザーからパスワードを受け取るアプリケーションを設計するときには必ず考慮しなければなりません。 ハッシュしなければ、パスワードを格納したデータベースが攻撃を受けたときにパスワードを盗まれてしまいます。 それは即時にアプリケーションが乗っ取られることにつながるし、 もしそのユーザーが他のサービスでも同じアカウント・同じパスワードを使っていればさらに被害が大きくなります。
ユーザーのパスワードにハッシュアルゴリズムを適用してからデータベースに格納しておくと、 攻撃者が元のパスワードを知ることが難しくなります。 とはいえ、パスワードのハッシュ結果との比較は可能です。
しかし、ここで注意すべき点は、パスワードのハッシュ処理はあくまでもデータベースへの不正アクセスからの保護にすぎず、 アプリケーション自体に不正なコードを注入される攻撃からは守れないということです。
- よく使われるハッシュ関数である md5() や sha1() は、なぜパスワードのハッシュに適していないのですか?
-
MD5 や SHA1 そして SHA256 といったハッシュアルゴリズムは、 高速かつ効率的なハッシュ処理のために設計されたものです。 最近のテクノロジーやハードウェア性能をもってすれば、 これらのアルゴリズムの出力をブルートフォースで(力ずくで)調べて元の入力を得るのはたやすいことです。
最近のコンピュータではハッシュアルゴリズムを高速に「逆算」できるので、 セキュリティ技術者の多くはこれらの関数をパスワードのハッシュに使わないよう強く推奨しています。
- よく使われるハッシュ関数では不適切だというのなら、 パスワードをどうやってハッシュすればいいのですか?
-
パスワードをハッシュするときに検討すべき重要な二点は、 その計算量とソルトです。 ハッシュアルゴリズムの計算コストが増えれば増えるほど、 ブルートフォースによる出力の解析に時間を要するようになります。
PHP には、 使うアルゴリズムを指定してハッシュを実行できる関数がふたつ組み込まれています。
まず最初のハッシュ関数は crypt() で、これはネイティブで数種のハッシュアルゴリズムに対応しています。 この関数を使うときには、選択したアルゴリズムが使用可能なことが保証されています。 PHP には各アルゴリズムのネイティブ実装が含まれているので、 仮にシステムがサポートしていない場合でもそのアルゴリズムを使えるのです。
もうひとつのハッシュ関数は hash() で、 これは crypt() よりもさらに多数のアルゴリズムやその亜種に対応しています。 しかし、 crypt() が対応しているアルゴリズムのいくつかには未対応です。 Hash 拡張モジュールは PHP に同梱されていますが、コンパイル時に無効化することもできます。 したがって、常に使えるとは限りません。一方 crypt() は PHP のコアに含まれているので、いつでも使えます。
パスワードのハッシュ用として推奨するアルゴリズムは Blowfish です。 これは MD5 や SHA1 に比べて圧倒的に計算量が多く、それでいてスケーラブルだからです。
- ソルトとは?
-
暗号理論におけるソルトとは、ハッシュ処理の際に追加するデータのことです。 事前に計算済みのハッシュとその元入力の対応表 (レインボーテーブル) で出力を解析される可能性を減らすために利用します。
端的に言うと、ソルトとはちょっとした追加データです。 これをつけるだけで、ハッシュをクラックするのが劇的に難しくなります。 事前に計算済みのハッシュとその元入力を大量にまとめた表が、オンラインで多数公開されています。 ソルトを使えば、そのハッシュ値がこれらの表に含まれている可能性を大きく減らすことができます。