Best way to encrypt large files with php

I am developing a project in php where it needs to encrypt files uploaded by users. These files can be from 1 to 200 mb more or less. Searching the Internet, I came to the conclusion that the best way to do this is to divide the files into pieces, for example, 4096 bytes. Therefore, I encrypt each fragment and add it to the full encrypted file. I actually use mcrypt and AES-256 encryption in CBC mode.

So my questions are: 1) Do I need to create a new initial vector for each fragment, or can I get the last 16 bytes of the last block of the previous fragment as the initial vector of the first block of the current fragment? This will result in the fact that only one iv will be added at the beginning of the encrypted file, and not one iv for each fragment that must be added before the executable fragment.

2) To add HMAC authentication. This question is related to the previous one. Should I add it for the whole file or separately for each fragment. In this case, doing this for the whole file is a problem, since it is usually added at the beginning of the file, and I cannot calculate hmac until the encrypted file is complete.

3). To download files, is it recommended to decrypt (in pieces) and send the file to the user at the same time, or is it better to first decrypt and send it later?

thanks

+7
source share
2 answers

You must encrypt the file stream and let PHP handle everything. In particular, the encryption filters combined with stream_filter_append to do what you want, then you just read the fragments of the plaintext file and write them to the output file stream. The filter causes encryption.

This way you are not reinventing the wheel and using code that was probably tested for safety.

For hmac, most libraries allow you to add data to hmac until you name finalize or something like that. Then you read the fragments of the ciphertext , add them to hmac. Repeat until all text will not be added to hmac and complete it.

Or, install openssl on the server and call openssl functions from PHP. You can use authenticated encryption mode, etc.

+4
source

I had an almost identical problem. Here is the solution I found out.

<?php $filecrypt = new filecrypt(); class filecrypt{ var $_CHUNK_SIZE; function __construct(){ $this->_CHUNK_SIZE = 100*1024; // 100Kb } public function encrypt($string, $key){ $key = pack('H*', $key); if (extension_loaded('mcrypt') === true) return mcrypt_encrypt(MCRYPT_BLOWFISH, substr($key, 0, mcrypt_get_key_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB)), $string, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB), MCRYPT_RAND)); return false; } public function decrypt($string, $key){ $key = pack('H*', $key); if (extension_loaded('mcrypt') === true) return mcrypt_decrypt(MCRYPT_BLOWFISH, substr($key, 0, mcrypt_get_key_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB)), $string, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB), MCRYPT_RAND)); return false; } public function encryptFileChunks($source, $destination, $key){ return $this->cryptFileChunks($source, $destination, $key, 'encrypt'); } public function decryptFileChunks($source, $destination, $key){ return $this->cryptFileChunks($source, $destination, $key, 'decrypt'); } private function cryptFileChunks($source, $destination, $key, $op){ if($op != "encrypt" and $op != "decrypt") return false; $buffer = ''; $inHandle = fopen($source, 'rb'); $outHandle = fopen($destination, 'wb+'); if ($inHandle === false) return false; if ($outHandle === false) return false; while(!feof($inHandle)){ $buffer = fread($inHandle, $this->_CHUNK_SIZE); if($op == "encrypt") $buffer = $this->encrypt($buffer, $key); elseif($op == "decrypt") $buffer = $this->decrypt($buffer, $key); fwrite($outHandle, $buffer); } fclose($inHandle); fclose($outHandle); return true; } public function printFileChunks($source, $key){ $buffer = ''; $inHandle = fopen($source, 'rb'); if ($inHandle === false) return false; while(!feof($inHandle)){ $buffer = fread($inHandle, $this->_CHUNK_SIZE); $buffer = $this->decrypt($buffer, $key); echo $buffer; } return fclose($inHandle); } } ?> 

Using:

 <?php $key = '3da541559918a808c2402bba5012f6c60b27661c'; // Your encryption key $filecrypt->encryptFileChunks('I-still-loooove-hula-hoop.gif', 'encrypted.gif', $key); $filecrypt->decryptFileChunks('encrypted.gif', 'decrypted.gif', $key); ?> 
+1
source

All Articles