Introduction

Le Web of Trust (WoT) est un concept utilisé dans le domaine de la sécurité informatique et de la cryptographie. Il s’agit d’un modèle de confiance décentralisé qui permet de vérifier l’authenticité des identités numériques et de garantir l’intégrité des communications.

Dans le contexte de la cryptographie à clé publique, le Web of Trust est utilisé pour valider les clés publiques des utilisateurs. Chaque utilisateur peut générer une paire de clés, composée d’une clé privée et d’une clé publique. La clé privée est gardée secrète par l’utilisateur, tandis que la clé publique est partagée avec les autres. Lorsque quelqu’un souhaite communiquer de manière sécurisée, il peut vérifier l’authenticité de la clé publique de son interlocuteur.

Bon, c’était la définition académique, pour faciliter la compréhension, voici un exemple concrêt.

Spam president lingot

Je reçois ce mail m’indiquant qu’un président d’un pays que je ne connais pas veut me donner des lingots d’or. Quelle chance ! Je vais tout de suite aller acheter une carte PSC pour payer les frais de dossier.

Et comme vous vous en doutez déjà, c’est bien un spam.

Mais comment puis-je le savoir ? Dans cet exemple, c’est assez simple : ce genre de mail est un classique du spam. Mais dans d’autres cas, il peut être plus difficile de distinguer les messages légitimes des messages frauduleux. Prenons un nouvel exemple :

Joël qui deteste kubevirt ?

Joël vient de m’envoyer ce mail pour préparer notre prochaine émission CuistOps. Mais avez-vous remarqué quelque chose d’étrange ?

Bien sûr, Joël adore Kubevirt, ce message est obligatoirement un faux ! Joël s’est fait pirater son compte mail et quelqu’un d’autre a envoyé ce mail à sa place.

Comment en être certain ? N’y a-t-il pas un moyen sûr de vérifier l’authenticité d’un mail ?

La réponse est oui, avec des clés PGP.

Qu’est-ce que PGP ?

PGP (Pretty Good Privacy) est une méthode de cryptographie qui permet de chiffrer et de signer des messages électroniques. Il utilise un système de clés publiques et privées pour garantir la confidentialité et l’intégrité des communications.

Par exemple, je possède une paire de clés PGP : une clé privée que je garde secrète et une clé publique que je partage avec les autres utilisateurs. Lorsque Joël m’envoie un mail, il peut le chiffrer avec ma clé publique de sorte que seul moi puisse le déchiffrer avec ma clé privée. De même, si je veux lui envoyer un mail, je peux le signer avec ma clé privée pour attester de mon identité et de l’intégrité du message.

Sauf si quelqu’un pirate l’une de nos clés privées, il est théoriquement impossible de déchiffrer (modulo la puissance de calcul des ordinateurs quantiques qui pourrait craquer le RSA) ou de signer un message sans la clé privée correspondante.

GPG

GPG (GNU Privacy Guard) est une implémentation libre et open-source de PGP. Il permet de chiffrer, de signer et de vérifier des messages électroniques en utilisant des clés publiques et privées. GPG est largement utilisé dans le monde de la sécurité informatique et de la cryptographie pour garantir la confidentialité et l’intégrité des communications (notamment avec les gestionnaires de paquets comme apt ou yum).

CA vs GPG

Il pourrait être tentant de comparer GPG à une autorité de certification (CA) comme Let’s Encrypt. Mais il y a une différence majeure entre les deux : les CA sont des systèmes centralisés dans lequel un tiers de confiance (la CA) signe les clés des utilisateurs. Cela signifie que nous devons faire confiance au CA pour valider les clés publiques des autres personnes.

Tandis que le GPG est un système décentralisé dans lequel les utilisateurs valident eux-mêmes les clés de leurs pairs.

Comment obtenir la clé publique de quelqu’un ?

Une notion importante du Web of Trust est la vérification de l’authenticité des clés publiques. Si Joël m’envoie sa clé publique par mail, comment puis-je être sûr que c’est bien la sienne et non celle d’un pirate ?

L’idéal est de vérifier la clé publique de Joël par un moyen sécurisé et fiable (par exemple, au cours d’une rencontre en face à face ou par téléphone). Il existe même des Key Signing Party où les utilisateurs se rencontrent pour échanger et valider leurs clés publiques.

Mais qu’en est-il des personnes que je ne connais pas ? Comment puis-je vérifier leur clé publique ?

Pour cela, il existe des serveurs de clés PGP qui permettent de stocker et de partager les clés publiques des utilisateurs.

J’utilise personnellement keys.openpgp.org et pgp.mit.edu pour stocker et partager ma clé publique.

Clé publique

N’importe qui peut consulter ces serveurs pour récupérer la clé publique d’un utilisateur. Mais attention, il est important de multiplier les sources pour vérifier l’authenticité de la clé (par exemple, en consultant plusieurs serveurs de clés).

On utilise les adresses mails pour rechercher les clés publiques, mais rien ne m’empêche de mettre une autre adresse mail que la mienne dans ma clé publique (il n’y a aucune vérification par mail lors de la soumission d’une clé sur ces serveurs).

Pour ceux qui utilisent Github (et sinon on verra ça plus bas) vous pouvez aussi ajouter votre clé publique sur votre profil.

Pour afficher la clé d’un membre de Github, il suffit de rajouter .gpg à la fin de l’URL de son profil comme ceci

Les smartcards (Yubikey)

