Importer des clefs GnuPG dans sa Nitrokey Pro

Dans un précédent article j’ai présenté la Nitrockey Pro et fait un bref tour du propriétaire. Cette fois-ci je vais expliquer comment y importer des clefs PGP déjà existantes.

Bien entendu je pars sur un système déjà installé et configuré et part du principe que la Nitrokey est paramétrée (PIN utilisateur et administrateur, nom du propriétaire etc.)

Avant de commencer

Voici la composition des clefs:

  • une clé principale servant a créer des sous clefs, de les révoquer et de signer celles des copains.
  • une sous clé permettant de chiffrer
  • enfin une sous clé permettant de signer

A partir de là nous allons mettre mes deux sous clefs sur la Nitrokey et garder la clé principale dans un endroit sûr.

L’importation n’est pas très difficile et prendra qu’une minute. Par contre il est important de réaliser quelques opérations en plus :

  • Créer un certificat de révocations.
  • Sauvegarder comme il se doit la clé maître et ses sous clefs, le certificat de révocation. En effet l’opération d’importation de vos sous clefs les supprimera du dossier ~/.GnuPG/
  • Sortir ma Master Key du trousseau GnuPG pour la mettre en sécurité sur un périphérique de stockage externe (clé USB)

Réaliser une sauvegarde

Avant tout, il est important de garder une copie de sauvegarde de sa clé maître et de ses sous clefs au cas où une manipulation ne se passerait pas comme prévu. Exportons les clefs privées, publiques et le certificat de révocation dans un fichier compressé et chiffré.

Commençons par créer un dossier dans le répertoire /tmp afin de recevoir le certificat de révocation et les sauvegardes de clefs :

mkdir /tmp/gpg_backup
chmod 700 /tmp/gpg_backup

Certificat de révocation

Voici la commande utile pour créer un certificat de révocation pour notre clé maître :

gpg --gen-revoke --output /tmp/gpg_backup/revoke.cert <id>

<id> représente l’identifiant de la clé. Une boite de dialogue apparaît ensuite demandant la phrase de passe permettant de débloquer la clé privée.

Exporter les clefs

Commençons par la clé privée :

gpg --export-secret-keys --armor --output /tmp/gpg_backup/ephase_private.asc <id>

Bien entendu la phrase de passe de la clé sera demandée

Puis la clé publique, qui ne nécessite pas de phrase de passe pour être débloquée :

gpg --export --armor --output /tmp/gpg_backup/ephase_public.asc <id>

Créer une archive sécurisée

Bien entendu il ne faut pas que ces données (du moins le certificat de révocation et la clé privée) tombent entre de mauvaises mains, il suffit simplement de créer une archive chiffrée du dossier /tmp/gpg_backup :

tar cz -C '/tmp/' gpg_backup | gpg --symmetric --output ephase_key.gpg && rm -rf /tmp/gpg_backup

Après avoir rentré un mot de passe de chiffrement fort pour protéger notre sauvegarde, nous sommes fin prêt pour la suite des opérations. Pour restaurer le dossier il suffira d’utiliser la commande suivante :

gpg --decrypt ephase_key.gpg | tar xz

Mettre ce fichier à l’abri

Le fichier ephase_key.gpg sera mis à l’abri sur un espace de stockage hors ligne (voir même plusieurs).

Importer la paire de clefs

La manipulation se fait depuis la gestion de clefs gpg, nous y accédons avec la commande :

gpg --expert --edit-key <id>

gpg (GnuPG) 2.2.17; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

La clef secrète est disponible.

sec  rsa4096/XXXXXXXXXXXXXXXX
     créé : 2016-07-07  expire : 2020-07-12  utilisation : SC
     confiance : ultime        validité : ultime
ssb  rsa4096/YYYYYYYYYYYYYYYY
     créé : 2016-07-07  expire : 2020-07-12  utilisation : E
ssb  rsa4096/ZZZZZZZZZZZZZZZZ
     créé : 2016-07-07  expire : 2020-07-12  utilisation : S
[  ultime ] (1). Yorick Barbanneau <ephase@example.com>

gpg>

