PHPでは、 hash_final関数は、インクリメンタルハッシュコンテキストを完了し、最終的なハッシュ値を返すために使用されるツールです。通常、大規模なデータまたはストリーミングデータのハッシュ計算を処理するために、 Hash_init 、 hash_updateなどの関数と組み合わせて使用されます。ただし、多くの開発者は、 hash_finalを使用する場合、いくつかの一般的な問題に遭遇します。この記事では、これらの問題を詳細に分析し、ソリューションを提供します。
hash_finalの定義は次のとおりです。
string hash_final ( HashContext $context [, bool $raw_output = FALSE ] )
$コンテキスト: hash_initによって作成されたハッシュコンテキスト。
$ raw_output : trueに設定されている場合、rawバイナリデータを出力します。それ以外の場合、出力小文字の16進文字列。
簡単な例:
$context = hash_init('sha256');
hash_update($context, 'hello');
$finalHash = hash_final($context);
echo $finalHash;
現象:
Hash_finalが呼び出されると、関連する$コンテキストが無効になります。たとえば、同じコンテキストを再度使用しようとする場合:
$context = hash_init('sha256');
hash_update($context, 'hello');
$final1 = hash_final($context);
$final2 = hash_final($context); // 間違い!
警告またはエラーが発生します。
解決:
コンテキストを再利用する必要がある場合は、 hash_finalの前にhash_copyに電話してください。
$context = hash_init('sha256');
hash_update($context, 'hello');
$contextCopy = hash_copy($context);
$final1 = hash_final($context);
$final2 = hash_final($contextCopy);
現象:
多くの人は、$ raw_output = trueが実際にバイナリを返すことを無視して、デフォルトで文字列出力のみを取得します。 Echoを使用して直接出力すると、Carled Codeが取得されます。
$context = hash_init('sha256');
hash_update($context, 'hello');
$final = hash_final($context, true);
echo $final; // ごみコードが表示される場合があります
解決:
読み取り可能なコンテンツを表示するには、 bin2hexまたはbase64_encodeを使用できます。
$final = hash_final($context, true);
echo bin2hex($final);
現象:
大型ファイルまたはビッグデータストリームにHashを使用する場合、 Hash()を使用すると、多くのメモリが直接消費されます。
$hash = hash('sha256', file_get_contents('largefile.dat'));
解決:
hash_init + hash_updateを使用してストリーミングします。
$context = hash_init('sha256');
$handle = fopen('largefile.dat', 'rb');
while (!feof($handle)) {
$data = fread($handle, 8192);
hash_update($context, $data);
}
fclose($handle);
$finalHash = hash_final($context);
現象:
同じ入力データは、他の言語(Python、node.jsなど)でPHPで計算されたハッシュ値と矛盾しています。
解決:
確認する:
入力エンコードは一貫しています(UTF-8対UTF-16)。
追加のラインブレークまたはスペースがあるかどうか。
同じ方法で計算されました(元のエンコードされたテキスト)。
例:PHPを使用してUTF-8エンコードされた文字列のSHA-256ハッシュを計算します。
$context = hash_init('sha256');
hash_update($context, mb_convert_encoding($input, 'UTF-8'));
$finalHash = hash_final($context);
現象:
URLのハッシュ検証の場合、正規化は無視され、同じアドレスに対して異なるハッシュが生じます。
$url1 = 'https://gitbox.net/page';
$url2 = 'https://gitbox.net/page/';
解決:
計算前にURLを正規化します。
function normalizeUrl($url) {
$parsed = parse_url($url);
$scheme = $parsed['scheme'] ?? 'http';
$host = $parsed['host'] ?? '';
$path = rtrim($parsed['path'] ?? '/', '/');
return "$scheme://$host$path";
}
$context = hash_init('sha256');
hash_update($context, normalizeUrl('https://gitbox.net/page/'));
$finalHash = hash_final($context);