AES 128位CTR使用PHP进行部分文件解密 [英] AES 128 bit CTR partial file decryption with PHP

查看:291
本文介绍了AES 128位CTR使用PHP进行部分文件解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这不是一个重复的帖子,因为我看到无处不在,我找不到一个答案。它关于部分解密。不完整。

This is not a duplicate post because I have looked everywhere and I can't find an answer to this. Its about partial decryption. Not full.

我对PHP有很好的了解,但对密码学知之甚少。
我知道密钥和iv的crypted文件。该文件正在解密整体,但真正的问题出现,当我尝试从中间解密部分文件。

I have a good knowledge of PHP but little knowledge about cryptography. I know the key and the iv of the crypted file. The file is decrypting fine as whole but the real issue arises when I try to decrypt the partial file from the middle.

它解密很好,当我尝试解密的第一个128kb的文件或256kb或从文件开头的任何长度。
但是当我从中间开始,它不解密,但是给出乱码输出。

It decrypts fine when I try to decrypt the first 128kb of the file or 256kb or any length from the beginning of the file. but when I start from the middle, it does not decrypt but gives gibberish output.

我将在这里发布一个文件的前100个字节的示例。

I will post here an example of first 100 bytes of the file.

加密是AES 128位CTR模式。

The encryption is AES 128 bit CTR mode.

我使用PHP的mdecrypt_generic和mcrypt_decrypt函数没有成功。

I have used both mdecrypt_generic and mcrypt_decrypt functions of PHP with no success.

使用的代码

$chunk2 = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, base64_decode($mega_key), $data, 'ctr', base64_decode($mega_iv));
echo base64_encode($data) .'<br />'. base64_encode($chunk2);

结果

9PX2fU83NF3hLc+HFdyHkqfxC4bHWKUQwQHJkNVnYbKCIQrhlHvTKtz8T3Bb0TgBkyBoGHnDCzZs3bu54KLQ8Bv0lzrTVJbzJY5msBfcy7Zi2Z/fLoMm+nvqdGPTNR0uwv45xJ8=
MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTE=

如你所见。解密后,结果是包含数字1 的文件的前100个字节。
该文件由Mega.co.nz使用JavaScript加密。根据Mega的文档,该文件已被加密,以进行部分加密/解密。

As you can see. after decryption, the result is the first 100 bytes of the file containing the digit 1 in series. The file is encrypted by Mega.co.nz using JavaScript. According to the documentation at Mega, the file has been encrypted in chunks for partial encryption/decryption.


文件加密

MEGA使用客户端加密/解密来端到端保护文件传输和存储。从客户端接收的数据被逐字存储和传输;
服务器既不解密也不重新加密,也不验证传入用户文件的加密。所有加密处理都由最终用户控制。
要允许完整性检查的部分读取,文件将被视为一系列块。为了简化服务器端处理,部分上传只能启动,
在块边界上结束。此外,部分下载只有在满足相同标准的情况下才能进行完整性检查。块边界位于
以下位置:0 / 128K / 384K / 768K / 1280K / 1920K / 2688K / 3584K / 4608K /。 (每1024 KB)/ EOF

MEGA uses client-side encryption/decryption to end-to-end-protect file transfers and storage. Data received from clients is stored and transmitted verbatim; servers neither decrypt, nor re-encrypt, nor verify the encryption of incoming user files. All cryptographic processing is under the control of the end user. To allow for integrity-checked partial reads, a file is treated as a series of chunks. To simplify server-side processing, partial uploads can only start and end on a chunk boundary. Furthermore, partial downloads can only be integrity-checked if they fulfil the same criterion. Chunk boundaries are located at the following positions: 0 / 128K / 384K / 768K / 1280K / 1920K / 2688K / 3584K / 4608K /. (every 1024 KB) / EOF

我用这个函数计算文件的块边界:

I am calculating the chunk boundaries of the file with this function:

public function get_chunks($size)
{
    $chunks = array();
    $p = $pp = 0;

    for ($i = 1; $i <= 8 && $p < $size - $i * 0x20000; $i++) {
        $chunks[$p] = $i * 0x20000;
        $pp = $p;
        $p += $chunks[$p];
    }

    while ($p < $size) {
        $chunks[$p] = 0x100000;
        $pp = $p;
        $p += $chunks[$p];
    }

    $chunks[$pp] = ($size - $pp);
    if (!$chunks[$pp])
    {
        unset($chunks[$pp]);
    }

    return $chunks;
}



