Лучший способ шифрования больших файлов с помощью php

Я разрабатываю проект в php, где он необходим для шифрования файлов, загружаемых пользователями. Эти файлы могут быть от 1 до 200 мб больше или меньше. Поиск в Интернете я пришел к выводу, что лучший способ сделать это – делить файлы на куски, например, 4096 байт. Поэтому я шифрую каждый фрагмент и добавляю его в полный зашифрованный файл. Я фактически использую шифрование mcrypt и AES-256 в режиме CBC.

Итак, мои вопросы: 1) Мне нужно создать новый начальный вектор для каждого фрагмента, или я могу получить последние 16 байт последнего блока предыдущего фрагмента в качестве начального вектора первого блока текущего фрагмента? Это приведет к тому, что в начале зашифрованного файла будет добавлено только один iv, а не один iv для каждого фрагмента, который должен быть добавлен перед блоком encrpyted.

2) Чтобы добавить аутентификацию HMAC. Этот вопрос связан с предыдущим. Должен ли я добавить его для всего файла или отдельно для каждого фрагмента. В этом случае выполнение этого для всего файла является проблемой, поскольку оно обычно добавляется в начале файла, и я не могу вычислить hmac до тех пор, пока зашифрованный файл не будет завершен.

3) В связи с этим. Для загрузки файлов рекомендуется ли расшифровать (в кусках) и отправить файл пользователю одновременно или лучше сначала дешифровать и отправить позже?

благодаря

Вы должны зашифровать поток файлов и позволить PHP обрабатывать все. В частности, фильтры шифрования в сочетании с stream_filter_append выполняют то, что вы хотите. Затем вы просто прочитаете фрагменты файла открытого текста и напишите их в поток выходных файлов. Фильтр вызывает шифрование.

Таким образом, вы не изобретаете колесо и используете код, который, вероятно, был проверен на предмет безопасности.

Для hmac большинство библиотек позволяют добавлять данные в hmac до тех пор, пока вы не назовете finalize или что-то в этом роде. Затем вы читаете фрагменты зашифрованного текста , добавляете их в hmac. Повторяйте до тех пор, пока весь зашифрованный текст не будет добавлен в hmac и не будет завершен.

Или, установите openssl на сервере и вызовите функции openssl из PHP. Вы можете использовать аутентифицированный режим шифрования и т. Д.

У меня была почти одинаковая проблема. Вот решение, которое я узнал.

<?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); } } ?> 

Применение:

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