Les algorithmes du type MD5 ou SHA permettent en effet d'obtenir à partir d'un flot de bits, dans notre cas une archive PHAR, un identifiant théoriquement unique sous la forme d'une chaîne de caractères plus ou moins longue, appelée signature.

Une fois stockée au sein de l'archive lors de sa création, cette signature est comparé par PHP avec celle qu'il calcule lors de l'exécution de l'archive.

Si les signatures sont identiques, l'archive est intègre, et dans le cas contraire, elle a été corrompue.

L'algorithme OpenSSL repose sur un mécanisme complètement différent basé sur une paire de clefs publique et privée, et c'est grâce à ce mécanisme que l'origine de l'archive peut être garantie.

Lorsque cet algorithme est utilisé, l'archive est en effet signé avec la clef privée, uniquement détenu par le créateur de l'archive et qui doit être absolument tenue secrète.

C'est en effet ,elle qui permet de garantir l'origine de l'archive puisque pour une clef publique, il ne peut correspondre en théorie qu'une et une seule clef privée.

À contrario, la clef publique, comme son nom l'indique, doit pouvoir être utilisé par n'importe qui, car c'est elle qui permet de vérifier à la fois l'intégrité de l'archive et sa provenance.

L'utilisation de OpenSSL pour signer une archive PHAR nécessite donc une paire de clefs privée/publique.

Si vous n'en disposez pas déjà, le plus simple pour signer une archive est de générer un certificat qui contiendra à la fois la clef publique et la clef privée, via l'éxécution en CLI de l'instruction suivante :

# openssl req -x509 -nodes -days 365   -newkey rsa:2048 -keyout mycert.pem -out mycert.pem

Attention, ce certificat contenant votre clef privée, il est absolument indispensable de le garder secret.

Une fois en possession de ce certficat, il est relativement simple de l'utiliser pour signer l'archive, le seul pré-requis étant que PHP dispose de l'extension OpenSSL.

La première chose à faire est d'obtenir une instance de la classe \Phar correspondant à l'archive à signer.

Il faut ensuite extraire du certificat la clef publique et la clef privée afin de signer l'archive via la méthode \Phar::setSignatureAlgorithm(), en lui passant comme argument la constante \Phar::OPENSSL et la clef privée sous la forme d'une chaîne de caractères.

Enfin, il faut mettre la clef publique dans un fichier portant le nom de l'archive complété de l'extension .pubkey .

<?php
$phar = new \phar('myArchive.phar');
$certificate = file_get_contents(__DIR__ . '/mycert.pem');
$publicKey = openssl_get_publickey($certificate);
$privateKey = openssl_get_privatekey($certificate);
openssl_pkey_export($privateKey, $privateKeyAsString);
$phar->setSignatureAlgorithm(\phar::OPENSSL, $privateKeyAsString);
$publicKeyDetails = openssl_pkey_get_details($publicKey);
file_put_contents(__DIR__ . '/' . name . '.pubkey', $publicKeyDetails['key']);
?>

Évidemment, il faut remplacer dans le script ci-dessus les chemins d'accès à l'archive et au certificat par ceux correspondant à votre contexte d'utilisation.

Une fois cela fait et le script exécuté, vous obtiendrez une archive PHAR signée à l'aide de OpenSSL, ainsi que la clef publique correspondante.

Les utilisateurs de votre archive seront alors certains, lorsqu'ils utiliseront votre archive, qu'elle est intègre et que c'est bien vous son éditeur car PHP utilisera pour cela et de manière totalement transparente pour l'utilisateur, la clef publique que vous aurez pris soins soit de distribuer avec votre archive, soit de rendre publique.

Si ce n'est pas le cas, les utilisateurs de votre archive PHAR obtiendront le message suivant, sous la forme d'une exception de type \UnexpectedValueException, lors de son exécution :

phar "/path/to/myarchive.phar" openssl signature could not be verified: openssl public key could not be read

Et si l'archive a été altérée ou si la clef publique ne correspond pas à la signature de l'archive, ils obtiendront le message suivant, cette fois sous la forme d'une exception de type \PharException :

phar "/path/to/myarchive.phar" has a broken signature

Je vous rappelle par ailleurs que pour générer et donc signer des archives PHAR, l est nécessaire soit de passer la valeur de la directive phar.readonly à 0 dans le fichier php.ini, soit de forcer la valeur à 0 sa valeur en ligne de commande via l'option -d de PHP, de la manière suivante :

# php -d phar.readonly=0 signMyArchiveWithOpenSSL.php

Enfin, PHP doit évidemment avoir été compilé avec les directives de compilation --enable-phar et --disable-zend-multibyte.