我尝试单独解密第二个块,它失败。
我不能发布一个128kb的块这里明显的原因,但我会显示你的块从第二个字节开始到第100个字节。
这是使用相同代码的结果:

I have tried decrypting the 2nd chunk individually, it fails. I cannot post a 128kb chunk here for obvious reasons, but I will show you chunk starting from 2nd byte to the 100th byte. This is the result with the same code:

使用的代码

$chunk2 = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, base64_decode($mega_key), $data, 'ctr', base64_decode($mega_iv));
echo base64_encode($data) .'<br />'. base64_encode($chunk2);

结果

9fZ9Tzc0XeEtz4cV3IeSp/ELhsdYpRDBAcmQ1WdhsoIhCuGUe9Mq3PxPcFvROAGTIGgYecMLNmzdu7ngotDwG/SXOtNUlvMljmawF9zLtmLZn98ugyb6e+p0Y9M1HS7C/jnEnw==
MDK6A0kyWI3903mj+GokBGfLvHCuzITg8flodIM34gGSGtpE3pnIxxGCDhq72AijgnlBUIv5DGuAVzNoc0MR2t5SnNi281TnmtnnlvomTOWKd3HAnJTtsKCvJoHXGQLdDfbMag==

结果与 mcrypt_module_open('rijndael-128','','ctr','');

我需要部分解密文件,因为我试图为Mega编写一个开源下载管理器,支持并行连接/恢复支持。

I need to partially decrypt a file because I am trying to code an open source download manager for Mega which supports parallel connections/resume support.

我需要对文件进行即时解密以允许文件流式传输,因此在下载后解密是没有问题的。

I need to decrypt the file on the fly to allow file streaming, so decrypting after its downloaded is out of question.

在mega的网站上,他们自己的下载界面使用多个连接并以块的形式下载文件,还有另一个Web服务允许从Mega下载多个连接并恢复支持。

At mega's website, their own download interface uses multiple connections and downloads the file in chunks and there is another web service that allows downloading from Mega with multiple connections and resume support.

我需要解密部分文件支持来自浏览器/下载管理器的HTTP Range标头请求。如果范围请求落在第二或第三块中,我需要能够解密该块并将其发送到客户端,而不从头开始解密该文件。

I need to decrypt the partial file to support HTTP Range header requests from the browser/download managers. If the range request falls with in the 2nd or 3rd block I need to be able to decrypt that block and send it to the client without decrypting the file from the beginning.

是甚么可能?

推荐答案

好的,我找到了解决部分内容的解决方案。
我有这个问题,当我试图解密来自Range的部分数据(为了创建一个Web代理)。
我发现,如果我下载整个文件(从位置0这样),没有问题。
例如:

Okay, I found the solution about decrypting partial content on the fly. I had this problem when I tried to decrypt partial data from Range ( in order to create a web proxy ). I discovered that if I download whole the file (from position 0 so), there is no problem. Example :

while($_total_dled != $content_length) {
        $raw = fgets($socket, 1024);
        $data = mdecrypt_generic($this->cipher, $raw);
        echo $data;
}

但是,如果我开始从 pos x <强>(像如果我收到:范围x-),mdecrypt_generic将失败,因为它没有被执行(x-1)次。
所以我试试这个:

BUT, if I start reading the file from pos x ( like if I received : Range x-) , mdecrypt_generic will failed, because it wasn't be executed (x-1) times before. So I try this :

for($i=0;$i<$range["start"];$i++) {
     mdecrypt_generic($this->cipher, "0");
}

只需要解密一个字符(x-1)强>次。
然后,带有while循环的部分。它的工作原理。
我们可以把这个迭代与相关的计数器联系起来。

Just need to decrypt one character (x-1) times. and then, the part with the while loop. And it works. May be we can link this iteration with the related counter.

希望这将有助于人们。

这篇关于AES 128位CTR使用PHP进行部分文件解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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