Les smartcards sont des cartes à puce qui permettent de stocker des clés privées. Elles offrent une sécurité supplémentaire en isolant les clés privées du système hôte.

Par exemple, le type de smartcard le plus connu est la Yubikey, mais il en existe d’autres comme la Nitrokey ou certaines Ledger.

Il en existe de plusieurs formats avec plusieurs connectiques, dans cet article, je vais utiliser une Yubikey 5 NFC.

Contexte

Tout a commencé avec l’article de Joseph Ligier : Créer un provider Terraform.

J’ai développé mon propre provider pour apprendre le fonctionnement interne de Terraform (et pour le fun).

Et lors de la publication de ma première version sur le registre d’Hashicorp, j’ai réalisé qu’il me fallait générer une clé GPG pour signer ma release. J’ai déjà eu l’usage de GPG brièvement, mais je me contentais juste de copier / coller les commandes sans vraiment comprendre ce que je faisais.

J’ai commencé à me renseigner sur le sujet, d’autant plus que j’ai quelques Yubikey qui trainent dans mes tiroirs (Merci Cloudflare).

Yubikey

Mon objectif est alors d’apprendre à utiliser les clés GPG pour signer mes commits, chiffrer mes échanges par mail, et sécuriser mes livrables.

Avertissement

Je suis totalement débutant dans le domaine de la cryptographie, je vais appliquer ce que j’ai vu sur internet et ce que j’ai compris. Si vous voyez des erreurs, n’hésitez pas à me le dire.

Comment fonctionne une clé GPG ?

Ce fut la première question que je me suis posée. Je suis assez rapidement tombé sur l’incroyable article de Dave Steele Anatomy of a gpg key qui semble être une référence sur les forums.

Cet article explique les différents concepts à connaître pour comprendre le fonctionnement d’une clé GPG.

Par exemple, une clé GPG peut posséder plusieurs permissions :

  • C (Certifier) : Permet de certifier les clés publiques des autres utilisateurs.
  • S (Signer) : Permet de signer les messages électroniques.
  • E (Encrypt) : Permet de chiffrer les messages électroniques.
  • A (Authenticate) : Permet d’authentifier l’utilisateur.

Ces permissions peuvent être cumulées sur une même clé ou réparties sur plusieurs sous-clés. Ainsi, il est possible de créer une clé principale avec la permission C et des sous-clés avec les permissions S, E et A (pour séparer les usages).

Une sous-clé (subkey) est une clé secondaire à une clé principale. Comme dit plus haut, celle-ci possède ses propres permissions et sa propre date d’expiration. La clé principale est la clé qui certifie ou révoque les sous-clés.

schéma des subkeys

Il existe aussi plusieurs manières d’afficher une clé GPG :

  • La version longue (ex : 355E36632085C9386A872739FB44D16A0CBA859C)
  • La version courte (ex : 0CBA859C) correspondant aux huit derniers caractères de la version longue.
  • L’empreinte (ex : 355E 3663 2085 C938 6A87 2739 FB44 D16A 0CBA 859C) correspondant à la version longue avec des espaces tous les quatre caractères.

En fonction du support sur lequel vous souhaitez afficher la clé, il peut être plus ou moins pratique d’utiliser l’une ou l’autre de ces versions.

Générer notre clé GPG

Passons maintenant au vif du sujet. On va générer une clé ed25519 qui va avoir pour objectif de certifier notre identité. Les autres actions (Encrypt, sign, authentificate) seront dans d’autres clés (subkeys).

Information

Pourquoi utiliser une clé ed25519 et non une clé RSA ?

Les clés RSA sont basées sur la factorisation de grands nombres premiers, tandis que les clés ed25519 sont basées sur les courbes elliptiques. Les clés ed25519 sont généralement plus courtes que les clés RSA pour un même niveau de sécurité, ce qui les rend plus efficaces en termes de stockage et de transmission (et usage de ressources).

Source : OLLAMA

gpg --expert --full-gen-key

Durant la question sur les capacités de la clé, on va choisir “Certifier” uniquement (donc retirer chiffrement, signature et authentification).

Actions possibles pour une clef RSA : Signer Certifier Chiffrer Authentifier
Actions actuellement permises : Certifier

   (S) Inverser la capacité de signature
   (C) Inverser la capacité de chiffrement
   (A) Inverser la capacité d'authentification
   (Q) Terminé

Quel est votre choix ?

J’ai choisi 4096 bits pour la taille de la clé et une expiration d’ici à 15 ans.

On vérifie que nous possédons bien notre clé gpg dans notre trousseau :

$ gpg --list-keys
/home/quentinj/.gnupg/pubring.kbx
---------------------------------
pub   ed25519/0CBA859C 2024-03-28 [C] [expire : 2029-03-27]
 Empreinte de la clef = B57F A3AD 4B0E 03E3 74FB  1F80 E12F DC61 2638 EC5E
uid

Elle expire bien dans 15 ans, et possède une confiance en “ultime” (puisque c’est nous qui venons de la générer). Sa seule permission est C (Certifier).

Pour vérifier que notre clé est bien importée, on peut de nouveau lister les clés. (maintenant, la confiance envers notre clé est “inconnue” car nous ne connaissons pas sa provenance)

$ gpg --list-keys
/home/quentinj/.gnupg/pubring.kbx
---------------------------------
pub   ed25519/0CBA859C 2024-03-28 [SC] [expire : 2029-03-27]
 Empreinte de la clef = CC52 8FF7 528A 6637 62F7  807F 93DB 5081 C95D 5F29
