Создать зашифрованный zip-архив с PHP - PullRequest
21 голосов
/ 14 марта 2009

Я ищу способ зашифровать TXT-файл в zip-файл, но защищенным паролем способом. Моя цель - отправить мне этот файл по электронной почте, чтобы никто не смог прочитать содержание вложения.

Кто-нибудь знает простой и, прежде всего, безопасный способ сделать это? Я могу создавать zip-архивы, но я не знаю, как их зашифровать или насколько это безопасно.

Ответы [ 5 ]

17 голосов
/ 14 марта 2009

Примечание: этот ответ рекомендует криптографический метод, который известен небезопасно, даже с хорошим паролем. Пожалуйста см. Ссылку из комментариев и WinZip QA на AES . Поддержка in-php AES zip-шифрования поставляется с php 7.2 libzip 1.2.0 ), что означает ответ скоро тоже устареет. До тех пор см. Этот ответ о том, как вызвать 7z вместо команды zip, которая поддерживает winzip Шифрование AES .

Вы можете использовать это:

<?php echo system('zip -P pass file.zip file.txt'); ?>

Где pass - пароль, а file.txt будет заархивирован в file.zip. Это должно работать на Windows и Linux, вам просто нужно получить бесплатную версию zip для Windows (http://www.info -zip.org / Zip.html # Win32 )

Этот вид безопасности может быть взломан атаками с использованием грубой силы, атаками по словарю и т. Д. Но это не так просто, особенно если вы выбрали длинный и сложный пароль.

11 голосов
/ 01 декабря 2017

Начиная с версии php 7.2 (выпущенной несколько часов назад), правильный способ сделать это - использовать дополнительные функции, включенные в ZipArchive собственный код php. (спасибо abraham-tugalov за указание на то, что это изменение грядет)

Теперь простой ответ выглядит примерно так:

<?php
$zip = new ZipArchive();
if ($zip->open('test.zip', ZipArchive::CREATE) === TRUE) {
    $zip->setPassword('secret_used_as_default_for_all_files'); //set default password

    $zip->addFile('thing1.txt'); //add file
    $zip->setEncryptionName('thing1.txt', ZipArchive::EM_AES_256); //encrypt it

    $zip->addFile('thing2.txt'); //add file
    $zip->setEncryptionName('thing2.txt', ZipArchive::EM_AES_256); //encrypt it

    $zip->close();

    echo "Added thing1 and thing2 with the same password\n";
} else {
    echo "KO\n";
}
?>

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

В этом примере представлены более сложные варианты.

<?php
$zip = new ZipArchive();
if ($zip->open('test.zip', ZipArchive::CREATE) === TRUE) { 
     //being here means that we were able to create the file..

     //setting this means that we do not need to pass in a password to every file, this will be the default
    $zip->addFile('thing3.txt');

    //$zip->setEncryptionName('thing3.txt', ZipArchive::EM_AES_128);
    //$zip->setEncryptionName('thing3.txt', ZipArchive::EM_AES_192);
    //you should just use ZipArchive::EM_AES_256 unless you have super-good reason why not. 
    $zip->setEncryptionName('thing3.txt', ZipArchive::EM_AES_256, 'password_for_thing3');

     $zip->addFile('thing4.txt');
    //or you can also use the index (starting at 0) of the file...
    //which means the following line should do the same thing...
    //but just referencing the text.txt by index instead of name..
    //$zip->setEncryptionIndex(1, ZipArchive::EM_AES_256, 'password_for_thing_4'); //encrypt thing4, using its index instead of its name...

    $zip->close();
    echo "Added thing3 and thing4 with two different passwords\n";
} else {
    echo "KO\n";
}
?>

Базовая поддержка zip-шифрования включена, поскольку в libzip 1.2.0 появилась поддержка шифрования. Таким образом, вам понадобится php 7.2 и libzip 7.2, чтобы запустить этот код ... Надеюсь, эта заметка будет искажена этим ответом "очень скоро"

4 голосов
/ 20 июля 2017

Хотя PHP является зрелым языком , не существует адекватного метода (исключая пользовательское расширение или что-то в этом роде) для решения такой простой задачи с использованием чистого PHP.
Что вы также можете сделать, это подождать, пока PHP 7.2 будет доступен для производства (cuz ZipArchive :: setEncryptionName реализовано (спасибо Пьеру и Реми)).
Но до тех пор вы также можете попытаться портировать php_zip > = 1.14.0 на PHP
постскриптум Я бы попробовал, но на моем ПК сейчас нет VS2015 +.

1 голос
/ 22 марта 2009

Все больше и больше инструментов поддерживают AES-зашифрованные ZIP-файлы. Это работает, это безопасно.

EDIT2: Вы можете использовать DotNetZip из PHP для динамического создания AES-зашифрованных zip-архивов из PHP. DotNetZip - это библиотека .NET, разработанная для языков .NET (C #, VB и т. Д.). Он работает только на Windows :(. Но DotNetZip делает AES, и он бесплатный, и работает на PHP.

Это код, который я использовал. (PHP v5.2.9 на Win32)

<code><?php
try
{
  $fname = "zip-generated-from-php-" . date('Y-m-d-His') . ".zip";
  $zipOutput = "c:\\temp\\" . $fname;
  $zipfact = new COM("Ionic.Zip.ZipFile");
  $zip->Name = $zipOutput;
  $dirToZip= "c:\\temp\\psh";
  # Encryption:  3 => 256-bit AES.  
  #     2 => 128-bit AES.  
  #     1 => PKZIP (Weak).  
  #     0 => None
  $zip->Encryption = 3;
  $zip->Password = "AES-Encryption-Is-Secure";
  $zip->AddDirectory($dirToZip);
  $zip->Save();
  $zip->Dispose();

  if (file_exists($zipOutput))
  {
    header('Cache-Control: no-cache, must-revalidate');
    header('Content-Type: application/x-zip'); 
    header('Content-Disposition: attachment; filename=' . $fname);
    header('Content-Length: ' . filesize($zipOutput));
    readfile($zipOutput);
    unlink($zipOutput);
  }
  else 
  {
    echo '<html>';
    echo '  <head>';
    echo '  <title>Calling DotNetZip from PHP through COM</title>';
    echo '  <link rel="stylesheet" href="basic.css"/>';
    echo '  </head>';
    echo '<body>';
    echo '<h2>Whoops!</h2>' . "<br/>\n";
    echo '<p>The file was not successfully generated.</p>';
    echo '</body>';
    echo '</html>';
  } 
}
catch (Exception $e) 
{
    echo '<html>';
    echo '  <head>';
    echo '  <title>Calling DotNetZip from PHP through COM</title>';
    echo '  <link rel="stylesheet" href="basic.css"/>';
    echo '  </head>';
    echo '<body>';
    echo '<h2>Whoops!</h2>' . "<br/>\n";
    echo '<p>The file was not successfully generated.</p>';
    echo '<p>Caught exception: ',  $e->getMessage(), '</p>', "\n";
    echo '<pre>';
    echo $e->getTraceAsString(), "\n";
    echo '
'; echo ''; echo ''; } ?>

Мне пришлось изменить DotNetZip, чтобы он работал с PHP: мне нужно было сделать свойство Name доступным для чтения / записи, и я должен был сделать его COM-вызываемым. Это изменение впервые доступно в v1.8.2.3 версии .

0 голосов
/ 02 января 2014

Вот как я это сделал. Это с Excel, но это то же самое.

  • Пусть php создаст случайное кодовое имя.
  • Сохраните кодовое имя в db или в файле, который будет включен в retrieve.php.
  • Отправьте себе кодовое имя.

  • Доступ через веб-сайт retrieve.php? Codename = [кодовое имя]

  • Пусть php проверит правильность кодового имени. (может быть, даже это возраст).
  • Создание файла Excel / textfile в памяти из данных, которые необходимо отправить вам.
  • Создайте код шифрования, добавив локальный пароль (который известен только вам) с кодовым именем. (Я говорю «добавить», но также можно смешивать, или xor-ed, или substr ...)
  • Шифрование на лету с помощью созданного кода шифрования.
  • Удалить кодовое имя из базы данных или файла конфигурации.
  • Возвратите этот зашифрованный документ по почте (в архиве или не по размеру).
  • Возможно, добавьте два первых символа из кодового имени в почте, чтобы узнать, какое локальное полное кодовое имя использовать.

  • Используйте локальный сценарий дешифрования для декодирования загруженного файла. Используйте тот же алгоритм кодового имени / пароля для создания ключа расшифровки.

Я использую gibberish-aes-php. (https://github.com/ivantcholakov/gibberish-aes-php)
Потому что тогда я могу использовать https://github.com/mdp/gibberish-aes в качестве javascript на клиентском декодере (для вещей, которые я хочу быстро просмотреть в браузере).

...