Шифрование больших файлов с помощью OpenSSL в PHP
Шифрование больших файлов имеет свои особенности. Так, например, файл, размер
которого превышает несколько сотен мегабайт не удастся зашифровать сразу весь —
так как на это просто не хватит памяти. Поэтому в таких случаях файлы приходиться
шифровать небольшими блоками — кусками.
В примере ниже показано как зашифровать большой файл с помощью OpenSSL в PHP.
<?php
// размер блока ("куска"), шифруемого файла
define('FILE_BLOCK_SIZE', 10240);
/**
* @param $source Путь к шифруемому файлу + название самого файл
* @param $dest Путь куда будет сохранен зашифрованный файл + название самого файла
* @param $key Ключ шифрования
*/
function encrypt_file(string $source, string $dest, string $key)
{
$cipher = 'aes-256-cbc'; // шифр
$ivLenght = openssl_cipher_iv_length($cipher); // длина вектора инициализации
$iv = openssl_random_pseudo_bytes($ivLenght); // генерирует псвевдо-случайную строку - вектор инициализации
$fd_source = fopen($source, 'rb'); // открываем исходный файл в режиме бинарного чтения
$fd_dest = fopen($dest, 'w'); // открываем новый файл в режиме записи
// записываем вектор инициализации в начало файла
// он нам понадобиться при расшифровке
fwrite($fd_dest, $iv);
// читаем исходный файл пока не достигнем конца файла
while ( !feof($fd_source) ) {
// из исходного файла берем "кусок"
$plaintext = fread($fd_source, $ivLenght * FILE_BLOCK_SIZE);
// шифруем этот "кусок"
$ciphertext = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
// ????
//$iv = substr($ciphertext, 0, $ivLenght);
fwrite($fd_dest, $ciphertext);
}
// закрываем файлы
fclose($fd_source);
fclose($fd_dest);
}
/**
* @param $source Полный путь к зашифрованному файлу
* @param $dest Путь, куда будет сохранен расшифрованный файл + название самого файла
* @param $key ключ шифрования
*/
function decrypt_file(string $source, string $dest, string $key)
{
$cipher = 'aes-256-cbc';
$ivLenght = openssl_cipher_iv_length($cipher);
$fd_source = fopen($source, 'rb');
$fd_dest = fopen($dest, 'w');
// извлекаем сохраненный вектор инициализации из начала файла
$iv = fread($fd_source, $ivLenght);
// по "кусочкам" расшифровываем файл
while ( !feof($fd_source) ) {
$ciphertext = fread($fd_source, $ivLenght * (FILE_BLOCK_SIZE + 1));
$plaintext = openssl_decrypt($ciphertext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
//$iv = substr($plaintext, 0, $ivLenght);
fwrite($fd_dest, $plaintext);
}
fclose($fd_source);
fclose($fd_dest) ;
}
Вызываем так:
<?php
$src_file = "новый_видеокурс.avi";
$dest_file = "новый_видеокурс.avi.encrypted";
$key = "самыйсильныйпароль";
// зашифровываем
encrypt_file($src_file, $dest_file, $key);
// расшифровываем
decrypt_file($src_file, $dest_file, $key);
Источник