uid                  [ inconnue] Quentin JOLY (une-tasse-de.cafe) <quentinj@une-pause-cafe.fr>
sub   rsa4096/0xC5185FB21336FF05 2024-03-28 [E] [expire : 2029-03-27]

Pour remettre un niveau de confiance ultime à notre clé, on va indiquer à notre trousseau que nous avons confiance en notre clé.

$ gpg --edit-key quentinj@une-pause-cafe.fr
gpg> trust
sec  ed25519/0CBA859C
     créé : 2024-03-28  expire : 2029-03-27  utilisation : C
     confiance : inconnu       validité : inconnu
[ inconnue] (1). Quentin JOLY (une-tasse-de.cafe) <quentinj@une-pause-cafe.fr>

Décidez maintenant de la confiance que vous portez en cet utilisateur pour
vérifier les clefs des autres utilisateurs (en regardant les passeports, en
vérifiant les empreintes depuis diverses sources, etc.)

  1 = je ne sais pas ou n'ai pas d'avis
  2 = je ne fais PAS confiance
  3 = je fais très légèrement confiance
  4 = je fais entièrement confiance
  5 = j'attribue une confiance ultime
  m = retour au menu principal

Quelle est votre décision ? 5
Voulez-vous vraiment attribuer une confiance ultime à cette clef ? (o/N) o

sec  ed25519/0CBA859C
     créé : 2024-03-28  expire : 2029-03-27  utilisation : C
     confiance : ultime        validité : inconnu
[ inconnue] (1). Quentin JOLY (une-tasse-de.cafe) <quentinj@une-pause-cafe.fr>
Veuillez remarquer que la validité affichée pour la clef n'est pas
forcément correcte avant d'avoir relancé le programme.

Générons ensuite les sous-clés dédiées aux actions de chiffrement, signature et authentification.

Remarque

Pourquoi utiliser des subkeys ?

Les subkeys permettent de séparer les différentes actions possibles avec une clé GPG. Celles-ci peuvent être utilisées séparément et peuvent être révoquées indépendamment de la clé principale.

Souvent, nous créons une clé principale de longue durée et des subkeys de plus courte durée pour les actions de chiffrement, signature et authentification.

De plus, dans le cadre de notre Yubikey, nous allons pouvoir stocker les subkeys sur la carte et la clé principale dans un lieu sûr. Ainsi, si jamais je perds ma Yubikey (et les codes qui vont avec), je pourrais révoquer les subkeys sans avoir à révoquer la clé principale.

Clé uniquement pour chiffrer (E) :

gpg --edit-key --expert quentinj@une-pause-cafe.fr
gpg> addkey
--> (8) RSA (indiquez vous-même les capacités)
gpg> 8
Actions possibles pour une clef RSA : Signer Chiffrer Authentifier
Actions actuellement permises : Chiffrer

   (S) Inverser la capacité de signature
   (C) Inverser la capacité de chiffrement
   (A) Inverser la capacité d'authentification
   (Q) Terminé

Je fais pareil pour les clés de signature et d’authentification.

---------------------------------
pub   ed25519 2024-03-29 [C] [expire : 2039-03-26]
      355E36632085C9386A872739FB44D16A0CBA859C
uid          [ inconnue] Quentin JOLY <quentinj@une-pause-cafe.fr>
sub   ed25519 2024-03-29 [S] [expire : 2026-03-29]
sub   ed25519 2024-03-29 [A] [expire : 2026-03-29]
sub   cv25519 2024-03-29 [E] [expire : 2026-03-29]

Si vous souhaitez voir la démarche complète en vidéo :

asciicast

Sauvegarder sa clé

Maintenant que nous avons généré notre clé, il est important de la sauvegarder en lieu sûr (au cas où nous la perdions ou que nous devions la révoquer).

Pour exporter ma clé publique, je vais exporter la clé principale et ses sous-clés.

gpg --export --armor quentinj@une-pause-cafe.fr > public.key

Information

Lorsque vous utilisez votre clé avec GPG, il est possible d’indiquer directement l’adresse mail utilisée par la clé si vous n’avez qu’une seule clé correspondant à cette adresse. Sinon, vous devrez utiliser l’identifiant de la clé (version longue, courte ou empreinte).

Je vais aussi sauvegarder ma clé privée principale ainsi que les clés privées des subkeys :

gpg --export-secret-keys --armor quentinj@une-pause-cafe.fr > private.key
gpg --export-secret-subkeys --armor quentinj@une-pause-cafe.fr > private-subkeys.key

Pour tester si notre clé est bien exportée et fonctionnelle, je vais la supprimer de mon trousseau et la réimporter.

gpg --delete-secret-keys quentinj@une-pause-cafe.fr
gpg --delete-keys quentinj@une-pause-cafe.fr

Les commandes gpg --list-keys et gpg --list-secret-keys ne devraient plus rien retourner.

gpg --import private.key

Pour tester si notre clé est bien fonctionnelle et que les sous-clés sont bien importées, on peut signer un message et le vérifier

$ echo -n "P'tit kawa ? " | gpg --clear-sign | gpg -d
P'tit kawa ?
gpg: Signature faite le ven. 29 mars 2024 09:20:35 CET
gpg:                avec la clef EDDSA 6C696783A87F328594ECB3A079C81E0291249128
gpg: Bonne signature de « Quentin JOLY <quentinj@une-pause-cafe.fr> » [ultime]

