ハッシュ関数は、データの整合性検証またはパスワード検証を実行する際に非常に一般的なツールです。ただし、ハッシュ比較( ==または===など)を使用しても、潜在的なハッシュ競合を予防し、効果的に検出することはありません。セキュリティを改善するために、PHPは2つの機能を提供します: Hash_finalとHash_equalsは、開発者がハッシュ操作をより安全に処理するのに役立ちます。
この記事では、これら2つの機能の使用を紹介し、実用的な例を使用して、それらを使用してハッシュ衝突検出を実現する方法を示します。
HASH_FINALは、 HASH_INITとHASH_UPDATEを使用してステップバイステップハッシュ計算を作成するときの最後のステップです。最終的なハッシュ値を返します。
例:
<?php
$context = hash_init('sha256');
hash_update($context, 'hello');
$hash = hash_final($context);
echo $hash;
ここでは、 Hash_initを使用してSHA-256のハッシュコンテキストを初期化し、 Hash_Updateを使用してデータをHashに追加し、最後にHash_Finalを使用して最終的なハッシュ結果を取得します。
Hash_equalsは、2つのハッシュ値を安全に比較するために使用されます。 ==を直接使用するのとは異なり、文字列の比較が早期に終了することによって引き起こされるタイミング攻撃を防ぐことができます。タイミング攻撃は、操作に必要な時間を測定することにより、機密情報を指定する攻撃方法です。
例:
<?php
$knownHash = hash('sha256', 'known_value');
$userInputHash = hash('sha256', $_POST['input']);
if (hash_equals($knownHash, $userInputHash)) {
echo '正常に一致します!';
} else {
echo 'マッチが失敗しました。';
}
ここで、ユーザーが入力した値が正しい値の一部にすぎない場合でも、 HASH_EQUALSはバイトバイトを完全に比較して、比較プロセス中に時差を漏らしないようにします。
ユーザーによって送信されたデータがハッシュ上の既存のデータと競合するかどうかを検出する必要があるとします(つまり、異なるデータが同じハッシュ値を生成します)。これを行うことができます:
hash_init 、 hash_update 、およびhash_finalを使用して、既存のデータのハッシュを計算します。
同じ方法でユーザーデータのハッシュを計算します。
Hash_equalsを使用して、2つのハッシュ値を比較します。
サンプルコード:
<?php
// 既存のデータをシミュレートします
$existingData = 'Original content';
$context1 = hash_init('sha256');
hash_update($context1, $existingData);
$existingHash = hash_final($context1);
// ユーザーがサビされたデータ
$userData = $_POST['user_data'];
$context2 = hash_init('sha256');
hash_update($context2, $userData);
$userHash = hash_final($context2);
// ハッシュ値を比較します
if (hash_equals($existingHash, $userHash)) {
echo 'ハッシュ競合が検出されました!データは同じか、同じハッシュ値を生成する場合があります。';
} else {
echo '未ハッシュ競合が検出されました。';
}
知らせ:
検出されたのと同じハッシュ値は、データが同じであるためかもしれませんが、理論的にはまれなハッシュ衝突によるものである可能性があります。したがって、この検出方法は、データの一貫性を判断するためにハッシュに完全に依存するのではなく、防御または検証により適しています。
hash_finalとhash_equalsを使用して、ハッシュを安全に計算して比較するだけでなく、タイミング攻撃を防ぎ、潜在的なハッシュ競合をある程度検出することもできます。セキュリティを含むシナリオでは、単純な文字列比較の代わりにこれらのツールを使用することをお勧めします。
たとえば、実際のアプリケーションでは:
アップロードされたファイルの整合性を確認します
パスワードを確認する( password_hashとpassword_verifyで使用)
インターフェイスコールの署名を検出します
これらの機能はすべて、セキュリティを改善するために使用できます。
もっと知りたい場合は、公式のPHPドキュメントをチェックすることをお勧めします。