Недостаточно памяти при расшифровке больших файлов в PHP с помощью phpseclib

Я пытаюсь написать программу, которая расшифровывает файлы AES на лету с помощью phpseclib. Файлы большие, поэтому я получаю сообщение об ошибке нехватки памяти, если использую file_get_contents($f) или fread(filesize($f)) для чтения входного файла.

По какой-то причине такой цикл создает поврежденные выходные файлы. ЗАЧЕМ!? знак равно

Например, входной файл размером 296 155 408 байт имеет размер 18 805 826 байт. ПРИМЕЧАНИЕ. Это работает, если весь файл может быть прочитан за одну итерацию цикла.

define('MY_BUFFER_SIZE', 128 * 1024);
$sessionKey = '....';

$filenameIn = $argv[1];
$fileIn = fopen($filenameIn, 'rb');
$filenameOut = dirname($argv[1]) . DIRECTORY_SEPARATOR . basename($argv[1], '.tar.gz') . '-decrypted.tar.gz';
$fileOut = fopen($filenameOut, 'wb');

// Setup cipher for continuous buffering and copy between files.
$aesCipher = new Crypt_AES(CRYPT_AES_MODE_CBC);
$aesCipher->setKey($sessionKey);
$aesCipher->setIV("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
$aesCipher->enableContinuousBuffer();
while (!feof($fileIn)) {
    $packet = fread($fileIn, MY_BUFFER_SIZE); // @TODO: Streaming not working.
    fwrite($fileOut, $aesCipher->decrypt($packet));
}

fclose($fileIn);
fclose($fileOut);

person bhafer    schedule 29.07.2014    source источник
comment
Вы понимаете, что означает этот CBC? Кроме того, можете ли вы более точно описать, что вы подразумеваете под испорченным?   -  person David Schwartz    schedule 29.07.2014
comment
Цепочка блоков шифра. :) Вот почему я включил непрерывный буфер. Думал, что это для такого типа использования. Поврежденные означает, что они недействительны. Я работаю с бинарниками .tgz, поэтому ничего не могу сказать, кроме того, что их нельзя открыть.   -  person bhafer    schedule 29.07.2014
comment
Вы имеете в виду, что вы шифруете их, а затем расшифровываете, и они повреждены? Если да, можете ли вы показать код шифрования и код дешифрования? (если это не то же самое)   -  person David Schwartz    schedule 29.07.2014
comment
Нет. Они уже зашифрованы извне. Я пытаюсь прочитать зашифрованный файл, расшифровать его и сохранить под новым именем. Добавляем немного больше кода вокруг фрагмента, чтобы обеспечить больше контекста...   -  person bhafer    schedule 29.07.2014
comment
Скорее всего, зашифрованный файл имеет не совсем ту структуру, которую ожидает этот код.   -  person David Schwartz    schedule 29.07.2014
comment
Он отлично работает, если файлы небольшие и требуется только одна итерация цикла.   -  person bhafer    schedule 29.07.2014
comment
Это полностью соответствует моему диагнозу.   -  person David Schwartz    schedule 29.07.2014
comment
Может быть, отключить прокладку? например. $aesCipher->disablePadding().   -  person neubert    schedule 29.07.2014


Ответы (1)


Спасибо @neubert! Требовалось добавить:

$aesCipher->disablePadding()

Это работает:

// Setup cipher for continuous buffering and copy between files.
$aesCipher = new Crypt_AES(CRYPT_AES_MODE_CBC);
$aesCipher->setKey($sessionKey);
$aesCipher->setIV("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
$aesCipher->enableContinuousBuffer();
$aesCipher->disablePadding();
while (!feof($fileIn)) {
    fwrite($fileOut, $aesCipher->decrypt(fread($fileIn, MY_BUFFER_SIZE)));
}
person bhafer    schedule 29.07.2014