Configuration de la Yubikey

La première chose à faire est de personnaliser les codes de déverrouillage et d’administration de la Yubikey.

Mais avant ça, je vais m’assurer que la clé soit bien reconnue par mon système.

$ gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: D2760001240103040006224123450000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 22412345
Name of cardholder: [non positionné]
Language prefs ...: [non positionné]
Salutation .......:
URL of public key : [non positionné]
Login data .......: [non positionné]
Signature PIN ....: non forcé
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

Très bien ! On obtient pleins d’informations comme le nombre de mauvais codes PIN avant que la clé ne se bloque, la marque et des métadonnées vides (comme le nom du propriétaire de la clé).

On va commencer par changer le code d’administration et le code de déverrouillage.

gpg --card-edit
gpg/carte> passwd

Il vous sera demandé de saisir le code de déverrouillage actuel (qui est 123456 par défaut). Ensuite, vous pourrez saisir le nouveau code de déverrouillage.

Après ça, on passe en mode admin pour changer le code d’administration.

gpg/carte> admin
Les commandes d'administration sont permises
gpg/carte> passwd
gpg: carte OpenPGP nº D2760001240103040006224123450000 détectée

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Quel est votre choix ? 4

Le code d’administration permet d’outrepasser le code de déverrouillage et de réécrire les clés sur la carte. Par défaut, c’est 12345678.

Vous pouvez aussi en profiter pour mettre vos informations sur la carte :

  • Nom
  • Sexe
  • URL de la clé publique (indispensable pour utiliser la clé privée)

Migrer sa clé privée vers une Yubikey

Maintenant que nous avons notre clé GPG et que notre Yubikey est configurée, nous allons migrer notre clé privée sur la Yubikey. Pour cela, nous allons d’abord migrer notre clé principale, puis sélectionner chaque sous-clé une par une pour les migrer sur la Yubikey.

La Yubikey possède 4 emplacements pour les clés :

  • Une pour signer les messages
  • Une pour chiffrer les messages
  • Une pour authentifier l’utilisateur
  • Une pour stocker la clé principale

Bien sûr, il est possible que ça soit la même clé qui soit utilisée pour toutes les actions (mais si vous avez suivi les étapes précédentes, vous avez généré des sous-clés pour chaque action).

Nous allons commencer par envoyer la clé principale et sélectionner chaque clé une par une pour les envoyer sur la Yubikey.

gpg --edit-key quentinj@une-pause-cafe.fr
gpg> keytocard # envoyer la clé principale sur la carte
gpg> key 1 # selectionner la clé de chiffrement
gpg> keytocard # envoyer la clé de chiffrement sur la carte
gpg> key 2 # selectionner la clé de signature
gpg> key 1 # déselectionner la clé de chiffrement
gpg> keytocard # envoyer la clé de signature sur la carte
gpg> key 3 # selectionner la clé d'authentification
gpg> key 2 # déselectionner la clé de signature
gpg> keytocard # envoyer la clé d'authentification sur la carte
gpg> save

C’est peut-être plus parlant en vidéo :

asciicast

Nous devrions avoir une sortie similaire à celle-ci :

$ gpg --list-secret-keys --keyid-format short               
/home/quentinj/.gnupg/pubring.kbx
---------------------------------
sec#  ed25519/0CBA859C 2024-03-29 [C] [expire : 2039-03-26]
      355E36632085C9386A872739FB44D16A0CBA859C
uid        [ inconnue] Quentin JOLY <quentinj@une-pause-cafe.fr>
ssb>  ed25519/6CF3343F 2024-03-29 [S] [expire : 2026-03-29]
ssb>  ed25519/D6A95E93 2024-03-29 [A] [expire : 2026-03-29]
ssb>  cv25519/CD5E8E4D 2024-03-29 [E] [expire : 2026-03-29]
  • sec# signifie que la clé est absente de notre trousseau et n’est pas utilisable (elle est sur la Yubikey).
  • ssb> signifie que notre trousseau GPG fait référence à une clé stockée sur la Yubikey.

Astuce

Dès lors que nos clés sont présentes sur la Yubikey, nous pouvons également activer le fait de devoir toucher la clé pour signer ou déchiffrer un message.

ykman openpgp keys set-touch sig on
ykman openpgp keys set-touch dec on

Cette pratique permet de s’assurer qu’un attaquant ne puisse pas utiliser notre clé en ayant un simple accès shell à notre machine.

Signer ses commits avec sa clé

En scrollant sur Xwitter durant la découverte de la faille xz (cve-2024-3094), je suis tombé sur ce tweet.

Tweet

On sait tous qu’avec Git, il est possible de modifier le mail / nom de l’auteur d’un commit, ça n’est un secret pour personne. Mais comment être sûr qu’un commit a bien été réalisé par la personne qui prétend l’avoir fait ? Je peux très bien me connecter sur mon compte Github, et réaliser un commit en utilisant le nom / email de Joël (l’authentification de Github ne permet que d’autoriser un commit à être push, pas son contenu).

Pour cela, il n’existe pas de solution miracle : il faut signer ses commits.

La première étape est de partager sa clé publique avec le serveur Git(Gitlab, Github, Bitbucket, etc).

Pour afficher sa clé publique en format ASCII, il suffit de taper la commande gpg --armor --export {KEYID}.

gpg --armor --export quentinj@une-pause-cafe.fr

Pour Github, collez le contenu de votre publique dans la section “GPG keys” via cette URL


