PHP方法逐块执行AES加密以节省内存使用量

时间:2015-01-31 04:49:06

标签: php memory-management encryption cryptography aes

让我解释一下我的困境。在我的PHP脚本中,我需要能够加密上传到我的网站的文件。我选择使用AES-256加密和CBC(Cipher-block chaining)操作模式。

最初我发现了一个非常有前途的功能,它可以做到这一点,它会像这样工作:

//Just the encryption part
$fileData = file_get_contents($serverFilePath);
$encData = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $binKey,
            $fileData,
            MCRYPT_MODE_CBC, 
            $binIV);

上述方法效果很好,除了一个主要问题:我在共享主机帐户上托管我的网站,并且您看到mcrypt_encrypt方法需要将数据一次性输入 em>作为二进制字符串。如果我加密的文件足够大,那就成了问题。在这种情况下,mcrypt_encrypt失败,我的脚本终止,用户看到一个空白的白页......哎呀!

之后我在error_log中收到以下消息:

  

PHP致命错误:允许X字节的内存大小耗尽(尝试过   在blah-blah中分配Y字节)

显然,通过在共享主机上运行,​​我的脚本没有所有可用的RAM,但即使它可以访问更多RAM,仍然可能存在加密文件大小超过所有可用RAM的情况,需要将其内容加载到二进制字符串中。

(顺便说一下,当我尝试加密一个200 MB的文件时,上面的方法失败了,而今天的标准并没有那么大。)

因此我的问题/困境:

是否有方法只对一个明文块执行AES加密(没有CBC或任何其他操作模式,只有普通的AES),如果是这样,我可以do CBC myself?如果是,我可以通过逐块加密来编写自己的方法,从而避免mcrypt_encrypt函数的陷阱而不将整个文件加载到RAM中。

任何建议都会受到赞赏吗?

1 个答案:

答案 0 :(得分:2)

您可以通过简单地使用mcrypt_encrypt的ECB模式而不是CBC模式来模拟单个AES块加密,然后自己执行CBC。 ECB模式基本上是无国籍的。在CBC模式下,没有来自最后一个加密块的传播。它只是在每个块上单独应用AES。

根据您的流读取方式,使用CBC加密块可能更容易或更高效。您仍然可以在文件的块上使用您的方法进行加密。然后,您将使用最后一个密文块作为下一个块的IV。