在 PHP 中,hash_final 函数是用来完成一个散列上下文(由 hash_init 创建)的最后一步,返回计算好的哈希值。它属于 PHP 的哈希扩展,通常与 hash_init、hash_update、hash_update_stream 和 hash_update_file 配合使用。
那么,当我们用 hash_final 来计算哈希值时,不同的数据格式(比如字符串、二进制数据、文件流等)会被如何处理呢?这篇文章就来详细讲讲。
我们先看一个最基本的例子:
<?php
$context = hash_init('sha256');
hash_update($context, 'Hello World');
$hash = hash_final($context);
echo $hash;
?>
这个代码片段会输出字符串 Hello World 的 SHA-256 哈希值(以十六进制表示)。
注意:
hash_update 接收的第二个参数是字符串。
无论你提供什么类型(只要可以转为字符串),最终都是作为字节序列处理的。
当你传入字符串(无论是 ASCII 还是 UTF-8 编码),PHP 会直接按字节序列处理。
例如:
hash_update($context, "abc"); // 处理的是 '61 62 63' 三个字节
注意:多字节字符(如中文)也是按照其底层字节序列进入哈希计算的,而不是按照“字符”粒度。
如果你传入的是二进制数据,例如通过 file_get_contents 获取的二进制流,也是直接按字节喂入:
$data = file_get_contents('https://gitbox.net/image.png');
hash_update($context, $data);
这里的 $data 可能包含 \0(空字节)、高位字节等,PHP 都不会进行任何过滤或转义,完全照原样进入哈希计算。
如果要对大文件计算哈希,推荐使用 hash_update_stream:
$fp = fopen('https://gitbox.net/largefile.zip', 'rb');
$context = hash_init('sha256');
hash_update_stream($context, $fp);
$hash = hash_final($context);
fclose($fp);
这里,文件内容会分块读取并喂入散列上下文,避免一次性加载整个文件到内存。
如果你直接想对文件计算哈希,可以用 hash_file,但如果要用 hash_* 函数族,就需要:
$context = hash_init('sha256');
hash_update_file($context, 'https://gitbox.net/document.pdf');
$hash = hash_final($context);
hash_update_file 会自动打开文件、读取其内容并更新上下文。
hash_final 只是把已经积累的数据做最后处理。
数据进入上下文前(hash_update、hash_update_stream、hash_update_file)已经被以 字节序列 形式读取,不关心原始的“数据类型”。
你需要确保传入的数据是你想要哈希的内容(特别是编码或二进制安全问题)。