Maintenant que Github reconnait notre clé, nous allons configurer Git pour qu’il l’utilise pour signer nos commits.

Assurez-vous d’utiliser la même adresse mail que celle utilisée pour générer votre clé GPG.

$ git config --get user.email 
quentinj@une-pause-cafe.fr

Demandez à Git d’utiliser cette même clé :

git config user.signingkey quentinj@une-pause-cafe.fr

Pour signer un commit, vous pouvez utiliser l’option -S :

git commit -S -m "chore: update docker image to 1.2"

Pour chiffrer systématiquement les commits, vous pouvez rajouter l’option commit.gpgsign à true dans la configuration de Git (ou un seul dépôt en ne mettant pas le flag --global) :

git config --global commit.gpgsign true

Les futurs commits vous demanderont de déverrouiller votre Yubikey (et de toucher la Yubikey si vous avez activé ce paramètre) pour signer le commit.

Dans l’historique des commits, vous pouvez voir directement sur Github si un commit est signé ou non.

Commit signé

Ou directement dans le terminal avec la commande git log --show-signature :

commit ade7e85223f55d36438d0a1148e0ddb6048ab4ce (HEAD -> page/yubikey, origin/page/yubikey)
gpg: Signature faite le mar. 01 avril 2024 15:04:25 CEST
gpg:                avec la clef EDDSA 7D51CDAB6D8994BFCA779C73431E06336CF3343F
gpg:                issuer "quentinj@une-pause-cafe.fr"
gpg: Bonne signature de « Quentin JOLY <quentinj@une-pause-cafe.fr> » [inconnu]
gpg: Attention : cette clef n'est pas certifiée avec une signature de confiance.
gpg:          Rien n'indique que la signature appartient à son propriétaire.
Empreinte de clef principale : 355E 3663 2085 C938 6A87  2739 FB44 D16A 0CBA 859C
     Empreinte de la sous-clef : 7D51 CDAB 6D89 94BF CA77  9C73 431E 0633 6CF3 343F
Author: QJoly <quentinj@une-pause-cafe.fr>
Date:   Tue Apr 1 15:04:25 2024 +0200

    Update Yubikey blog post

commit e7f2a4036d41d62f1fd9ddb0d23830f047543524
gpg: Signature faite le mar. 01 avril 2024 14:44:45 CEST
gpg:                avec la clef EDDSA 7D51CDAB6D8994BFCA779C73431E06336CF3343F
gpg:                issuer "quentinj@une-pause-cafe.fr"
gpg: Bonne signature de « Quentin JOLY <quentinj@une-pause-cafe.fr> » [inconnu]
gpg: Attention : cette clef n'est pas certifiée avec une signature de confiance.
gpg:          Rien n'indique que la signature appartient à son propriétaire.
Empreinte de clef principale : 355E 3663 2085 C938 6A87  2739 FB44 D16A 0CBA 859C
     Empreinte de la sous-clef : 7D51 CDAB 6D89 94BF CA77  9C73 431E 0633 6CF3 343F
Author: QJoly <quentinj@une-pause-cafe.fr>
Date:   Tue Apr 1 14:44:45 2024 +0200

    Update email address in fr.json

Sachant que ma clé est en confiance inconnue, Git me signale bien que la signature du commit provient d’un tiers de confiance inconnu

Si je modifie la confiance de ma clé publique à “ultime”, Git n’affichera plus cet avertissement.

Information

Pour ceux qui ne veulent pas passer à GPG, j’ai découvert qu’il était aussi possible de signer ses commits avec une clé SSH : Documentation Gitlab.

Chiffrer ses échanges par mail

Passons au chiffrement de nos mails avec Thunderbird (un des objectifs premiers de cet article).

La plupart des clients mails supportent à présent nativement le PGP (avant, il fallait installer un plugin comme Enigmail). Thunderbird est mon client mail pour le travail et pour les mails personnels, je vais donc l’utiliser dans la suite de cet article (mais bien d’autres clients supportent le PGP).

Ajouter sa clé publique

Allez dans les paramètres du compte sur lequel vous souhaitez activer PGP, puis “End-to-end encryption” (ou “Chiffrement bout-à-bout” en français).

Dans la section “OpenPGP”, cliquez sur “Add key”, sélectionnez ensuite l’usage d’une clé externe (votre Yubikey). Add key

Si l’option ne s’affiche pas, c’est qu’elle n’est pas activée dans Thunderbird. Pour la rendre disponible, il faut ouvrir l’éditeur de configuration de Thunderbird et activer l’option mail.openpgp.allow_external_gnupg à true.

Config Editor

Activer option

Vous pouvez entrer l’ID de votre clé (disponible via gpg -k).

Add key

Ensuite, ouvrez le gestionnaire de clé, et importez votre clé publique.

Import public

Vous êtes maintenant fins prêts pour envoyer et recevoir des mails chiffrés.

Tester l’envoi d’un mail chiffré

Pour tester l’envoi d’un mail chiffré, vous pouvez envoyer un mail à Edward, un bot qui répondra automatiquement à vos mails.

Utilisez votre compte fraichement configuré pour envoyer un mail à edward-fr@fsf.org.

Edward

Thunderbird nous affiche un avertissement comme quoi la clé publique d’Edward n’est pas connue.

Cliquez sur “Resolve” pour que l’on vous propose deux choix :

  • Importer la clé publique d’Edward via un fichier.
  • Aller contacter différents serveurs de clés pour trouver la clé publique d’Edward (à partir de son mail).

