2

PHPのセキュリティのベストプラクティスについてもっと知りたいと思っていますが、AnthonyFerraraによるpassword_hashとpassword_compatプロジェクトに出くわしました。私はそれを実装する方法を理解していると思いますが、テスト中に、パスワードハッシュの初心者の理解と矛盾する奇妙な振る舞いに出くわしました。

password_hash関数の結果をMySQLデータベースのユーザーレコードに保存し、password_verifyを使用して検証するためにそのハッシュを取得すると、期待どおりに機能します。ただし、まったく同じことを実行し、データベースからプルするのではなく、データベースからのコピー/貼り付けを介してパスワードハッシュをハードコーディングすると、password_verify関数が失敗します。

コードは以下のとおりです。

// Get the Username and password hash from the MySQL database.  GetPassTestuser routine returns an array where
//   position[0][0] is the username and position[0][1] is the password hash.
$arrUser = GetPassTestuser("mike24");
echo("User Name: ".$arrUser[0][0]."<br/>");
echo("Password hash: ".$arrUser[0][1]."<br/>");

// Run password_verify with the password hash collected from the database.  Compare it with the string "mytest"
//  (This returns true in my tests).
if (password_verify("mytest",$arrUser[0][1])){
    echo("Password verified");
} else {
    echo("Password invalid");
}
echo("<hr>Now On to our second test...<br/>");
// Now run password_verify with a string representation directly copied/pasted from the database.  This is 
//   being compared with "mytest", which in my mind should return a true value.  But it doesn't and this test
//   fails.  Not sure why.
if (password_verify("mytest","$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm")){  // String shown here is the same as value contained in $arrUser[0][1]
    echo("2nd Test Password verified");
} else {
    echo("2nd test Password invalid");
}

これは実際のコードで行うことではありませんが、違いが何であるかを理解しようとしているだけです。まったく同じハッシュが含まれていると思われる文字列変数を使用すると正常に機能するのに、ハードコーディングされていると機能しないのはなぜですか?

ありがとう!

4

3 に答える 3

5

PHPDOCから

リテラルの一重引用符を指定するには、円記号()でエスケープします。リテラルの円記号を指定するには、それを2倍にします(\)。バックスラッシュの他のすべてのインスタンスは、文字通りのバックスラッシュとして扱われます。これは、\rや\nなど、慣れている他のエスケープシーケンスが、特別な意味を持つのではなく、指定されたとおりに文字通り出力されることを意味します。

ドル記号($)が検出された場合、パーサーは可能な限り多くのトークンを取得して、有効な変数名を形成します。変数名を中括弧で囲んで、名前の終わりを明示的に指定します。

一重引用符を使用する

交換

"$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"

'$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm'

または

"\$2y\$10\$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"
于 2012-10-11T16:33:25.283 に答える
2

私のコメントに関して、私はこれが答えとしてよりうまくいくだろうと思いました:

if (password_verify("mytest",'$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm')){  // String shown here is the same as value contained in $arrUser[0][1]
    echo("2nd Test Password verified");
} else {
    echo("2nd test Password invalid");
}
于 2012-10-11T16:34:34.453 に答える
1

PHPマニュアルの文字列の章をご覧ください。つまり、ハードコードされたハッシュは、可変補間を使用したPHP文字列です。

"$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"
 ^  ^  ^

これらの変数は存在しないため、3つの通知で空白の部分文字列が作成されます。あなたは通知を見るべきでした。そうでない場合は、エラー報告の設定を確認してください。

(ヒント:変数の補間が必要な場合を除いて、すべての場所で一重引用符を使用してください。)

于 2012-10-11T16:35:30.167 に答える