web-dev-qa-db-ja.com

PHPのpassword_hash / password_verifyはどのように機能しますか?

the PHP manual のこの例では、実行するたびに異なる結果が出るのはなぜですか?

echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

そして、password_verify()は、これらすべてのハッシュが「rasmuslerdorf」に一致することを認識します。医者がはっきり言ったとしても、それは私にとって魔法のようです:

Password_hash()は、返されたハッシュの一部としてアルゴリズム、コスト、ソルトを返すことに注意してください。したがって、ハッシュを検証するために必要なすべての情報が含まれています。これにより、ソルトまたはアルゴリズム情報用の個別のストレージを必要とせずに、検証機能でハッシュを検証できます。

この機能はタイミング攻撃に対して安全です。

echo password_verify ( 'rasmuslerdorf' , '$2y$10$EMawXU7qNS4GzU2Do8bByeb7sSQZxecvmZ6mBrToxsOaY7RMAIGua' );  //=>true
echo password_verify ( 'rasmuslerdorf' , '$2y$10$0vMA2k7LxTBstI/J7clkkuZZ/XtuS1fklVuoM6sl4Fc/aj1avQa5u' ); //=>true
echo password_verify ( 'rasmuslerdorf' , '$2y$10$iuE2EzHMNONAWFKh/4Wyl.dcBxgFaNzAh32va0/gyE4ScqnNr/Uc.' ); //=>true

何が起こっている?どのようにpassword_verify()は、いくつかのクレイジーな文字列の一致が「rasmuslerdorf」であることを知っていますが、ハッカーはそうではありませんか?

8
Phung D. An

password_hash関数は、内部的に次の手順を実行します。

  1. それはあなたがそれを呼び出すたびに新鮮なランダムな塩を選びます。
  2. これは、ランダムなソルト、パスワード、およびその他のアルゴリズムパラメーター(コストファクターなど)を入力として受け取る高価なハッシュ関数を適用します。
  3. アルゴリズムパラメータ、ランダムソルト、ハッシュ出力を組み合わせて、解析して個別に回復できる出力文字列にします。

#1のランダムな選択が、同じ入力を提供しても毎回異なる出力を生成する理由です。ステップ#3からのフォーマット済み出力は、password_verifypassword_hashによって選択されたランダムなソルトを認識できるようにするものです。

12
Luis Casillas

有用な暗号化ハッシュを作成する鍵は、アルゴリズムを不可逆にすることですが、一貫して繰り返し可能にする必要があります。あれは:

  • password_hash('rasmuslerdorf')の出力だけでは、文字列_'rasmuslerdorf'_を取得できません
  • 入力_'rasmuslerdorf'_が与えられると、password_hash('rasmuslerdorf')への以前の呼び出しと同様に同じ出力を生成できます

これにより、パスワードを取得することなく、ハッシュに対するユーザーのパスワード試行をチェックできます。

繰り返し可能なハッシュを取得する最も簡単な方法は、入力のみに依存することです。したがって、password_hash('rasmuslerdorf')は常に同じ値を返します。しかし、これは攻撃者が一連の一般的なパスワードのハッシュを計算し、盗まれたデータベースで一致するものを検索できることを意味します。

したがって、代わりに、優れたハッシュアルゴリズムはsaltを追加します。これは、ランダムな文字列をパスワードに追加しただけで、毎回ハッシュを変えることができます。後でハッシュ関数を繰り返してsameの回答を得るには、保存時に使用されたソルトを知る必要があります。

これは_password_hash_が実際に出力するもので、1つの文字列に結合されます。

  • 入力を特定のソルトでハッシュした結果
  • 使用したランダム塩
  • 使用されたハッシュアルゴリズム
  • ハッシュアルゴリズムを制御するその他のオプション(たとえば、意図的にハッシュを遅くするために使用されるラウンドの数)

この出力は毎回異なるため、同じ答えが得られるかどうかを確認するには、ユーザーの入力でハッシュを繰り返すdifferent関数が必要です。これが_password_verify_の目的です。

  • 保存された文字列から、アルゴリズム、オプション、ソルトを見つけます
  • これらのパラメーターと、ユーザーがログインしようとしたパスワードを使用してハッシュアルゴリズムを実行します。
  • 結果が格納された文字列のハッシュ部分と一致するかどうかを確認します

同じアルゴリズムを同じオプションとハッシュで実行すると、結果が異なる場合、ユーザーは間違ったパスワードを入力した必要があります。

3
IMSoP