À partir de là nous allons procéder par étape :

  1. choisir la sous clé pour 1 (le chiffrement) et l’exporter dans le slot chiffrement sur la Nitrokey
  2. choisir la sous clé 2 (signature) et l’exporter dans le slot signature

La clé maitre sera sortie du trousseau et mise à l’abri.

Exporter la clé ¨Chiffrement¨

Voici les commandes à entrer pour exporter la première clé sur la Nitrokey :

gpg> key 1

[...]

gpg> keytocard

key 1 permet de dire à gpg que l’on travaille sur la première sous clé, et keytocard envoi celle-ci sur notre smartcard

gpg nous demande de déverrouiller en entrant la phrase de passe et le code PIN administrateur de la Nitrokey.

Exporter la clé ¨Signature¨

Il faut maintenant dé-sélectionner la sous clé 1 :

gpg> key 1

Pour copier la clé 2:

gpg> key 2

[...]

gpg> keytocard

Comme précédemment, gpg nous demande de déverrouiller en entrant la phrase de passe et le code PIN administrateur de la Nitrokey.

Sauvegarder les changements.

Il ne reste plus qu’à sauvegarder nos changement sur les clefs et quitter gpg

gpg> save

Les deux sous clefs seront alors supprimées de notre trousseau et disponible uniquement via la smartcard.

Mettre sa clé maître à l’abri

La clé maître est la plus importante des clefs, elle permet de créer d’autre sous clefs, d’émettre des certificats de révocation pour celles-ci ou encore de signer les clefs publique des amis.

Il est tout à fait possible de la sortir du trousseau pour la mettre à l’abri et de la remettre lorsque l’on en a besoin.

Pour ma part j’ai choisi de mettre la clé sur un support externe chiffré, et avec l’aide d’un script de monter le support lorsque j’en ai besoin et de créer un lien symbolique de la clé depuis le répertoire de GnuPG.

Les outils utilisés sont en général installés de base : LUKS et udisk

Créer le conteneur chiffré

Toutes les opérations suivantes se font en super utilisateur ou avec sudo.

Dans un premier temps partitionnons la clé USB (ici sdb):

parted -s /dev/sdb mklabel msdos mkpart primary ext4 1MiB 100%

Il nous faut ensuite créer le conteneur chiffré :

cryptsetup luksFormat /dev/sdb1
WARNING!
========
Cette action écrasera définitivement les données sur /dev/sdb1.

Are you sure? (Type uppercase yes): YES
Saisissez la phrase secrète pour /dev/sdb1 :
Vérifiez la phrase secrète :

Le déverrouiller :

cryptsetup luksOpen /dev/sdb1 gpg_master
Saisissez la phrase secrète pour /dev/sdb1 :

Pour le formater :

mkfs.ext4 -E root_owner=1000:1000 -m 0 /dev/mapper/gpg_master

Il faut bien entendu adapter le paramètre root_owner en fonction de votre UID et de votre GID.

Et enfin monter la partition avec :

mkdir -p /mnt/usb
mount /dev/mapper/gpg_master /mnt/usb

Puis s’assurer que la clé USB ne peut être lue seulement par notre utilisateur :

chmod 700 /mnt/usb

Déplacer la clé maitre GnuPG sur votre clé USB

Les commandes suivantes sont à faire dans la foulée mais en tant utilisateur courant.

Nous allons utiliser une fonctionnalité de GnuPG 2 : les clefs privées sont stockées dans le répertoire ~/.gnupg/private-keys-v1.d/ ou chaque fichier correspond à une clé et le nom est repris dans le champs keygrip :

gpg -K --with-keygrip 
/home/ephase/.gnupg/pubring.kbx
-------------------------------
sec   rsa4096 2016-07-07 [SC] [expire : 2020-07-12]
      3526F4565D76C5674AA56690936CDF3783293949
      Keygrip = ABCDEF1234567890ABCDEF1234567890ABCDEF12
uid          [  ultime ] Yorick Barbanneau <ephase@example.com>
ssb>  rsa4096 2016-07-07 [E] [expire : 2020-07-12]
      Keygrip = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
ssb>  rsa4096 2016-07-07 [S] [expire : 2020-07-12]
      Keygrip = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