À savoir que peu importe la méthode choisie, il faut toujours valider la clé importée (en contactant votre interlocuteur par un moyen sécurisé et fiable, ou en vérifiant cette clé publique sur une autre source).

Après quelques secondes, on reçoit la réponse d’Edward qui devrait être celle-ci :

Mail chiffre


Lorsqu’on indique à Thunderbird de chiffrer un mail, celui-ci va activer 3 options :

  • Chiffrer le contenu du mail.
  • Chiffrer l’objet du mail.
  • Signer le mail.

Sign

Une signature sert à prouver à votre destinataire que le message a bien été envoyé par vous. C’est une garantie d’intégrité du message (et de son origine). Ce mécanisme peut être activé systématiquement puisque le récepteur n’a pas besoin d’une paire de clés pour vérifier la signature, ma femme (n’utilisant pas de PGP) peut donc lire mes mails signés sans avoir à déchiffrer quoi que ce soit.

Pour un client non compatible avec le PGP, une signature sera sous forme d’un fichier texte attaché au mail.

Et sur Android ?

Je consulte régulièrement mes mails sur mon téléphone, il est alors vital que je puisse déchiffrer mes mails directement depuis mon téléphone. Par chance, l’application que j’utilise au quotidien est compatible avec le PGP : k-9 mail.

Dans les paramètres de mon compte mail, puis “Chiffrement de bout en bout”, je vais activer le chiffrement PGP. K-9 me demande alors d’installer l’application OpenKeychain qui fera le lien entre ma Yubikey et mon client mail.

Une fois installé, j’ouvre OpenKeyChain pour ajouter ma clé. J’utilise la puce NFC présente sur ma Yubikey sur le dos de mon téléphone pour importer ma clé.

Importer une clé sur Android

Maintenant, je peux essayer d’envoyer un mail chiffré depuis mon téléphone.

Avant l’envoi du mail, je peux cocher le fait de chiffrer / signer mon mail. OpenKeyChain me demandera de scanner par Yubikey (par NFC).

NFC importer clé

Je peux également gérer les identités de mes contacts comme sur GPG :

Gestion du trousseau

Signer ses livrables

Il est possible de générer des fichiers signatures pour garantir l’intégrité des fichiers que vous partagez (ainsi que sa provenance) Le principe est le même qu’un checksum sauf que cette signature est générée avec ma clé privée et peut être vérifiée avec ma clé publique (donc je suis le seul à pouvoir générer cette signature tandis qu’un checksum peut être créé par n’importe qui).

Pour générer une signature, vous pouvez utiliser la commande suivante :

gpg --sign [fichier]

Pour vérifier une signature, vous pouvez utiliser la commande suivante :

gpg --verify [fichier.gpg]

Par exemple, je souhaite envoyer le fichier sujet-cuistops.pdf à Joël.

Joël dispose déjà de ma clé publique dans son trousseau GPG.

joel@cuistops:~$ gpg -k
/home/joel/.gnupg/pubring.kbx
------------------------
pub   ed25519 2024-03-29 [C] [expires: 2039-03-26]
      355E36632085C9386A872739FB44D16A0CBA859C
uid           [ultimate] Quentin JOLY <quentinj@une-pause-cafe.fr>
sub   ed25519 2024-03-29 [S] [expires: 2026-03-29]
sub   ed25519 2024-03-29 [A] [expires: 2026-03-29]
sub   cv25519 2024-03-29 [E] [expires: 2026-03-29]

Je peux créer la signature du fichier sujet-cuistops.pdf avec la commande suivante :

quentin@cuistops:~$ gpg --sign sujet-cuistops.pdf

J’obtiens donc le fichier sujet-cuistops.pdf.gpg que je vais envoyer à Joël.

Il peut alors vérifier que le fichier provient bien de moi.

joel@cuistops:~/Documents$ gpg --verify sujet-cuistops.pdf.gpg
gpg: Signature made Sun 31 Mar 2024 11:55:32 CEST
gpg:                using EDDSA key 7D51CDAB6D8994BFCA779C73431E06336CF3343F
gpg: Good signature from "Quentin JOLY <quentinj@une-pause-cafe.fr>" [ultimate]

Si le fichier est signé correctement, il peut le déchiffrer avec la commande suivante :

joel@cuistops:~/Documents$ gpg --output sujet-cuistops.pdf --decrypt sujet-cuistops.pdf.gpg
gpg: Signature made Sun 31 Mar 2024 11:55:32 CEST
gpg:                using EDDSA key 7D51CDAB6D8994BFCA779C73431E06336CF3343F
gpg: Good signature from "Quentin JOLY <quentinj@une-pause-cafe.fr>" [ultimate]

joel@cuistops:~/Documents$ file sujet-cuistops.pdf
sujet-cuistops.pdf: PDF document, version 1.7, 2 pages

Évidemment, ça ne fonctionne que si Joël a bien importé ma clé publique dans son trousseau GPG.

Chiffrer des fichiers avec GPG

Maintenant, en plus de signer les fichiers, je veux les chiffrer pour que seul Joël puisse les lire.

Pour cela, je possède sa clé publique qu’il vient de me donner par un support fiable (par clé USB provenant de sa main à la mienne).

J’importe sa clé avec gpg --import jseguillon.pub et je lui accorde une confiance ultime (gpg --edit-key joel.seguillon@cuistops puis trust et 5).

