Как расшифровать большие файлы кусками с помощью функции PHP openssl_decrypt? - PullRequest
2 голосов
/ 20 июня 2019

Я работаю над хранилищем файлов и делюсь веб-приложением с Laravel на бэкэнде API и VueJS в качестве фронт-приложения. Я должен зашифровать загруженные файлы с помощью скрипта BASH, запускаемого каждую минуту, с помощью процедуры CRON, но мне нужно расшифровать их с помощью Laravel / PHP из контроллера в ответ StreamDownload (мне нужно дешифровать куски файлов кусками, потому что большие использовать слишком много памяти для нашего сервера). Мы решили зашифровать файлы из внешней подпрограммы, чтобы пользователь не мог дождаться его шифрования, иногда через несколько минут после загрузки файла.

Я использую Laravel 5.7 с PHP 7.3 на сервере Debian 4.9, но я делаю свои тесты на локальном компьютере в Windows 10, а также с WAMP и PHP 7.3. Я использую Git Bash для запуска и тестирования команд оболочки.

Мой текущий FileController содержит много методов, включая «Создать» и «Скачать». «Создать» просто сохраняет файл в каталоге хранилища Laravel и создает новый ресурс «Файл» в базе данных, а «Загрузка» пытается удалить зашифрованный файл, расшифровать его и отправить клиенту.

Вот мой метод создания. Он просто создает ресурс и сохраняет файл с расширением префикса .decrypted. (Я позволил много пробелов, потому что логика этого метода не о шифровании)

//App\Http\Controllers\Files\FileController.php

public function create(Request $request)
    {
       ...

       $file = File::create([
            'name' => $name,
            'uuid' => $uuid,
            ...
        ]);

        ...

        $output->move($userPath, $uuid.'.decrypted');

        ...

        return new FileResource($file);
    }

Затем, вот сценарий BASH, который я написал для шифрования суффиксированных файлов каждую минуту (я заменил разумную информацию на «###», не беспокойтесь.)

#encrypt.sh

#!/bin/bash

set -euo pipefail

# PARAMETERS
APP_KEY='######'
FILES_PATH='/###/.../storage/app/files/'
FILES_LIST=$(find "$FILES_PATH" -type f -name '*.decrypted' )
KEY=$(echo "$APP_KEY" | base64 -d -i | xxd -p -c 64)

while read -r file; do
  INPUT_PATH=$file
  OUTPUT_PATH=${file%.decrypted}
  IV=$(openssl rand -hex 16)
  openssl AES-256-CBC -K $KEY -iv $IV -in $INPUT_PATH -out $OUTPUT_PATH
done < <(echo "$FILES_LIST")

echo 'Done'

Насколько мне известно, этот код работает хорошо.

Тогда вот мой последний фрагмент кода: метод Download.

//App\Http\Controllers\Files\FileController.php

public function download(File $file, Request $request)
    {
        ...

        $dlFile = Storage::disk('files')->path($file->path);

        ...

        return response()->streamDownload(
            /* Note: $dlFile is the path, $file is the Laravel resource */
            function () use ($dlFile, $log, $file) {
                $cipher = config('app.cipher'); // AES-256-CBC
                /* Note: the app key is stored in format "base64:#####...", this is why there's a substr() inside a base64() */
                $key = base64_decode(substr(config('app.key'), 7));
                if ($fpIn = fopen($dlFile, 'rb')) {
                    $iv = fread($fpIn, 16);
                    while (!feof($fpIn)) {
                        $ciphertext = fread($fpIn, $this->memoryLimit());
                        $plaintext = openssl_decrypt($ciphertext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
                        print($plaintext);
                    }
                    fclose($fpIn);
                }
            },
            $fileName,
            [
                'Content-Type' => $file->mime,
                'Content-Length' => $file->size
            ],
            'inline'
        );
    }

Я получил этот последний кусок кода от этой страницы .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...