Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best approach to encrypt big files with php

I'm developing a project in php where it's needed to encrypt files uploaded by users. This files could be from 1mb to 200mb more or less. Searching on the web, I came to the conclusion that the best way to do it was dividing files in chunks of, example, 4096 bytes. So I encrypt every chunk and append it to the full encrypted file. I'm actually using mcrypt and AES-256 encryption in CBC mode.

So, my questions are: 1) I have to create a new initial vector for every chunk, or can I get the last 16bytes of the last block of a previous chunk as the initial vector of the first block of the current chunk? This will result in having just one iv to append at the beginning of the encrypted file, and not one iv for every chunk to append before the encrpyted chunk.

2) In order to add a HMAC authentication. This question is linked to the previous one. Should I add it for the whole file or individually for every chunk. In this case, doing it for the whole file is a problem since it is usually added at the beggining of the file, and I cannot calculate the hmac until the encrypted file is complete.

3) Related to this. For file download, is it a good idea to decrypt (in chunks) and send file to the user simultaneously or is it better to decrypt first and send later?

Thanks

like image 363
Sam Lowry Avatar asked Apr 23 '13 17:04

Sam Lowry


1 Answers

You should encrypt the file stream and let PHP handle everything. In particular encryption filters combined with stream_filter_append to do what you want. Then you would just read chunks of the plaintext file and write them to the output file stream. The filter causes the encryption to happen.

This way you aren't reinventing the wheel and are using code that has likely been audited for security issues.

For hmac, most libraries let you keep adding data to the hmac until you call finalize or something like that. Then you would read in chunks of ciphertext, add them to the hmac. Repeat until the entire ciphertext has been added to the hmac and finalize it.

Or, install openssl on the server and call openssl functions from within PHP. You could use an authenticated cipher mode, etc.

like image 84
mikeazo Avatar answered Sep 16 '22 15:09

mikeazo