PHPでは、2つの文字列が等しいかどうかを比較する必要がある場合、一般的に使用される方法はSTRCMP関数です。ただし、セキュリティ要件の増加により、PHP 5.6はセキュリティ比較のために特異的に機能HASH_Equalsを導入しました。この記事では、これら2つの機能の違いを詳細に紹介し、いくつかのシナリオでHASH_Equalsが推奨される理由を説明します。
strcmp(string $ str1、string $ str2):int
STRCMPは、辞書の順序で2つの文字列を比較するために使用されます。整数値を返します。
0は、2つの文字列がまったく同じであることを意味します
負の数は、最初の文字列が2番目の文字列よりも小さいことを示しています
正の数は、最初の文字列が2番目の文字列より大きいことを意味します
hash_equals(string $ nowned_string、string $ user_string):bool
Hash_equalsは、2つの文字列がまったく同じかどうかを比較するために特別に使用され、比較プロセスはタイミング攻撃を防ぐための安全な方法です。ブール値を返します:
真は、2つの文字列が正確に等しいことを意味します
偽は不平等なことを意味します
パスワードハッシュ、APIキー、署名などの機密データの検証などの一部のセキュリティシナリオでは、攻撃者は、比較関数の実行時間を測定することにより、文字列の同じ部分の長さを推測し、正しいキーを徐々に推測できます。通常の文字列比較関数( STRCMPなど)は、最初の異なる文字が見つかったときにすぐに戻ります。その結果、ストリングの部品長に関連する比較時間が漏れやすくなります。
Hash_equalsは、タイミング攻撃を防ぐために特別な考慮事項で設計されています。比較時間は、2つの文字列の同じ部分の長さで変化しませんが、代わりに実行時間を修正して、情報の漏れのリスクを減らします。
<?php
// 使用 strcmp 2つの文字列の比較
$known = 'securetoken123';
$userInput = 'securetoken124';
if (strcmp($known, $userInput) === 0) {
echo "正常に一致します(strcmp)";
} else {
echo "マッチが失敗しました(strcmp)";
}
?>
<?php
// 使用 hash_equals 2つの文字列の比較
$known = 'securetoken123';
$userInput = 'securetoken124';
if (hash_equals($known, $userInput)) {
echo "正常に一致します(hash_equals)";
} else {
echo "マッチが失敗しました(hash_equals)";
}
?>
上記のコードの文字列比較では、 STRCMPは最初の異なる文字ですぐに戻り、 Hash_equalsは完全な比較を実行することに注意してください。
パスワードの検証ハッシュ:ほとんどのパスワードの検証はpassword_verifyに合格しますが、自分で比較ハッシュを実装する場合は、 hash_equalsを使用することをお勧めします。
暗号化された署名を比較してください:たとえば、HMAC、JWTなど。キーを推測しないようにします。
比較セキュリティトークン:APIキー、アクセストークン、検証コードなど。
簡単に言えば、セキュリティ関連の文字列比較にはhash_equalsを使用することをお勧めします。
Hash_equalsでは、渡される2つのパラメーターが文字列であり、同じ長さであることが必要です。そうしないと、 Falseが直接返されます。
Hash_equalsを使用する前に、入力文字列が文字列タイプであり、予期しないエラーを回避するために同じ長さを確保することをお勧めします。
STRCMPは一般的に使用され、強力な文字列比較関数ですが、安全で繊細な機会には、 Hash_equalsは、時限攻撃を防止する特性のため、より適切な選択です。 Hash_equalsの正しい使用は、アプリケーションのセキュリティを効果的に改善し、潜在的な攻撃リスクを回避できます。