3

I need to be able to create an archive(zip) file with password protection using PHP. I am using Laravel 5.4 and PHP 7.1 version. I looked at this link here for ZipArchive class documentation in PHP. I also looked at here for setPassword function. But appears that creation of password protected archives is not supported. It will be a massive surprise for me if it is not possible to create password protected archive in a mature programming language such as PHP 7.1.

So I guess I must be missing something. Can someone point me to the right direction? E.g. a sample example or open source third party library or extension to achieve this will be greatly appreciated.

Andy
  • 2,493
  • 6
  • 37
  • 63
  • Since the `setPassword()` only sets the password that is used to decompress an archive you could use `system('zip -P .zip ');` instead. – Cyclonecode Jul 19 '17 at 20:11
  • OK. So first create an archive file and before uploading (storing)... run the command line script to set password? – Andy Jul 19 '17 at 20:14
  • 1
    Possible duplicate of [ZIP a file and protect with a password in PHP](https://stackoverflow.com/questions/39833496/zip-a-file-and-protect-with-a-password-in-php) – Cyclonecode Jul 19 '17 at 20:17
  • 2
    I came across http://php.net/manual/en/ziparchive.setencryptionname.php documentation which will be available for PHP 7.2. But since PHP 7.2 is probably not production ready at the time of this writing, we will have to wait until then. – Andy Jul 19 '17 at 20:21

1 Answers1

4

Easy peasy lemon squeezy (no).
Yes, creation of password protected archives is not supported (they will be created simply as non-protected archives, as you just described).
But, still it can be used to extract password protected archives.

Returning to the problem.
You always can just

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

(this will work both on Windows and our beloved Linux)

But, if it not fits into your requirements, let's continue.
I would suggest you to use DotNetZip (Windows only), you will exactly dynamically generate AES-encrypted zip archives from PHP.

<?php
// origin: https://stackoverflow.com/a/670804/3684575
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 '</pre>';
    echo '</body>';
    echo '</html>';
}

?>

But still, this is very dirty solution and more of that, not works on Linux.

So, although PHP is a mature language, there is no adequate method (excluding custom extension or something like that) to achieve such a simple task with pure PHP.
What you also can do, is to wait until PHP 7.2 will be available for production (cuz ZipArchive::setEncryptionName is implemented (thanks to Pierre and Remi)).
But, until then you also can try to port php_zip >= 1.14.0 to PHP < 7.2, but there is currently no compiled binaries available, so you have to compile it yourself and try if it is possible at all (I believe it is).
p.s. I would try it, but have no VS2015+ on my PC right now.

Abraham Tugalov
  • 1,902
  • 18
  • 25