Pour les besoin d’un client, nous avons dû développer une commande permettant de chiffrer en PGP un fichier .csv transmis par la suite via SFTP.

Nous nous sommes alors penché sur les solutions à notre portée pour implémenter cette demande dans notre application Symfony et avons sélectionné le package système GnuPG et la librairie PEAR/Crypt_GPG.

Installation

RUN set -ex; \
apk add --no-cache --virtual .build-deps \
gnupg; \

Pour la dépendance Crypt_GPG et étant donné qu’il s’agit d’un projet Symfony, nous passons simplement par composer : `composer require pear/crypt_gpg`.

Génération d’une paire de clés

Même si votre client vous a confié la clé publique à utiliser pour chiffrer les fichiers que vous lui transmettrez, vous ne possédez certainement pas la paire permettant de chiffrer puis déchiffrer pour confirmer que votre méthode fonctionne. Il peut alors être intéressant de générer en local une paire de clés.

Dans notre situation exécuter la commande gpg --gen-key en bash sur votre container applicatif. À moins de se trouver dans un cas particulier de chiffrement, les propositions par défaut du prompt suffiront amplement. Il faudra juste saisir un nom, une adresse email et une phrase de passe utilisée.

L’affichage des clés enregistrées se fait avec la commande gpg --list-keys et permet d’afficher la liste des clés enregistrées. Comme votre client se base sur un fichier texte contenant sa clé publique, il vous faut également partir d’un même type de fichier pour tester au mieux vos chiffrements. L’export des clés se fait comme suit :

gpg --export-secret-keys <identifiant_de_votre_clé> > /var/www/html/keys/client_private_key.txt
gpg --armor --export <identifiant_de_votre_clé> > /var/www/html/keys/client_public_key.txt

Chiffrer et déchiffrer dans Symfony

 

Pour tester ces fonctionnalités et la librairie Crypt_GPG, nous créons une commande Symfony qui sera exécutée en ligne de commande et qui affichera le contenu du fichier entre chaque étape de chiffrement et de déchiffrement.

Notre commande affichera successivement le fichier de base, le fichier au contenu chiffré puis le fichier déchiffré.

<?php

namespace AppBundle\Command;

use Crypt_GPG;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class EncryptionAndDecryption extends Command
{
    protected function configure()
    {
// ...
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
// ...
        $output->writeln('fichier de base : ' . $csv);
        $encryptedCsv = $this->csvEncryption($csv);
        $output->writeln('fichier chiffré : ' . $encryptedCsv);
        $decryptedCsv = $this->csvDecryption($encryptedCsv);
        $output->writeln('fichier déchiffré : ' . $decryptedCsv);
// ...
    }

    /**
     * @param $csv
     * @return mixed
     */
    private function csvEncryption($csv)
    {
        $publicKey = file_get_contents("/var/www/html/keys/client_public_key.txt");
// ou récupération de la clé publique depuis un serveur AWS S3 par exemple.
        $gpg = new Crypt_GPG();
        $info = $gpg->importKey($publicKey);
        $gpg->addencryptkey($info[ 'fingerprint' ]);
        $encryptedCsv = $gpg->encrypt($csv);

        return $encryptedCsv;
    }

    /**
     * @param $encryptedCsv
     * @return mixed
     */
    private function csvDecryption($encryptedCsv)
    {
        $this->logger->info('Déchiffrement');
        $privateKey = file_get_contents("/var/www/html/keys/client_private_key.txt");
// ou récupération de la clé privée depuis un serveur AWS S3 par exemple.
        $gpg = new Crypt_GPG();
        $info = $gpg->importKey($privateKey);
        $gpg->addDecryptKey($info[ 'fingerprint' ], "azerty123"); //azerty123 = passphrase
        $decryptedCsv = $gpg->decrypt($encryptedCsv);

        return $decryptedCsv;
    }
}