AES 128 бит CTR частичная расшифровка файлов с помощью PHP

Это не дублированный пост, потому что я посмотрел везде и не могу найти ответ на этот вопрос. Это о частичной расшифровке. Не полный.

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

Он прекрасно расшифровывается, когда я пытаюсь расшифровать первые 128 КБ файла или 256 КБ или любую длину от начала файла. но когда я начинаю с середины, он не расшифровывает, а выдает бессмысленный вывод.

Я опубликую здесь пример первых 100 байтов файла.

Шифрование - 128-битный режим CTR AES.

Я использовал функции PHP mdecrypt_generic и mcrypt_decrypt, но безуспешно.

используемый код:

$chunk2 = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, base64_decode($mega_key), $data, 'ctr', base64_decode($mega_iv));
echo base64_encode($data) .'<br />'. base64_encode($chunk2);

Результат:

9PX2fU83NF3hLc+HFdyHkqfxC4bHWKUQwQHJkNVnYbKCIQrhlHvTKtz8T3Bb0TgBkyBoGHnDCzZs3bu54KLQ8Bv0lzrTVJbzJY5msBfcy7Zi2Z/fLoMm+nvqdGPTNR0uwv45xJ8=
MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTE=

Как вы видете. после дешифрования результатом являются первые 100 байтов файла, содержащего цифру 1 в серии. Файл зашифрован Mega.co.nz с использованием JavaScript. Согласно документации в Mega, файл был зашифрован кусками для частичного шифрования / дешифрования.

Шифрование файлов

MEGA использует шифрование / дешифрование на стороне клиента для сквозной защиты при передаче и хранении файлов. Данные, полученные от клиентов, хранятся и передаются дословно; серверы не дешифруют, не перешифруют и не проверяют шифрование входящих пользовательских файлов. Вся криптографическая обработка находится под контролем конечного пользователя. Чтобы обеспечить частичное чтение с проверкой целостности, файл обрабатывается как серия фрагментов. Чтобы упростить обработку на стороне сервера, частичные загрузки могут начинаться и заканчиваться только на границе фрагмента. Кроме того, частичные загрузки могут быть проверены на целостность, только если они соответствуют одному и тому же критерию. Границы фрагментов расположены в следующих положениях: 0 / 128K / 384K / 768K / 1280K / 1920K / 2688K / 3584K / 4608K /. (каждые 1024 КБ) / EOF

Я вычисляю границы фрагментов файла с помощью этой функции:

public function get_chunks($size)
{
    $chunks = array();
    $p = $pp = 0;

    for ($i = 1; $i <= 8 && $p < $size - $i * 0x20000; $i++) {
        $chunks[$p] = $i * 0x20000;
        $pp = $p;
        $p += $chunks[$p];
    }

    while ($p < $size) {
        $chunks[$p] = 0x100000;
        $pp = $p;
        $p += $chunks[$p];
    }

    $chunks[$pp] = ($size - $pp);
    if (!$chunks[$pp])
    {
        unset($chunks[$pp]);
    }

    return $chunks;
}

Я попытался расшифровать 2-й блок по отдельности, это не удается. Я не могу разместить чанк 128 КБ здесь по понятным причинам, но я покажу вам чанк, начиная со 2-го байта до 100-го. Это результат с тем же кодом:

используемый код:

$chunk2 = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, base64_decode($mega_key), $data, 'ctr', base64_decode($mega_iv));
echo base64_encode($data) .'<br />'. base64_encode($chunk2);

Результат:

9fZ9Tzc0XeEtz4cV3IeSp/ELhsdYpRDBAcmQ1WdhsoIhCuGUe9Mq3PxPcFvROAGTIGgYecMLNmzdu7ngotDwG/SXOtNUlvMljmawF9zLtmLZn98ugyb6e+p0Y9M1HS7C/jnEnw==
MDK6A0kyWI3903mj+GokBGfLvHCuzITg8flodIM34gGSGtpE3pnIxxGCDhq72AijgnlBUIv5DGuAVzNoc0MR2t5SnNi281TnmtnnlvomTOWKd3HAnJTtsKCvJoHXGQLdDfbMag==

Результаты совпадают с mcrypt_module_open('rijndael-128', '', 'ctr', '');

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

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

На веб-сайте mega их собственный интерфейс загрузки использует несколько подключений и загружает файл порциями, а есть еще один веб-сервис, который позволяет загружать из Mega несколько подключений и поддерживать возобновление.

Мне нужно расшифровать частичный файл для поддержки запросов заголовка HTTP Range от браузера / менеджеров загрузки. Если запрос диапазона попадает во 2-й или 3-й блок, мне нужно иметь возможность расшифровать этот блок и отправить его клиенту, не расшифровывая файл с самого начала.

Это вообще возможно? Это должно быть потому, что какой-то сайт уже сделал это.

2 ответа

Хорошо, я нашел решение о расшифровке частичного контента на лету. У меня была эта проблема, когда я пытался расшифровать частичные данные из Range (для создания веб-прокси). Я обнаружил, что, если я загружаю весь файл (с позиции 0 так), нет проблем. Пример:

while($_total_dled != $content_length) {
        $raw = fgets($socket, 1024);
        $data = mdecrypt_generic($this->cipher, $raw);
        echo $data;
}

НО, если я начну читать файл с позиции x (как если бы я получил: Range x-), mdecrypt_generic завершится ошибкой, потому что он не был выполнен (x-1) раз раньше. Итак, я пытаюсь это:

for($i=0;$i<$range["start"];$i++) {
     mdecrypt_generic($this->cipher, "0");
}

Просто нужно расшифровать один символ (х-1) раз. и затем часть с циклом while. И это работает. Может быть, мы можем связать эту итерацию с соответствующим счетчиком.

Надеюсь, это поможет людям.

Сдается мне, что вы делаете много вычислений на границах чанка (которые приведены в виде таблицы + простой расчет на 4608Ki) и не рассчитываете, чтобы добраться до нового IV.

IV - это просто случайный одноразовый номер плюс счетчик блоков. Таким образом, чтобы вычислить новый "IV" для конкретного чанка, вам нужно сделать:

  1. создать начальный счетчик, сдвинув одноразовый номер в старшие (левые) байты
  2. получить нижнюю границу куска
  3. разделить нижнюю границу на размер блока
  4. добавить или XOR (то же самое для первых 2^64 блоков) результирующее число к начальному счетчику
  5. инициализировать ваш шифр с ним

Тогда вы должны быть в состоянии расшифровать.

Другие вопросы по тегам