$ gpg -k
/home/quentinj/.gnupg/pubring.kbx
---------------------------------
pub   ed25519 2024-03-29 [C] [expire : 2039-03-26]
      355E36632085C9386A872739FB44D16A0CBA859C
uid          [ inconnue] Quentin JOLY <quentinj@une-pause-cafe.fr>
sub   ed25519 2024-03-29 [S] [expire : 2026-03-29]
sub   ed25519 2024-03-29 [A] [expire : 2026-03-29]
sub   cv25519 2024-03-29 [E] [expire : 2026-03-29]

pub   rsa3072 2024-04-01 [SC]
      85DD92335057613C268B117A3BF41286C1CA636A
uid          [  ultime ] Joël Seguillon <joel.seguillon@cuistops>
sub   rsa3072 2024-04-01 [E]

Je souhaite lui envoyer un fichier ./kube/config permettant d’accéder à un cluster Kubernetes sur notre infrastructure.

Je vais commencer par chiffrer le fichier en précisant l’adresse mail de Joël (dont la clé est enregistrée dans mon trousseau).

gpg --encrypt --recipient joel.seguillon@cuistops ~/.kube/config

Cette commande va créer le fichier ~/.kube/config.gpg que je vais envoyer à Joël par Google Drive (ou tout autre moyen de partage de fichier).

Si je tente de lire le fichier chiffré, je vais obtenir un message d’erreur, car je n’ai pas la clé privée de Joël pour le déchiffrer.

$ gpg --decrypt ~/.kube/config.gpg
gpg: chiffré avec une clef RSA de 3072 bits, identifiant D3352725C53827D9, créée le 2024-04-01
      « Joël Seguillon <joel.seguillon@cuistops> »
gpg: échec du déchiffrement : No secret key

Joël, lui peut déchiffrer le fichier avec sa clé privée.

joel@cuistops:~$ gpg --output .kube/config --decrypt config.gpg
gpg: encrypted with 3072-bit RSA key, ID D3352725C53827D9, created 2024-04-01
      "Joël Seguillon <joel.seguillon@cuistops>"

SSH avec une smartcard

Nativement, il est possible de stocker une clé privée grâce au protocole FIDO2 sur une Yubikey indépendamment de la clé GPG.

Mais puisque j’ai déjà une clé GPG stockée sur ma Yubikey, je souhaite également utiliser mon trousseau GPG pour me connecter à des serveurs SSH.

Car oui, les algorithmes de chiffrement utilisés par GPG et SSH sont les mêmes (RSA, DSA, ECDSA, ED25519, etc) !

Je vais commencer par exporter ma clé publique au format SSH :

$ gpg --export-ssh-key quentinj@une-pause-cafe.fr
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHPcu52OwmMIV8ImVzVfzBncjl+fL6/QN7HOZQ4Rkom8 openpgp:0xD6A95E93

Nous allons ensuite activer le support SSH dans GPG :

echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf

Puis, on redémarre le service GPG :

gpg-connect-agent reloadagent /bye

Dans cet état, GPG peut faire office de gestionnaire de socket Unix pour SSH. Il nous suffit alors de surcharger la variable SSH_AUTH_SOCK pour qu’elle pointe vers le socket Unix de GPG.

export GPG_TTY="$(tty)"
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent

Pour confirmer ça, on peut vérifier que la clé est bien présente dans le trousseau SSH :

$ ssh-add -L
256 SHA256:mOVlK0yr1tCSyjN1qi0Q2Fj9Y9ScUHHv4sNsKEPku/8 cardno:000622412322 (ED25519)

Après avoir configuré la clé publique sur Github, je peux tester l’authentification par clé SSH :

$ ssh git@github.com
PTY allocation request failed on channel 0
Hi QJoly! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.

Migrer d’une smartcard à une autre

Je dispose de deux smartcards, chacune étant une Yubikey. Les deux possèdent la même clé privée, mais lorsque je veux signer mes commits avec la Yubikey B, c’est la Yubikey A que mon ordinateur me demande.

En réalité, GPG va retenir que ma clé privée est sur la smartcard A et même si une autre Yubikey disposant de cette clé privée est disponible, GPG n’en voudra pas et demandera la Yubikey qu’il a en mémoire.

Pour palier à ce problème, il faut supprimer la référence de la clé privée vers la smartcard.

# Afficher les clés connues
$ gpg-connect-agent 'KEYINFO --list' /bye
S KEYINFO 7E47CF933E1E4F50F2EDAB6DFA07FE5882F7BA43 T D2760001240103040006224123450000 OPENPGP.2 - - - - -
S KEYINFO 648A03F4E5198FB941E8B6991E76C9B7D962CB78 T D2760001240103040006224123450000 OPENPGP.3 - - - - -
S KEYINFO 72C18AEB4B31EDC1CEE8B365DC795F7909A2E854 T D2760001240103040006224123450000 OPENPGP.1 - - - - -
OK

La valeur D2760001240103040006224123450000 fait référence au numéro de série de la Yubikey que je souhaite “oublier”.

Pour supprimer ces références, je vais utiliser la commande gpg-connect-agent "DELETE_KEY [SERIAL]" /bye.

gpg-connect-agent "DELETE_KEY 7E47CF933E1E4F50F2EDAB6DFA07FE5882F7BA43" /bye
gpg-connect-agent "DELETE_KEY 648A03F4E5198FB941E8B6991E76C9B7D962CB78" /bye
gpg-connect-agent "DELETE_KEY 72C18AEB4B31EDC1CEE8B365DC795F7909A2E854" /bye

