質問: ### 質問 PHPにおいてpassword_hash()はなぜ安全なのでしょうか? 暗号アルゴリズム、ストレッチング回数、ソルトなどパスワードの解析における情報は全てそのハッシュに収められています。従って、password_verify()単独で真偽判定が可能であり、それは本当に便利なのですが、その分、ハッシュが漏洩した際に十分安全ではないと言えるのではないでしょうか?
回答: パスワードの保存にハッシュ値を用いるのは、「もっと良い方法がない」からというのが単純化した理由です。 たとえば、暗号鍵を安全に保存でき、外部に漏洩しないことが確実であるならば、ハッシュ値よりも暗号化して保存した方が確実です。 しかし、そもそもパスワードを保護する理由というのは、なんらかの理由でパスワード情報が漏洩した後の保護をしたいわけなので、パスワード情報は漏洩するが鍵は漏洩しないというシナリオは描きにくいわけです。絶対にできないわけでもありませんが、ハードウェアセキュリティモジュール(HSM)を使用するような高価な方法となりますし、サーバーに侵入されているという前提では、HSMとて絶対とまでは言えません。 このため、暗号鍵のような秘密情報を安全に保存できるという前提をさわやかにあきらめた方法が、pashword_hash等で採用されている方法で、これが現在の主流です。 まず、ハッシュ値というのは、平文からハッシュ値を求めるのはある程度高速にできるが、ハッシュ値から平文に戻す手段はありません。ただし、パスワードの場合は、総当りで求める方法があり、password_veryしながら順にしらべていけば、理論的にはいつかは平文パスワードが分かります。 しかし、その「いつか」が100年後であれば、実質的には問題ないわけです。もちろん、1000年後とか1万年後であれば、さらに安全です。 なので、password_hashで用いられているアルゴリズムは、「計算に時間が掛かる」という性質を持っています。単に計算量が多いと言うだけでは不十分です。ハッシュアルゴリズムは比較的単純なのでGPUによる高速計算ができる場合が多いのですが、パスワード保存用のハッシュアルゴリズムには、GPUによる高速計算がやりにくいような工夫がされています。 一方、ハッシュ値の計算に秘密情報を混ぜることもできますが、著名なアプリケーション等ではあまり見かけない方法です...といいつつ、私が本を書いた時にはこの方法を採用しました。当時はまだ password_hash関数がなかったからそうしましたが、今は、password_hashを使うことをお勧めします。