Je doit donc chercher la clé 3526F4565D76C5674AA56690936CDF3783293949.key et la copier sur notre clé :

mkdir -p /mnt/usb/.gpg_master
chown 700 /mnt/usb/.gpg_master
mv ~/.gnupg/private-keys-v1.d/3526F4565D76C5674AA56690936CDF3783293949.key /mnt/usb/.usbmaster

Afin de bien vérifier que la clé n’est plus disponible, il suffit de faire :

gpg -K
/home/ephase/.gnupg/pubring.kbx
-------------------------------
sec#  rsa4096 2016-07-07 [SC] [expire : 2020-07-12]
      3526F4565D76C5674AA56690936CDF3783293949
uid          [  ultime ] Yorick Barbanneau <ephase@example.com>
ssb>  rsa4096 2016-07-07 [E] [expire : 2020-07-12]
ssb>  rsa4096 2016-07-07 [S] [expire : 2020-07-12]

Le # à côté de sec indique que la clé maître n’est plus disponible dans le trousseau GnuPG.

Automatiser le montage de la clé

Afin de faciliter les opérations de montage et démontage de la clé USB contenant notre clé maître, on va s’aider d’un script.

L’utilisation est simple, une fois mis dans un endroit accessible via le $PATH il suffit de faire gpgmount.sh m pour monter la clé USB ou gpgmount.sh u pour la démonter.

#!/bin/bash

UUID=""
mountpoint=""

usage () {
cat <<EOF 
$0 m | u
$0 mount | unmount

mount or unmount encrypted device based on UUID and attach private keys
EOF
}

if [ -L "/dev/disk/by-uuid/${UUID}" ]
then
    case "$@" in
        "m"|"mount")

            echo "Mount encryted key"
            action=$(udisksctl unlock -b /dev/disk/by-uuid/${UUID})

            if [ ! $? -eq 0 ]
            then
                echo $action
                exit 10
            fi
            mountpoint=$(udisksctl mount -b /dev/mapper/luks-${UUID} | \
                awk '{print $4}')

            while read -r f
            do
                base=$(basename $f)

                #create symlink to key file if not exist
                if [ ! -e "~/.gnupg/private-keys-v1.d/$base" ]
                then
                    ln -s $f ~/.gnupg/private-keys-v1.d/$base
                fi
            done < <(find ${mountpoint%.}/.gpg_master/ -type f -name "*.key")
        ;;
        "u"|"unmount")
            echo "unmount encrypted key"
            while read -r f
            do
                rm $f
            done < <(find ~/.gnupg/private-keys-v1.d -type l -name "*.key")

            udisksctl unmount -b /dev/mapper/luks-${UUID} 2&> /dev/null || \
                echo "Volume is already unmounted"
            udisksctl lock -b /dev/disk/by-uuid/${UUID} 2&> /dev/null || \
                echo "Encrypted container is not unlocked"
        ;;
        *)
            echo "parameter not understood, what do you want :"
            usage
            exit 1
        ;;
    esac
else
    echo "USB device $UUID is not connected"
    exit 5
fi

exit 0

Il faut bien entendu mettre l’uuid de la partition contenant notre clé maître dans la variable UUID.

Pour le récupérer il suffit de lancer la commande blkid en tant que root avec en paramètre la partition en question:

blkid /dev/sdb1
/dev/sdb1: UUID="<uuid>" TYPE="crypto_LUKS" PARTUUID="<partuuid>"

En conlusion

J’ai essayé ici de créer un environnement équilibré entre sécurité et facilité. La Nitrokey permet donc de sécuriser mes sous clefs utilisées tous les jours tout en les rendant disponibles sur mes deux machines principales.

Bien sûr il serait plus sécurisé de n’utiliser la clé maître sur une machine totalement hors ligne démarrée par une distribution live. Mais avouez que pour signer les clé des amis (lors de chiffro-fête par exemple), ce n’est pas l’idéal.

Bibliographie

Kernel Maintainer PGP guide — The Linux Kernel documentation par Konstantin Ryabitsev - lien

Using an offline GnuPG master key (2015) par Damien Goutte-Gattat - lien