Information

Si vous êtes sûr de ce que vous faites, vous pouvez supprimer toutes les smartcards connues avec la commande suivante :

list_key=$(gpg-connect-agent 'KEYINFO --list' /bye)
for key in $list_key; do
    echo $key | cut -d' ' -f3 | xargs -I {} gpg-connect-agent "DELETE_KEY {}" /bye
done

En insérant ma nouvelle Yubikey et en actualisant son status via gpg --card-status, je vais automatiquement recréer ces références avec la nouvelle smartcard.

Arrivée sur un nouveau poste

Prenons le cas où j’arrive sur un nouveau poste de travail sur lequel je souhaite développer (et donc signer mes commits).

J’arrive sur un poste dont le trousseau n’est absolument pas initialisé (pas de clé, pas de configuration). Ma clé Yubikey est bien insérée, mais je n’ai pas encore importé ma clé publique, de ce fait celle-ci n’affiche aucune information.

$ gpg --card-status
gpg: répertoire « /home/quentinj/.gnupg » créé
gpg: le trousseau local « /home/quentinj/.gnupg/pubring.kbx » a été créé
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006224123220000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 22412322
Name of cardholder: Quentin JOLY
Language prefs ...: fr
Salutation .......: 
URL of public key : https://github.com/qjoly.gpg
Login data .......: [non positionné]
Signature PIN ....: non forcé
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: E8D5 9EBC C28B 4ACC BEEB  74D2 312D FBFE 3C29 D864
      created ....: 2024-03-29 07:52:51
Encryption key....: 89F6 D00D E754 7C9C 7B32  143E 96F9 9A5D 69C1 54F7
      created ....: 2024-03-29 07:53:53
Authentication key: 82DB 8659 D803 833E A58C  07AF 4572 02EB 5C92 137C
      created ....: 2024-03-29 07:53:34
General key info..: [none]

Je vais commencer par importer ma clé publique. Celle-ci est directement téléchargeable depuis Github (cf. la variable URL of public key).

wget https://github.com/qjoly.gpg
gpg --import public.key

Je peux ensuite vérifier ma clé et indiquer à GPG que je lui fais confiance.

gpg --list-keys
gpg --edit-key quentinj@une-pause-cafe.fr
gpg> trust
gpg> 5 # confiance ultime

Maintenant, mon trousseau GPG reconnait la clé privée stockée sur ma Yubikey.

$ gpg --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006224123220000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 22412322
Name of cardholder: Quentin JOLY
Language prefs ...: fr
Salutation .......: 
URL of public key : https://github.com/qjoly.gpg
Login data .......: [non positionné]
Signature PIN ....: non forcé
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: E8D5 9EBC C28B 4ACC BEEB  74D2 312D FBFE 3C29 D864
      created ....: 2024-03-29 07:52:51
Encryption key....: 89F6 D00D E754 7C9C 7B32  143E 96F9 9A5D 69C1 54F7
      created ....: 2024-03-29 07:53:53
Authentication key: 82DB 8659 D803 833E A58C  07AF 4572 02EB 5C92 137C
      created ....: 2024-03-29 07:53:34
General key info..: pub  ed25519/312DFBFE3C29D864 2024-03-29 Quentin JOLY <quentinj@une-pause-cafe.fr>
sec>  ed25519/312DFBFE3C29D864  créé : 2024-03-29  expire : 2039-03-26
                                nº de carte : 0006 22412322
ssb#  ed25519/79C81E0291249128  créé : 2024-03-29  expire : 2026-03-29
ssb>  ed25519/457202EB5C92137C  créé : 2024-03-29  expire : 2026-03-29
                                nº de carte : 0006 22412322
ssb>  cv25519/96F99A5D69C154F7  créé : 2024-03-29  expire : 2026-03-29
                                nº de carte : 0006 22412322

$ gpg --list-secret-keys
sec>  ed25519 2024-03-29 [C] [expire : 2039-03-26]
      E8D59EBCC28B4ACCBEEB74D2312DFBFE3C29D864
      Nº de série de carte = 0006 22412322
uid          [  ultime ] Quentin JOLY <quentinj@une-pause-cafe.fr>
ssb#  ed25519 2024-03-29 [S] [expire : 2026-03-29]
ssb>  ed25519 2024-03-29 [A] [expire : 2026-03-29]
ssb>  cv25519 2024-03-29 [E] [expire : 2026-03-29]

À présent, je peux utiliser ma Yubikey pour signer mes commits.

Conclusion

Initialement, je trouvais l’intérêt d’un article sur le PGP assez limité. Mais en me plongeant dans le sujet et en découvrant les différentes applications possibles, je me rends compte que ça peut être un outil très puissant pour sécuriser ses échanges et garantir l’intégrité de ses fichiers.

De plus, j’ai toujours repoussé ma compréhension du PGP en pensant que c’était trop contraignant et que ça n’apportait pas grand-chose. Je suis très content de m’être lancé dans ces expérimentations.

Je suis encore loin d’avoir exploré toutes les possibilités du PGP, je vais continuer à l’utiliser et à l’approfondir pour en tirer le meilleur parti.

D’ici là, vous pouvez toujours m’envoyer un petit mail chiffré pour me dire ce que vous avez pensé de cet article 😉 (ma clé publique est disponible sur mon Github)

Un énorme merci à Jérémy pour la relecture de cet article !