Как предотвратить ошибку mcrypt_encrypt () для шифрования файла большего размера?

0

Я пытаюсь зашифровать загруженный файл с помощью PHP-скрипта, подобного этому. Он отлично работает с меньшими файлами, но когда я пытаюсь загрузить тестовый файл размером 49,2 МБ (что не так уж важно по сегодняшним стандартам), следующая причина: моя страница php отображает пустую страницу, завершая скрипт:

$binaryFileData = file_get_contents($serverFilePath);
$binaryEncFile = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $binaryKey, $binaryFileData, MCRYPT_MODE_CBC, $binaryIV);

Я получаю строку в файле error_log который гласит:

PHP Неустранимая ошибка: допустимый размер памяти 134217728 байт исчерпан (пытался выделить 51694736 байт) в /home2/myaccount/public_html/myfldr/myfile.inc в строке 620

Строка 620 указывает на mcrypt_encrypt в моем примере выше.

Поэтому я сделал некоторые исследования, и люди предложили добавить в файл php.ini:

memory_limit = -1

Что я и сделал, но это все равно привело к тому же результату.

Поэтому у меня есть вопрос из двух частей:

  1. Очевидно, как предотвратить исключение этого исключения из моего сценария?

  2. Есть ли способ заставить эту функцию возвращать ошибку или вызывать исключение, которое я могу уловить, а не просто завершать (и в результате получается белая/пустая страница, отображаемая пользователю?)

Мне нужно также разрешить пункт 2 выше, чтобы удалить незашифрованный файл с сервера, если сбой шифрования (что я, очевидно, не могу сделать, если mcrypt_encrypt просто завершает мой скрипт.

PS. Мне нужно сказать, что я запускаю этот скрипт в общей учетной записи, размещенной в BlueHost.

  • 0
    Возможно, ваш интернет-провайдер отключил изменение предела памяти для совместного использования ресурсов многими клиентами. Может быть, вам нужно платить больше.
  • 0
    @HoboSapiens: Хм. Может быть. Но если это так, то функция mcrypt_encrypt бесполезна, не так ли? Кроме того, мне любопытно, поскольку загрузка всего файла в ОЗУ и его шифрование может быть плохой идеей, есть ли способ сделать это блок за блоком? Или, другими словами, путем чтения, шифрования и записи небольших фрагментов файла, по одному за раз.
Теги:
encryption
error-log
php-ini

2 ответа

1

использование

ini_set("memory_limit","640M");

Чтобы установить предел памяти на более высокий предел. Приведенное выше увеличивает лимит с вашего 128MB до 640Mb.

Если вы все еще сталкиваетесь с проблемами, используйте

realpath_cache_size = 16k
realpath_cache_ttl = 120

Обратите внимание, что в php 5.3 и после того, как вы можете просто поместить файл user.ini (с линией памяти_limit = 640M) в каталог public_html, но это не разрешено всеми cpanels.

  • 0
    Благодарю. Просто любопытно, почему настройка его через ini_set имеет эффект, а его изменение через php.ini - нет?
  • 0
    Некоторые настройки игнорируют (к сожалению) настройки файла .ini. Сегодня существует тенденция поддерживать их как можно больше, потому что общие конфиги могут быть очень легко написаны через .inis.
Показать ещё 3 комментария
0

Одним из возможных способов решения проблемы было бы зашифровать файл небольшими кусками (например, 4128 байт за раз).

Образец кода:

$fr=fopen('input.file','r');
$fw=fopen('output.file','w');
while(!feof($fr))
{
    $buffer=fread($fr,4128);
    $result=mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $binaryKey, $buffer, MCRYPT_MODE_CBC, $binaryIV);
    false!==$result && fwrite($fw,$result);
}
fclose($fw);
fclose($fr);

Таким образом, вы получаете зашифрованный файл, который позже может быть расшифрован путем изменения этих шагов.

Обратите внимание, что размер 4128 куска не выбирается случайным образом. Зная, что RIJNDAEL поддерживает блоки 128/192/256 бит (т.е. 16/24/32 байта), я определил LCM между этими номерами (это 96), а затем я выбрал любой размер блока (около 4K), который кратен 96 Случилось так, что 4128 соответствовали критериям.

Почему размер куска важен? Поскольку MCrypt делит ваш входной текст на фиксированные блоки длины вашего блока и, если есть напоминание, он заполняет это пространство нулями до тех пор, пока длина блока не разделится точно. Поэтому мы не хотим, чтобы MCrypt мог это сделать, правильно? Во всяком случае, имейте в виду, что он сделает это для последнего блока вашего файла (если вам не повезет, так что он уже кратен вашему размеру блока.

Я надеюсь, что это помогает...

  • 0
    Я не совсем уверен насчет 4128 байтов или какого-либо жестко закодированного значения, но в конечном итоге я использовал этот подход, то есть шифрование кусками. Важно отметить, что размер каждого блока шифрования должен быть кратным размеру блока шифра. Это можно получить, вызвав mcrypt_get_iv_size , например: $cipher_block_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню