在很多應用中,驗證文件的完整性是非常重要的。特別是當你需要下載或上傳文件時,確保文件沒有被篡改或損壞是非常關鍵的。 PHP 提供了多種方法來進行文件哈希校驗,其中hash_update_stream和hash_equals()是兩種常用的函數組合。
本文將介紹如何使用hash_update_stream函數來逐步讀取文件併計算哈希值,然後利用hash_equals()函數對比計算出的哈希值與預期的哈希值,從而驗證文件的完整性。
hash_update_stream :該函數是用於計算數據流的哈希值。在處理大文件時,通過將文件分塊讀取並逐步更新哈希值,可以有效地避免內存溢出的問題。
hash_equals :這是一個用於比較兩個哈希值的安全函數。它可以防止時序攻擊,比直接使用==或===更加安全,因為它不會因哈希值的不同長度而暴露時間差。
假設你已經有一個文件和一個預期的哈希值,你想通過以下步驟來驗證文件的完整性。
首先,我們需要打開待驗證的文件。我們可以使用fopen()打開文件進行讀取。
$file = fopen('path/to/your/file', 'rb');
然後,使用hash_init()初始化一個哈希上下文。這里以sha256為例,當然你也可以使用其他哈希算法(如md5 、 sha512等)。
$hashContext = hash_init('sha256');
我們將文件分塊讀取,通過hash_update_stream()函數將每個塊的數據更新到哈希上下文中。
while (!feof($file)) {
$data = fread($file, 8192); // 讀取8KB數據塊
hash_update_stream($hashContext, $data);
}
在文件讀取完畢後,使用hash_final()來獲取計算出的文件哈希值。
$fileHash = hash_final($hashContext);
最後,我們使用hash_equals()來安全地比較計算出的文件哈希值與預期的哈希值,確保文件沒有被篡改。
$expectedHash = '預期的哈希值'; // 你可以從服務器或其他安全的地方獲得這個哈希值
if (hash_equals($fileHash, $expectedHash)) {
echo "文件完整,哈希值匹配!";
} else {
echo "文件損壞或被篡改,哈希值不匹配!";
}
以下是完整的示例代碼:
<?php
// 打開文件
$file = fopen('path/to/your/file', 'rb');
if (!$file) {
die('无法打開文件');
}
// 初始化哈希上下文
$hashContext = hash_init('sha256');
// 逐步讀取文件并更新哈希值
while (!feof($file)) {
$data = fread($file, 8192);
hash_update_stream($hashContext, $data);
}
// 獲取文件的哈希值
$fileHash = hash_final($hashContext);
// 預期的哈希值
$expectedHash = '預期的哈希值'; // 例如,'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
// 比較哈希值
if (hash_equals($fileHash, $expectedHash)) {
echo "文件完整,哈希值匹配!";
} else {
echo "文件損壞或被篡改,哈希值不匹配!";
}
// 關閉文件
fclose($file);
?>