在PHP 中, hash_final是一個與hash_init和hash_update搭配使用的重要函數,主要用於生成哈希摘要(也就是簽名),用於校驗數據的完整性。本文將詳細講解如何正確使用hash_final來生成簽名,並確保消息在傳輸或存儲過程中的完整性。
hash_final是PHP 提供的哈希擴展中的一個函數,用於完成一個分步的哈希運算並返回結果。它的基本工作流程如下:
使用hash_init初始化一個哈希上下文。
使用hash_update向上下文中追加要哈希的數據(可以多次調用以處理大數據塊)。
使用hash_final獲取最終的哈希值(簽名)。
這種分步方式特別適合處理大文件或流式數據,因為你不需要一次性加載整個內容到內存中。
我們來看一個簡單的例子,模擬對一段消息進行簽名:
<?php
$message = '這是一段需要簽名的消息';
$algo = 'sha256';
// 初始化哈希上下文
$context = hash_init($algo);
// 更新哈希上下文,可以分多次添加數據
hash_update($context, $message);
// 獲取最終的簽名(摘要)
$signature = hash_final($context);
// 輸出簽名
echo "簽名: " . $signature . "\n";
?>
在這個例子中,我們使用sha256算法生成消息的摘要。輸出的是十六進制編碼的哈希值,這個值可以用來在接收端驗證消息的完整性。
僅生成簽名是不夠的,關鍵是如何驗證簽名。一個完整的流程通常包含以下步驟:
1??發送端:
生成簽名。
將消息和簽名一起發送給接收端。
2??接收端:
接收到消息。
使用相同算法重新生成消息的簽名。
比較接收到的簽名和計算出的簽名是否一致。
代碼示例(接收端驗證):
<?php
$received_message = '這是一段需要簽名的消息';
$received_signature = '发送端提供的簽名';
$algo = 'sha256';
// 重新计算簽名
$context = hash_init($algo);
hash_update($context, $received_message);
$calculated_signature = hash_final($context);
// 比较簽名
if (hash_equals($received_signature, $calculated_signature)) {
echo "消息完整,未被篡改。\n";
} else {
echo "警告:消息可能已被篡改!\n";
}
?>
?注意:使用hash_equals比較簽名而不是直接用== ,可以防止時間攻擊。
假設你要讓用戶從https://gitbox.net/download/file.zip下載一個文件,並提供哈希值供校驗,可以這樣做:
<?php
$file = 'file.zip';
$algo = 'sha256';
// 打開文件流式讀取
$context = hash_init($algo);
$handle = fopen($file, 'rb');
while (!feof($handle)) {
$data = fread($handle, 8192);
hash_update($context, $data);
}
fclose($handle);
// 获取文件的簽名(哈希值)
$hash = hash_final($context);
echo "下載鏈接: https://gitbox.net/download/file.zip\n";
echo "文件哈希(用於校驗完整性): $hash\n";
?>
下載者可以用相同算法計算下載後的文件哈希值,確保與提供的值一致,從而驗證文件是否完整、未被篡改。