hash_equals

タイミング攻撃に対しても安全な文字列比較

説明

bool hash_equals(#[\SensitiveParameter]string $known_string, #[\SensitiveParameter]string $user_string)

実行している間に known_string の内容を漏らすことなく、 ふたつの文字列が等しいかどうかを調べます。

この関数は、タイミング攻撃を緩和する目的で使えます。 === を用いた通常の比較は、値が異なるかどうかや、 値が最初に異なる位置に応じて、比較に多少時間がかかります。 よって、その間に秘密の known_string の内容が漏洩してしまいます。

警告

最初のパラメータよりはむしろ、 2つ目の文字列をユーザーが指定することが重要です。

パラメータ

known_string

秘密にしておく必要がある、既知の文字列

user_string

ユーザーが指定する、比較対象の文字列

戻り値

ふたつの文字列が等しい場合に true を返します。 そうでない場合に、false を返します。

例1 hash_equals の例

<?php
$secretKey = '8uRhAeH89naXfFXKGOEj';

// $value と $signature の値はユーザが提供します。
// 例: URL内の値と、$_GET から取得した値です
$value = 'username=rasmuslerdorf';
$signature = '8c35009d3b50caf7f5d2c1e031842e6b7823a1bb781d33c5237cd27b57b5f327';

if (hash_equals(hash_hmac('sha256', $value, $secretKey), $signature)) {
    echo "The value is correctly signed.", PHP_EOL;
} else {
    echo "The value was tampered with.", PHP_EOL;
}
?>

上の例の出力は以下となります。

The value is correctly signed.

注意

注意:

指定するパラメータは両方、長さが等しくなければいけません。 違う長さの文字列が指定されると、この関数はすぐに false を返すので、 タイミング攻撃が行われた場合に既知の文字列の長さが漏洩するかもしれません。

参考

  • hash_hmac