This new feature implementation rely on libzip library new version 1.2.0.

For now, only build using system library is supported for this new feature, but an update of the bundled library is planed.

When everything will be validated, version will be released and merged in php sources (ext/zip), probably in PHP 7.2.

this development  is in progress, nothing final, proposed methods still can change.

RPM installation

The  php-pecl-zip-1.4.0.0-0.2.20170301dev package is available in remi-test repository (and remi-php70-test, remi-php71-test).

Installation from sources

From a clone of the sources, available in github :

$ phpize
$ ./configure --with-libzip
...
checking for libzip... from pkgconfig: version 1.2.0 found in /usr/lib64
checking for zip_open in -lzip... yes
checking for zip_file_set_encryption in -lzip... yes
...
$ make
...
Build complete.
Don't forget to run 'make test'.
$ make test
...
PASS ZipArchive::setEncryption*() functions [tests/oo_encryption.phpt]

Encrypted archive creation

Three methods are available to manage encryption :

ZipArchive::setEncryptionName($name, $method [, $password]);
ZipArchive::setEncryptionIndex($index, $method [, $password]);
ZipArchive::setPassword($password);

Encryption method being one of the new constants:  ZipArchive::EM_NONE, ZipArchive::EM_AES_128, ZipArchive::EM_AES_192 or ZipArchive::EM_AES_256.

Example 1:

Using per file password

$zip = new ZipArchive;
$zip->open(__DIR__ . '/encrypted.zip',   ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE);
$zip->addFile(__FILE__, 'foo.php');
$zip->setEncryptionName('foo.php', ZipArchive::EM_AES_256, 'secret');
$zip->close();

Example 2:

Using default (global) password

$zip = new ZipArchive;
$zip->open(__DIR__ . '/encrypted.zip',   ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE);
$zip->setPassword('secret');
$zip->addFile(__FILE__, 'foo.php');
$zip->setEncryptionName('foo.php', ZipArchive::EM_AES_256);
$zip->close();

Encrypted archive reading

Example :

$zip = new ZipArchive;
$zip->open(__DIR__ . '/encrypted.zip');
print_r($zip->statName($file));
$zip->setPassword('secret');
$text = $zip->getFromName('foo.php');
$zip->close();

To be noticed :

  • the setPassword method call, which set the default password
  • the statName method output now includes a new information field: encryption_method (259 is ZipArchive::EM_AES_256)

Encrypted archive reading using stream

The password need to be given using a stream context.

Exemple :

$ctx = stream_context_create(array(
    'zip' => array(
        'password' => 'secret'
    )
));
$text = file_get_contents('zip://' . __DIR__ . '/encrypted.zip#foo.php', false, $ctx);

Conclusion

Full script used in above examples is available in the extension sources: encryption.php

This new feature seems really useful and will improve compatibility with other tools, such as WinZip for Windows or 7za for Linux.

This change should be available in Fedora 26 which already have libzip 1.2.0.