Gpg et Yubikey le nec plus ultra du chiffrement
Les clés GPG#
Je me suis enfin motivé à générer mes propres clés GPG. Je ne vais pas expliquer ce qu’est GPG : d’autres l’ont fait bien mieux que moi, et des articles très poussés existent si vous voulez le détail.
Si t’es dev ou admin sys et que ta clé SSH traîne en clair dans ~/.ssh/ sur ton disque, ou que tu n’as jamais signé un mail de ta vie, cet article te concerne.
Moi je voulais : chiffrer mes mails, chiffrer des fichiers, m’authentifier en SSH via GPG. Le tout sur une Yubikey.
Les Yubikeys#
Une Yubikey, c’est une petite clé USB. J’en ai pris deux, une USB-C et une USB-A, les deux avec NFC pour les utiliser depuis le téléphone aussi.
La procédure#
Génération de la clé maître#
Tout ça se fait sur une machine déconnectée d’internet, bootée sur un live USB. Il faut une distribution qui embarque tout le nécessaire. J’ai fait une clé Tails comme préconisé dans un des articles en sources.
J’ai téléchargé la dernière image Tails et flashé une clé USB depuis mon portable. Je branche, un lsblk pour identifier le bon device et ne pas faire de bêtises :
sudo dd bs=4M conv=fsync oflag=direct status=progress if=Téléchargements/tails-amd64-6.17.img of=/dev/sda
J’attends la fin, je reboote sur la clé. Tails me demande la langue, le clavier, la localisation. J’ouvre un terminal, on peut y aller.
Génération de la clé maître :
gpg --expert --full-generate-key
Le --expert permet de générer plus que des clés sign/chiffrer (nécessaire pour l’auth SSH). Le --full-generate-key ouvre un menu interactif.
Résultat :
➜ ~ gpg --expert --full-gen-key
gpg (GnuPG) 2.4.7; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Please select what kind of key you want:
(1) RSA and RSA
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC (sign and encrypt) *default*
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
(14) Existing key from card
L’option 11. Il y a des clés RSA et DSA mais de ce que j’en ai entendu, les plus solides sont les ECC à courbe elliptique. Me demandez pas pourquoi, les maths c’est pas mon domaine. Vous devriez être tranquille.
Surtout, on peut choisir les capabilities de chaque clé. Bien plus granulaire.
Je veux une clé maître qui ne fasse que de la certification, c’est-à-dire certifier d’autres clés.1
Your selection? 11
Possible actions for this ECC key: Sign Certify Authenticate
Current allowed actions: Sign Certify
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Les actions par défaut sont Sign et Certify. Pourquoi un défaut qui n’est pas une bonne pratique ? Voir ce lien.2 On toggle la capacité signature avec S. Le menu se réaffiche avec seulement Certify, on quitte avec Q.
Ensuite, le choix de la courbe elliptique. Si vous ne savez pas quoi prendre, ed25519 : rapide, sécurisé, largement supporté.
Puis l’expiration de la clé maître :
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Mettez une expiration, au cas où la clé fuiterait. Normalement elle finit dans un coffre-fort caché dans votre bunker, mais on ne sait jamais, un acteur malveillant peut mettre la main dessus et compromettre toutes les sous-clés générées avec. On peut rallonger la date d’expiration plus tard — pas encore testé, je pointe l’article qui en parle.3
Le prompt affiche la date d’expiration et demande confirmation. Puis votre nom. J’ai mis mon pseudo : votre nom apparaît dans la clé publique, que vous partagez partout, et je n’ai pas envie d’exposer mon identité réelle. Certains cas demandent la vraie identité — les contributeurs de gros projets open source, qui se retrouvent en événements pour se certifier leurs clés en présentant une pièce d’identité.4
Puis l’email. Tout ça forme une identité utilisateur (uid), on peut en ajouter d’autres plus tard. Récapitulatif, vérification, et une passphrase pour sécuriser la clé maître au cas où quelqu’un mettrait la main dessus.
Détail amusant : pendant la génération, gpg vous demande de taper au clavier ou bouger la souris pour générer des octets aléatoires et monter l’entropie. Des fois vous avez à peine le temps de faire quoi que ce soit.
La clé maître est générée. Récapitulatif :
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: directory '/home/b0dian/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/b0dian/.gnupg/openpgp-revocs.d/3FF5BE6BA84EDEDD21C4AE0DC1DDF61ADDB0003F.rev'
public and secret key created and signed.
pub ed25519 2025-07-18 [C] [expires: 2035-07-16]
3FF5BE6BA84EDEDD21C4AE0DC1DDF61ADDB0003F
uid test <test@ŧest.com>
Beaucoup d’infos : pub donne le type de clé (ed25519 ici), la date de création, les capacités (certification seule, c’est notre maître), l’expiration. En dessous, l’identifiant unique de la clé. Et l’uid, nom et mail.
Fiou. Suite.
Générer les sous-clés#
La clé maître va certifier des sous-clés qu’on génère. Retour aux commandes gpg :
gpg --expert --edit-key test@test.com
On peut utiliser l’identifiant unique ou le mail. Le mail marche si il n’est pas lié à d’autres clés, sinon on se mélange les pinceaux. Je n’ai qu’une clé avec ce mail, ça marche. (Il doit y avoir des puristes qui crient au scandale, je m’en tape.)
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
(14) Existing key from card
Trois sous-clés, une par usage : signer, chiffrer, s’authentifier. On répète addkey trois fois, option 11 (ECC avec capabilities custom) sauf pour le chiffrement où on prend le 12 (ECC encrypt only) — OpenPGP impose un algorithme différent pour le chiffrement (Curve25519/ECDH).
Sous-clé de signature (Sign only) : on toggle tout pour ne garder que S.
Sous-clé de chiffrement (Encrypt only) : option 12 directement, rien à toggler.
Sous-clé d’authentification (Authenticate only) : option 11, on toggle pour ne garder que A.
Un gpg --list-secret-keys pour vérifier :
sec ed25519 2025-07-18 [C] [expires: 2035-07-16]
3FF5BE6BA84EDEDD21C4AE0DC1DDF61ADDB0003F
uid [ultimate] Dimitri <monmail@example.com>
ssb ed25519 2025-07-18 [S] [expires: 2026-07-18]
ssb cv25519 2025-07-18 [E] [expires: 2026-07-18]
ssb ed25519 2025-07-18 [A] [expires: 2026-07-18]
La clé maître [C] et les trois sous-clés, chacune son rôle.
Sauvegarder avant tout#
Étape critique. Une fois les sous-clés transférées sur la Yubikey, elles n’en sortent plus jamais. Perdre la Yubikey sans backup, c’est perdre ses clés. Point.
On exporte tout avant de toucher à quoi que ce soit.
Lister les clés pour récupérer l’identifiant :
gpg --list-secret-keys
Puis exporter la maître et les sous-clés :
gpg --export-secret-keys --armor <ID> > master-key.asc
gpg --export-secret-subkeys --armor <ID> > subkeys.asc
gpg --export --armor <ID> > public-key.asc
Et le certificat de révocation, généré automatiquement à la création :
cp ~/.gnupg/openpgp-revocs.d/<ID>.rev revocation-cert.asc
Tout ça sur un support chiffré, déconnecté d’internet — une clé USB LUKS par exemple, rangée en lieu sûr. J’en ai fait plusieurs copies.
On est toujours sur Tails à ce stade : tout est en RAM, rien n’est écrit sur le disque de la machine hôte. C’est pour ça qu’il faut vraiment prendre le temps de copier ces fichiers avant d’éteindre.
Transférer les sous-clés sur les Yubikeys#
Backup au chaud, on peut y aller. On branche la première Yubikey et on entre en mode édition de la carte :
gpg --edit-key <ID>
key 1 pour sélectionner la première sous-clé (la [S]) — une étoile apparaît. Puis keytocard, et GPG demande le slot :
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
On répète pour les deux autres :
key 2puiskeytocard→ slot 2 (Encryption key)key 3puiskeytocard→ slot 3 (Authentication key)
Et save.
GPG remplace les sous-clés locales par un pointeur vers la carte (ssb>). C’est pour ça que le backup passait avant : les clés privées ne sont plus sur la machine, elles sont dans la Yubikey.
Pour la deuxième Yubikey, même procédure, mais il faut d’abord réimporter les sous-clés depuis le backup. Sinon GPG voit déjà les pointeurs carte et ne peut plus rien transférer.
gpg --import subkeys.asc
On branche la deuxième Yubikey et on répète le keytocard pour chaque sous-clé.
Vérifier que tout est en ordre#
gpg --list-secret-keys
Les sous-clés avec ssb> (le chevron) sont sur une carte. Si vous voyez ssb#, la clé privée n’est plus disponible localement — normal après un transfert sans réimport.
Pour voir ce qui est sur la Yubikey :
gpg --card-status
Les infos de la carte, les clés par slot, leurs fingerprints.
Cas concret : l’authentification SSH#
Le cas d’usage le plus utile au quotidien pour un profil DevOps. L’idée : la sous-clé d’authentification sur la Yubikey à la place d’une clé SSH classique. Ta clé privée ne quitte jamais la carte. Jamais.
Configurer gpg-agent pour SSH#
Dire à gpg-agent de gérer aussi le socket SSH. Dans ~/.gnupg/gpg-agent.conf :
enable-ssh-support
Puis dans ton .bashrc ou .zshrc :
export GPG_TTY=$(tty)
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent
On recharge le shell et on vérifie que l’agent voit la clé :
ssh-add -L
Ça retourne la clé publique SSH dérivée de la sous-clé [A]. C’est elle qu’on colle dans ~/.ssh/authorized_keys sur les serveurs.
Utilisation#
Rien de spécial, on se connecte comme d’habitude :
ssh user@monserveur.bzh
gpg-agent intercepte la demande, la transmet à la Yubikey, et selon la config la Yubikey demande un PIN ou un touch physique. Si quelqu’un vole ta machine, sans la Yubikey il ne s’authentifie pas. Beau, non ?
Bonus : signer ses commits Git#
Tant qu’on y est, on signe les commits avec la sous-clé [S] :
git config --global user.signingkey <ID>
git config --global commit.gpgsign true
Chaque git commit demande un touch sur la Yubikey. Les commits sortent avec le badge « Verified » sur GitHub/GitLab.
Sources#
- La documentation NixOS pour l’utilisation de Yubikey pour se connecter avec PAM
- La documentation NixOS pour l’utilisation de Yubikey pour chiffrer/déchiffrer ses disques — c’est ça qui a commencé à me mettre le pied à l’étrier. Avec une seule Yubikey je voulais chiffrer/déchiffrer mes disques et surtout m’authentifier sur mes machines NixOS. Autant la partie GPG est assez simple, autant la partie chiffrement des disques est velue !
- Le premier article que j’ai suivi pour effectuer la procédure avant de comprendre (grâce à l’article suivant) qu’il fallait backuper les clés avant de les exporter dans la Yubikey
- Un super article qui détaille toute la procédure pour setup deux Yubikeys pour s’authentifier en SSH avec GPG