如何在PHP中为大型文件计算sha256 [英] How to calculate sha256 for large files in PHP

查看:219
本文介绍了如何在PHP中为大型文件计算sha256的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想请教您有关如何在PHP中计算大文件的sha256的帮助。当前,我使用Amazon Glacier来存储旧文件,并使用它们的API上传档案。最初,我只是使用无法访问MB大小的图像的小文件。当我尝试上传超过1MB的内容时,API响应说我给他们的校验和与他们计算的结果不同。

I would like to ask your assistance on how to calculate sha256 of large files in PHP. Currently, I used Amazon Glacier to store old files and use their API to upload the archive. Initially, I just used small files that cannot reach to MB-sized images. When I tried to upload more than 1MB, the API response said that the checksum I gave to them is different from what they had calculated.

这是我上传的代码文件:

Here is my code to upload the file:

//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...)

我尝试了如下所示的函数来检查最终的哈希值,但打印时似乎不是正确的哈希值:

I tried the function like below to check for the final hash but it seems it's not the right hash when I print it:

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ÿXgíÖ'„ IoA\C÷×

阿玛zon Glacier API文档显示了如何按规定计算校验和:

The Amazon Glacier API documentation shows how to compute the checksum as stated:


对于每1 MB的有效载荷数据块,计算SHA-256哈希。最后一块数据可以小于1 MB。例如,如果要上载3.2 MB的存档,则需要为前三个1 MB数据块中的每一个计算SHA-256哈希值,然后计算其余0.2 MB数据的SHA-256哈希值。这些哈希值形成树的叶子节点。

For each 1 MB chunk of payload data, compute the SHA-256 hash. The last chunk of data can be less than 1 MB. For example, if you are uploading a 3.2 MB archive, you compute the SHA-256 hash values for each of the first three 1 MB chunks of data, and then compute the SHA-256 hash of the remaining 0.2 MB data. These hash values form the leaf nodes of the tree.

我认为提供校验和与正确方法有关,但是我不知道如何使用PHP处理大型文件。

I think there has something to with the correct way in providing the checksum but I don't know how I should do it with large files using PHP. I really need your help regarding this one.

推荐答案

冰川有其自己的计算SHA256-TREE-HASH的方式。
这里有PHP上的有效代码。
此函数返回根据需要从1MB部件创建的SHA256哈希。

Glacier have theirs own way to count SHA256-TREE-HASH. Here you have working code on PHP. This function returns SHA256 hash created from 1MB parts as they want. It works perfect for me, even for large or small files.

private function getFinalHash($path, $MB = 1048576)
{
    $fp = fopen($path, "rb");
    $hashes = [];
    while (($buffer = fread($fp, $MB))!=="") {
        $hashes[] = hash("sha256", $buffer, true);
    }
    if(count($hashes)==1){
        return bin2hex($hashes[0]);
    }
    while(true){
        $hashes_new = [];
        foreach($hashes as $k => $hash){
            if ($k % 2 == 0) {
                if(isset($hashes[$k+1])){
                    $hashes_new[] = hash("sha256", $hash.$hashes[$k+1], true);
                }
            }
        }
        if(count($hashes)>2 && count($hashes) % 2 != 0){
            $hashes_new[] = $hashes[count($hashes)-1];
        }
        if(count($hashes_new)>1){
            $hashes = $hashes_new;
        }else{
            fclose($fp);
            return bin2hex($hashes_new[0]);
        }
    }
}

这篇关于如何在PHP中为大型文件计算sha256的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