Как зашифровать/расшифровать файлы с помощью php (mcrypt)?

Я удивлен, что не нашел в Интернете ни одного фрагмента кода, совета или руководства, объясняющего, как зашифровать файл, используя только стандартные компоненты php.

Поэтому я прошу вашего совета: как зашифровать/расшифровать файлы, используя только стандартные функции mcrypt и php? У меня нет возможности использовать gnupg. Нет, на самом деле, мой вопрос: как сделать вышеперечисленное, не испортив мои файлы? Потому что я уже чертовски шифрую/дешифрую эти файлы (с помощью mcrypt/AES), и это хорошо работает для jpeg, PDF, некоторых файлов .doc и, что интересно, файлов .docx, защищенных паролем. Он не работает с незащищенными файлами .docx и многими другими типами файлов.

Мой текущий код таков. По сути, я просто открываю файл, перебираю данные с помощью mcrypt/AES и записываю их на сервер/даю пользователю загрузить их.

Для кодирования после загрузки:

// using codeigniter's encryption library, which uses mcrypt and the AES cypher
$this->load->library('encrypt');
$pathandname = $config['upload_path'].$output['content'][$a]['file_name']; 
$theFile = file_get_contents($pathandname);
$fh = fopen($pathandname,'w');
fwrite($fh,$this->encrypt->encode($theFile));
fclose($fh); 

Чтобы расшифровать и скачать:

$this->load->library('encrypt');
$pathandname = $filelocation.$results[0]['encryptedfile']; 
$theFile = file_get_contents($pathandname);
$decrypted = $this->encrypt->decode($theFile);
force_download($filename, $decrypted); // a codeigniter function to force download via headers

person Flo    schedule 30.07.2012    source источник
comment
в чем именно проблема?: Ваш нынешний подход не работает? Или вас интересует, как это сделать без CodeIgniter? Если второе, то почему бы просто не почитать соответствующие источники?   -  person tdammers    schedule 30.07.2012
comment
Нет, я хочу знать, как использовать по существу этот метод. Но расшифрованный файл   -  person Flo    schedule 30.07.2012
comment
Не используйте больше устаревшую библиотеку шифрования CodeIgniter 2, вместо этого используйте библиотеку шифрования CodeIgniter 3. Шифрование было хрупким, Шифрование надежно.   -  person Scott Arciszewski    schedule 12.08.2015


Ответы (1)


как зашифровать/расшифровать файлы, используя только стандартные функции mcrypt и php?

Ну, вы не хотите использовать mcrypt. Вы хотите использовать натрий в эти дни.

Шифрование файла с помощью натрия (PHP 7.2+, PECL ext/sodium или натрия_compat)

Соответствующий API, который вам нужен, — crypto_secretstream.

const CUSTOM_CHUNK_SIZE = 8192;

/**
 * @ref https://stackoverflow.com/q/11716047
 */
function encryptFile(string $inputFilename, string $outputFilename, string $key): bool
{
    $iFP = fopen($inputFilename, 'rb');
    $oFP = fopen($outputFilename, 'wb');

    [$state, $header] = sodium_crypto_secretstream_xchacha20poly1305_init_push($key);

    fwrite($oFP, $header, 24); // Write the header first:
    $size = fstat($iFP)['size'];
    for ($pos = 0; $pos < $size; $pos += CUSTOM_CHUNK_SIZE) {
        $chunk = fread($iFP, CUSTOM_CHUNK_SIZE);
        $encrypted = sodium_crypto_secretstream_xchacha20poly1305_push($state, $chunk);
        fwrite($oFP, $encrypted, CUSTOM_CHUNK_SIZE + 17);
        sodium_memzero($chunk);
    }

    fclose($iFP);
    fclose($oFP);
    return true;
}

Расшифровка выглядит так:

/**
 * @ref https://stackoverflow.com/q/11716047
 */
function decryptFile(string $inputFilename, string $outputFilename, string $key): bool
{
    $iFP = fopen($inputFilename, 'rb');
    $oFP = fopen($outputFilename, 'wb');

    $header = fread($iFP, 24);
    $state = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $key);
    $size = fstat($iFP)['size'];
    $readChunkSize = CUSTOM_CHUNK_SIZE + 17;
    for ($pos = 24; $pos < $size; $pos += $readChunkSize) {
        $chunk = fread($iFP, $readChunkSize);
        [$plain, $tag] = sodium_crypto_secretstream_xchacha20poly1305_pull($state, $chunk);
        fwrite($oFP, $plain, CUSTOM_CHUNK_SIZE);
        sodium_memzero($plain);
    }
    fclose($iFP);
    fclose($oFP);
    return true;
}

Использование двух функций вместе:

$key = random_bytes(32);
encryptFile('input.txt', 'cipher.txt', $key);
decryptFile('cipher.txt', 'decrypt.txt', $key);
person Scott Arciszewski    schedule 27.10.2019
comment
Не могли бы вы немного объяснить ключевой параметр и какие значения он принимает? А при расшифровке нужен такой же ключ правильный? - person Crimin4L; 14.06.2021