Wiki ⇒ v10 Developer's manual ⇒ Packages (PHAR) ⇒ CPG Dragonfly™ CMS
Wikiv10 Developer's manual ⇒ Packages (PHAR)

14. 5: Packages (PHAR) Parent


PHAR (PHp ARchives) is a nice PHP feature. They are a way to distribute an entire PHP application as a single archived file that can be executed directly by the PHP intepreter without having to unarchive them.

Starting with PHP 5.3, you can use OpenSSL to sign a Phar archive. The intepreter will now refuse to run the code unless the required public key is present. This provides some security protection; you now know that any Phar that has been signed with that key is a valid update.

Dragonfly CMS v10 supports Phar as non-executable OpenSSL signed:

  • PharData module (example: /modules/Downloads.phar + /modules/Downloads.phar.pubkey)
  • Package manager repository archive (.tgz/.tar.gz)

PharData module

As explained above you can create a PharData package of your module and sign it with an OpenSSL private key.

<?php
	$file = '/module/that/needs/to/be/signed.tgz';
	copy('public-key.pubkey', "{$file}.pubkey");
	$phar = new \PharData($file);
	$phar->setSignatureAlgorithm(Phar::OPENSSL, file_get_contents('/private-key.pem'));

To test how it works you can

  1. download Wiki.tgz
  2. download PM-DragonflyCMS-10.pubkey
  3. rename PM-DragonflyCMS-10.pubkey to Wiki.tgz.pubkey
  4. Place both files in /modules/
  5. Got to http://example.com/?admin&op=modules to see it listed

Package manager repository

Since we built many modules, we use a script that signs all packages and creates the required repository packages.xml.
You can find the packager.php script for reference in the bitbucket repo

Built your own with OpenSSL keys

Prerequisites

  1. NOT on a production server (do this on a local machine)
  2. OpenSSL
  3. PHP of at least 5.3 (really, you should be on at least 7.x now)
  4. PHP OpenSSL extension
  5. phar.readonly=0 in php.ini DON'T DO THIS ON A PRODUCTION SERVER!

Step 1: Create a Public/Private Key

Use OpenSSL to create a public/private key pair. This is the fast, but slightly less secure way.

openssl genrsa -out packages_private.pem 4096
openssl rsa -in packages_private.pem -pubout -out packages_public.pem

If you want further security, you could create a key that requires a password to use:

openssl genrsa -aes256 -out packages_private.pem 4096
openssl rsa -in packages_private.pem -outform PEM -pubout -out packages_public.pem

The upside of this is, it's now even harder to compromise your private key, because a potential attacker would need to have both, the private key and the password to use it. The downside of this is that you will need your password every time you use this key, which makes the use of automated build tools impossible (or else the password is in the built tools which makes protection useless).

The above mentioned packager.php doesn't handle passwords (yet).

So you now have 2 keys: a public key, and a private one. Store the private key at a safe place. If your private key is compromised, there is no real good way to invalidate it once you have your Phars out in the wild. Your users will need to download a new Phar with a new public key if your key is compromised, not to mention the bad things that could happen if someone could sign updates that look like they come from you. Dragonfly CMS Package manager does allow a public key in the generated packages.xml (<public_key>{$key}.pubkey</public_key>) but deactivates the repository for security reasons.

Step 2: Sign the Phar

Now you can you either use the module code or the repository packager

Step 3: Distribution

For both ways you must make the packages_public.pem available to the public

When you used the module code, you must distribute the packages_public.pem as mentioned, like: modulename.tgz.pubkey.

When you used the repository packager you must provide the packages_public.pem readable and the repository location.

More info and assistence

Go to this forum topic


Created: Tuesday, January 16, 2018 (03:51:31) by DJ Maze
Updated: Thursday, August 09, 2018 (00:13:34) by DJ Maze