我想在PHP中计算大型文件的SHA256。目前,我正在使用Amazon Glacier存储旧文件及其API来上传档案。最初,我只使用了无法访问MB大小图像的小文件。当我尝试上传超过1MB时,API响应表示我给他们的校验和与他们计算的不同。
以下是我上传文件的代码:
//get the sha256 using the file path
$image = //image path;
$sha256 = hash_file("sha256", $image);
$archive = $glacier->uploadArchive([
'accountId' => '',
'body' => "",
'checksum' => $sha256,
'contentSHA256' => $sha256,
'sourceFile' => $image,
'vaultName' => 'my-vault'
]);
错误:
AWS HTTP error: Client error: `POST https://glacier.us-west-2.amazonaws.com/vaults/70/archives` resulted in a `400 Bad Request` response:{"code":"InvalidParameterValueException","message":"Checksum mismatch: expected 9f1d4da29b6ec24abde48cb65cc32652ff589467 (truncated...)
我尝试了下面的函数来检查最终的哈希值,但是当我打印它时它似乎不是正确的哈希:
private function getFinalHash($file)
{
$fp = fopen($file, "r");
$ctx = hash_init('sha256');
while (!feof($fp)) {
$buffer = fgets($fp, 1024);
hash_update($ctx, $buffer);
}
$hash = hash_final($ctx, true); print_r($hash);exit;
fclose($fp);
}
结果哈希是这样的:ŸM¢>nÂJ½äŒ¶\Ã&RÿX“gíÖ'”IoA \ C÷× 我认为这里唯一的问题是获取文件的最终哈希值。文件大小为5.7 MB。
我认为提供校验和的方法有正确但我不知道如何使用大文件。我真的需要你的帮助。
答案 0 :(得分:0)
设法获得所需的输出,并通过以下例程验证摘要。
<?php
$fileName = isset($argv[1]) ? $argv[1] : die("Usage : php sha256.php <<filename>> <<hash>>" . PHP_EOL);
if(!file_exists($fileName))
die("FATAL : The file specified does not exists!");
$hash = isset($argv[2]) ? $argv[2] : die("Usage : php sha256.php <<filename>> <<hash>>" . PHP_EOL);
$ctx = hash_init('sha256');
echo("INFO : Reading file $fileName ...");
$file = fopen($fileName, 'r');
while(!feof($file)){
$buffer = fgets($file, 1024);
hash_update($ctx, $buffer);
}
echo(" DONE!" . PHP_EOL);
echo("INFO : Calculating SHA256 hash of $fileName ...");
$hashRaw = hash_final($ctx, false); // Here, set the $raw_output to false
echo(" DONE!" . PHP_EOL);
echo ($hash . " INPUT " . PHP_EOL);
echo ($hashRaw . " OUTPUT " . PHP_EOL);
if($hash == $hashRaw)
echo("INFO : Hash Comparison: OK!" . PHP_EOL);
else
echo("WARN : Hash Comparison: MISMATCH!" . PHP_EOL);
echo("END" . PHP_EOL);
您的问题是,您正在$raw_output
中将true
设置为string hash_final ( HashContext $context [, bool $raw_output = FALSE ] )
,这将生成输出作为原始二进制数据。将其设置为false或根本不使用它,因为它的默认值为false
(see the doc)。希望这会有所帮助。