PHPの hash_equals 関数とは?なぜ == や === を使わないのか?

hash_equals
は PHP において、2つの文字列が等しいかを安全に比較するための関数です。特にパスワードのハッシュや署名の検証などで使われます。==
や ===
といった通常の比較演算子とは異なり、タイミング攻撃(Timing Attack)を防ぐために設計されています。
なぜ ==
や ===
を使わないのか?
==
や===
は文字列を比較する際、最初に違う文字が見つかった時点で処理を終了します。そのため比較にかかる時間は、文字列の先頭から何文字目で違いが見つかるかによって変わります。- 攻撃者は比較にかかる時間の差を測定し、文字列の一部を推測できてしまう可能性があります。これがタイミング攻撃です。
タイミング攻撃(時系列攻撃)とは?
タイミング攻撃とは、プログラムの処理時間の微妙な違いを利用して、秘密情報(パスワードや暗号鍵など)を推測する攻撃手法です。例えば、文字列の比較処理で、最初に異なる文字が見つかるまでの時間が長いほど、入力が正解に近いことを意味します。
攻撃者は高精度な時間計測を行い、繰り返し処理時間を観察・分析することで、少しずつ秘密情報の内容を推測していきます。このため、処理時間に差が出る比較方法はセキュリティリスクとなります。
hash_equals
はどう防ぐのか?
- 比較処理の時間が常に一定になるよう設計されているため、部分的な一致でも時間差が生じません。
- これにより、攻撃者は時間の差から情報を得ることができず、安全に比較できます。
例
$hash1 = hash('sha256', 'password123');
$hash2 = hash('sha256', 'password124');
// 通常の比較(安全でない)
if ($hash1 === $hash2) {
echo "一致";
} else {
echo "不一致";
}
// 安全な比較
if (hash_equals($hash1, $hash2)) {
echo "一致";
} else {
echo "不一致";
}
まとめ
hash_equals
はタイミング攻撃を防止するための安全な比較関数です。==
や===
は比較時間が文字列によって異なるため、安全ではありません。- パスワードのハッシュや署名、トークンなどの安全に関わる文字列の比較に必ず使うべきです。
関連記事