简体   繁体   English

使用 openSSL 在 PHP 中加密(大)文件

[英]Encrypting (large) files in PHP with openSSL

我正在尝试使用 AES 加密 PHP 中的(大)文件并研究使用 Mcrypt 和 OpenSSL,问题是到目前为止我发现的所有解决方案都只加密字符串,而我尝试加密的文件会触发最大值PHP 的内存限制(不幸的是不能设置得更高),我将如何实现这一目标?

You could use CBC encryption using Mcrypt and then encrypt a segment of data at a time.您可以使用 Mcrypt 使用 CBC 加密,然后一次加密一段数据。 Make sure that the segment is x times the block size of the used cipher (eg 16 bytes for AES).确保该段是所用密码块大小的 x 倍(例如,AES 为 16 字节)。 Encrypt the segment and take the last block of the generated ciphertext and use it as IV for the next segment.加密该段并取生成密文的最后一个块并将其用作下一段的 IV。 The final segment should be PKCS#7 padded (plenty of examples out there including in the mcrypt_encrypt comments).最后一段应该是 PKCS#7 填充的(包括在mcrypt_encrypt注释中的大量示例)。

By chaining the segments together you get a ciphertext indistinguishable from a single encrypt (test your code using this information).通过将这些段链接在一起,您可以获得与单个加密无法区分的密文(使用此信息测试您的代码)。 Decryption is identical, using the ciphertext as IV.解密相同,使用密文作为IV。 To see how it works, look at the CBC encryption method:要了解它是如何工作的,请查看 CBC 加密方法:

在此处输入图片说明


EDIT: if possible you should use the OpenSSL equivalent functionality.编辑:如果可能,您应该使用 OpenSSL 等效功能。 That's not (well) documented, but you should be able to do the same using the code found in the link within the comment that Scott mentioned .这没有(很好)记录在案,但您应该能够使用Scott 提到的评论中的链接中找到的代码来做同样的事情。 Note that you should first perform everything without padding, and then for the final segment with padding .请注意,您应该首先在没有填充的情况下执行所有操作,然后使用 padding执行最后一段。

I have published two functions which encrypt and decrypt even large files with the help of openssl_encrypt() using the AES-128-CBC algorithm.我已经发布了两个函数,它们使用AES-128-CBC算法在openssl_encrypt()的帮助下加密和解密大文件。

Please refer to this openssl_encrypt() .请参考这个openssl_encrypt()

Updated answer更新答案

Encrypting big files is a hard problem as its hard to verify that no "chunk" has been tampered with.加密大文件是一个难题,因为很难验证没有“块”被篡改。

Use a library such as https://github.com/defuse/php-encryption使用诸如https://github.com/defuse/php-encryption 之类的库

\\Defuse\\Crypto\\File::encryptFile( 'in.file', 'out.file', $key ); \\Defuse\\Crypto\\File::encryptFile( 'in.file', 'out.file', $key );

-- Old answer -- -- 旧答案 --

http://www.shellhacks.com/en/Encrypt-And-Decrypt-Files-With-A-Password-Using-OpenSSL http://www.shellhacks.com/en/Encrypt-And-Decrypt-Files-With-A-Password-Using-OpenSSL

$ openssl enc -aes-256-cbc -salt -in file.txt -out file.txt.enc

to not use too much memory, you want a stream cipher.为了不使用太多内存,您需要一个流密码。 Call this in PHP with backticks `用反引号在 PHP 中调用它`

or with shell_exec或使用 shell_exec

Make sure that the variables are NOT user input (eg user cant control file.txt).确保变量不是用户输入(例如用户无法控制 file.txt)。 generate them yourself.自己生成它们。

Edit编辑

As shell exec is not available由于 shell exec 不可用

http://jeremycook.ca/2011/03/20/easy-file-encryption/ http://jeremycook.ca/2011/03/20/easy-file-encryption/

There is a solution there.那里有一个解决方案。 Though and I can't stress this enough.虽然我不能强调这一点。 Stream ciphers are hard I have not reviewed the code there fully nor do I think I am capable.流密码很难我没有完全审查那里的代码,我也不认为我有能力。 Using open SSL directly is a much better option直接使用 open SSL 是一个更好的选择

http://php.net/manual/en/filters.encryption.php http://php.net/manual/en/filters.encryption.php

Is the example code是示例代码

Using SSL on your website would take care of it for you.在您的网站上使用 SSL 会为您解决问题。 Any files that are transmitted are encrypted by the client browser, and server using the HTTPS protocol.任何传输的文件都由客户端浏览器和服务器使用 HTTPS 协议加密。

As far as storing the encrypted versions of the files I would not recommend.至于存储文件的加密版本,我不推荐。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM