Publié le 06/11/2019.
Dans un précédent article, nous avions vu comment se faire une carte à puce OpenPGP. L'utilisation de cette dernière étant bien plus complexe qu'il n'y parait, un nouvel article s'impose afin d'éviter les embûches.
Dans cet article, nous créerons une nouvelle clé OpenPGP dite clé maîtresse ainsi que 3 sous-clés ayant chacune un rôle précis. Les sous-clés seront ensuite transférées sur la carte à puce et le tout devra être sauvegardé sur un support fiable stocké de manière sécurisée.
La cryptographie ne pardonne pas. Afin d'éviter le pire, il vous est rappelé que :
Ces principes sont généraux et ne s'appliquent pas que dans le cadre des cartes à puces cryptographiques mais sont ici fondamentaux. La perte d'une seule clé secrète peut vous faire perdre un très grand nombre de données importantes, alors ne laissez rien au hasard.
GnuPG ayant tendance à régulièrement changer son interface en ligne de commande, vous pourrez avoir besoin de vous référer au manuel de la version que vous utilisez afin d'adapter certaines commandes présentées ici. Les logiciels utilisés pour l'écriture de cet article sont :
Afin de suivre ce guide, vous devez posséder au moins :
Il est recommandé de disposer de plusieurs cartes OpenPGP. Si tel est le cas, ne vous sentez pas obligé de transférer les clés sur l'ensemble de ces cartes, vous pouvez n'en utiliser qu'une et, si elle venait à être indisponible (perte, vol, panne, …), vous pourrez alors en configurer une autre à partir de vos sauvegardes.
Il est également très fortement recommandé d'utiliser plusieurs supports de sauvegarde. Ces supports seront idéalement différents et stockés de manière sécurisée à des endroits séparés. Du soin que vous apporterez aux sauvegardes découlera votre aptitude à faire face à une situation imprévue.
Par défaut, GnuPG utilise le répertoire $HOME/.gnupg
pour y stocker l'ensemble des clés publiques et privées ainsi que d'autres informations nécessaires à son fonctionnement. Si nous utilisons GnuPG sans prendre de précautions particulière, les clés privées générées seront stockées en local, ce qui représente potentiellement un risque de fuite. Afin d'éviter ça, il est très fortement recommandé de brancher un support amovible (carte SD, clé USB, etc) qui sera alors dédié à la sauvegarde de nos clés. Toutes les commandes devront être lancées depuis un dossier situé sur ce support amovible. Grace à l'option --homedir
de GnuPG, les clés seront écrites sur ce support amovible et non le disque dur local.
Les points importants à bien garder en mémoire sont les suivants :
Ceci dit, positions nous sur le support amovible et créons le dossier qui contiendra la configuration de GnuPG :
$ cd /chemin/vers/le/support/amovible
$ mkdir gpg_save
$ chmod 700 gpg_save
Il existe plusieurs types de clés, chacun ayant ses avantages et ses inconvénients. D'un coté nous avons RSA, technologie basée sur les nombres premiers dont les clés sont très grosses et dont l'implémentation est réputée très complexe, la moindre erreur entraînant une catastrophe. De l'autre, nous avons les courbes elliptiques qui, pour un niveau de sécurité équivalent, une des clés d'une taille bien plus réduites que RSA et dont les implémentations sont en général relativement simples. Le problèmes des courbes elliptiques réside plus dans les raisons du choix des courbes qu'autre chose (cf. Standardisation des courbes elliptiques : à qui faire confiance ? et SafeCurves). Ainsi, on préférera l'usage de de la courbe 25519 plutôt que des courbes du NIST.
Les autres types de clés présentent, à mon sens, beaucoup moins d'intérêt.
Ma recommandation personnelle est donc de choisir, en fonction de la disponibilité et par ordre de priorité :
Malheureusement, contrairement aux courbes du NIST, Curve 25519 est récente et n'est donc pas disponible sur la plupart des cartes à puce. à vrai dire je ne connais à l’heure actuelle aucune carte à puce supportant Curve 25519. À défaut, il sera donc fait usage dans cet article de la courbe P-256 du NIST.
La clé maîtresse est une clé qui ne sera pas présente sur la carte. Elle sert exclusivement à signer d'autres clés et à, accessoirement, la capacité de signer des documents. C'est lors de sa génération que nous devrons sélectionner la technologie sous-jacente.
$ gpg --homedir gpg_save --full-gen-key --expert
Durant ce processus, nous sélectionnerons les options ECC and ECC
, NIST P-256
et une durée d'expiration de 0 afin que la clé n'expire jamais. GnuPG nous demande également divers informations au sujet de la clé, les plus importantes étant notre nom, notre adresse email et le mot de passe qui servira à protéger la clé secrète. Si vous comptez faire signer votre clés par d'autres personnes afin d'intégrer un réseau de confiance, il est important d'indiquer votre véritable identité car, afin de contrer la fraude, la plupart des événements imposent de présenter une voire deux pièces d'identité officielles.
Notez que, bien que nous ne le verrons pas dans cet article, vous pourrez par la suite ajouter de nouvelles identité à votre clé.
Notre clé maîtresse est maintenant créée. Vérifions donc les informations à son sujet :
$ gpg --homedir gpg_save --list-secret-keys
-------------------------------------------------
sec nistp256 2019-11-06 [SC]
ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
uid [ultimate] Derp Derpson <derp.derpson@example.com>
ssb nistp256 2019-11-06 [E]
Les blocs de lignes commençant par sec
et ssb
indiquent respectivement une clé privée et une sous-clé privée. Bien qu'une sous-clé ait été automatiquement générée, nous attendrons la section suivante pour nous pencher dessus. Concentrons nous donc sur la clé principale, donc sec
:
nistp256
indique que c'est une clé utilisant la courbe elliptique P-256 standardisée par le NIST ;2019-11-06
est la date de création de la clé ;[SC]
indique les capacités de la clé (voir plus bas) ;ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
est l'identifiant complet de la clé ;uid [ultimate] Derp Derpson <derp.derpson@example.com>
indique que la clé est rattachée à une identité (uid pour User IDentifier), ici Derp Derpson dont l'adresse email est derp.derpson@example.com, et que nous avons une confiance ultime ([ultimate]
) dans le fait que c'est bien cette personne qui possède la clé (voir plus bas).Les clés privées ne sont pas égales entre elles. À ce titre, comme nous l'avons vu, elles ont chacune un usage limité. Les usages, représentés par des lettres, sont les suivants :
S
(sign) signer un document ;C
(certify) certifier (via une signature) la clé publique d'un utilisateur ;E
(encrypt) chiffrer un document (plus précisément, ce type de clé privée nous permet de déchiffrer les documents que les autres utilisateurs ont chiffrés avec la clé publique associée) ;A
(authenticate) authentification auprès d'un autre service.Chiffrer c'est très bien, mais si l'on ne peut pas s'assurer de l'identité de son destinataire, alors ça ne sert pas à grand chose (cf. attaque de l'homme du milieu). De plus, une signature ne vaut rien si vous n'êtes pas certain que la personne ayant apposée cette signature est bien la bonne. Afin de créer cette confiance, il existe plusieurs modèles. OpenPGP utilise celui de la toile de confiance. Pour résumer, chaque clé à la pouvoir d'en signer d'autres et nous allons accorder un certain niveau de confiance aux clés que nous connaissons et avons pu vérifier. Les niveaux sont les suivants :
ultimate
(u
) : niveau ultime, réservé pour les clés que l'on génère nous-même ;full
(f
) : nous avons vérifié que l'identité sur la clé correspond bien à la bonne personne et nous avons totalement confiance dans les clés signées par cette personne ;marginal
(m
) : nous avons vérifié que l'identité sur la clé correspond bien à la bonne personne et nous avons une confiance relative dans les clés signées par cette personne ;none
(n
) : nous avons vérifié que l'identité sur la clé correspond bien à la bonne personne mais nous ne lui faisons pas confiance pour signer d'autres clés ;unknown
(q
) : nous avons vérifié que l'identité sur la clé correspond bien à la bonne personne mais nous ne savons pas si cette personne est digne de confiance ou non pour signer d'autres clés.Rappelons que chacun a des critères différents pour attester que l'identité d'une clé correspond bien à la personne légitime. La toile de confiance repose à la fois sur notre jugement propre mais aussi sur notre confiance dans le jugement des autres. C'est pour cela que, lorsque l'on signe une clé (et donc que l'on atteste de l'identité associée), on indique un niveau de qui représente notre confiance dans le jugement du propriétaire de cette clé pour en signer d'autres.
Comme nous l'avons vu, nous disposons actuellement d'une clé principale capable de signer et certifier ainsi que d'une sous-clé permettant de (dé)chiffrer. Une carte OpenPGP ne permettant pas de certifier, nous garderons la clé maîtresse dans nos sauvegardes et, pour signer, nous allons générer une nouvelle sous-clé avec cette capacité. Nous allons donc éditer notre clé principale afin avec l'option --edit-key
et, dans le shell interactif de GnuPG, générer une nouvelle sous-clé avec la commande addkey
. Ceci fait, on utilise la commande save
pour sauvegarder les modifications et quitter le shell interactif.
$ gpg --homedir gpg_save --expert --edit-key ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
[…]
gpg> addkey
[…]
gpg> save
Lors de la génération, nous sélectionnons les options ECC (sign only)
, NIST P-256
et une durée d'expiration de 0 afin que la clé n'expire jamais. Vérifions ensuite la résultat :
$ gpg --homedir gpg_save --list-secret-keys
-------------------------------------------------
sec nistp256 2019-11-06 [SC]
ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
uid [ultimate] Derp Derpson <derp.derpson@example.com>
ssb nistp256 2019-11-06 [E]
ssb nistp256 2019-11-06 [S]
Nous allons maintenant générer une troisième sous-clé qui sera destinée à l'authentification. Bien entendu, ce n'est nécessaire que si l'on souhaite que si l'on souhaite utiliser cette capacité. Son utilité première réside principalement dans son utilisation conjointe avec ssh. Pour ce faire, nous utilisons exactement la même méthode que pour l'ajout de la sous-clé de signature, mais durant le processus de génération nous sélectionnerons l'option ECC (set your own capabilities)
afin de donner à la clé la capacité d'authentification (A
) et de lui retirer ce qui était mis par défaut (S
).
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
Your selection? 11
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? A
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign Authenticate
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? S
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Authenticate
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? Q
Vérifions à nouveau le résultat :
$ gpg --homedir gpg_save --list-secret-keys
-------------------------------------------------
sec nistp256 2019-11-06 [SC]
ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
uid [ultimate] Derp Derpson <derp.derpson@example.com>
ssb nistp256 2019-11-06 [E]
ssb nistp256 2019-11-06 [S]
ssb nistp256 2019-11-06 [A]
Tout est parfait, nous avons bien notre clé principale dotées des capacités de signature et de certification (SC
) et nos trois sous-clés ayant chacune une unique capacité. L'une des sous-clés permet de (dé)chiffrer (E
), l'autre de signer (S
) et la dernière de s'authentifier (A
).
Nous allons ici exporter deux clés publiques différentes. D'un côté, la clé publique destinée à être utilisée par GnuPG et de l'autre la clé publique ssh correspondant à notre clé d'authentification.
$ gpg --homedir gpg_save --armor --output public_key.asc --export ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
$ gpg --homedir gpg_save --armor --output public_ssh_key.pub --export-ssh-key ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
Conservez ces deux fichiers. Vous pouvez envoyer le contenu de public_key.asc
sur un serveur de clés et le donner à tous vos contacts, c'est grâce à lui que les autres utilisateurs pourront vous envoyer un message chiffré et vérifier vos signatures. Si vous souhaitez utiliser votre clé OpenPGP pour vous authentifier avec ssh, vous devrez ajouter le contenu du fichier public_ssh_key.pub
dans le fichier $HOME/.ssh/authorized_keys
de la machine de destination.
Maintenant que nous avons généré toutes les clés dont nous aurons besoin, c'est le moment de s'occuper de la stratégie sauvegarde. En effet, l'opération de transfert des clés sur la carte est destructrice : les clés transférées sont supprimées du répertoire local et remplacées par une fausse clé indiquant que l'emplacement est désormais la carte à puce.
La stratégie que nous allons déployer est la suivante : nous souhaitons conserver le dossier gpg_save
comme sauvegarde et, en plus, exporter les clés privées dans un fichiers distinct. Nous utiliserons ensuite ce fichier pour créer un nouveau dossier de temporaire pour GnuPG d'où les clés seront transférées sur la carte.
$ gpg --homedir gpg_save --armor --output private_keys.asc --export-secret-keys ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
$ mkdir gpg_keytransfert_tmp
$ chmod 700 gpg_keytransfert_tmp
$ gpg --homedir gpg_keytransfert_tmp --import private_keys.asc
Vérifions que notre nouveau répertoire de configuration GnuPG contienne bien nos clés privées :
$ gpg --homedir gpg_keytransfert_tmp --list-secret-keys
-------------------------------------------------------------
sec nistp256 2019-11-06 [SC]
ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
uid [ unknown] Derp Derpson <derp.derpson@example.com>
ssb nistp256 2019-11-06 [E]
ssb nistp256 2019-11-06 [S]
ssb nistp256 2019-11-06 [A]
Attention, sec
ou ssb
peuvent avoir un suffixe dont la signification est la suivante :
#
indique que la clé privée est inutilisable (non présente) ;>
indique que la clé privée est stockée sur une carte à puce et n'est donc pas présente localement.Vérifiez avec attention que votre répertoire de sauvegarde n'indique aucun de ces suffixes lorsque vous utilisez --list-secret-keys
.
Ici tout est bon, notre sauvegarde des clés privées est fonctionnelle. Si vous souhaitez utiliser plusieurs supports de sauvegarde, c'est le moment d'y copier le dossier gpg_save
ainsi que le fichier private_keys.asc
.
Tout étant prêt, nous allons maintenant configurer notre carte à puce. La première étape consiste en sa personnalisation. Pour cela, nous utilisons --edit-card
qui affiche un résumé des information de la carte et nous donne un shell interactif pour la paramétrer.
$ gpg --edit-card
Nous remarquons que la carte dispose de 3 emplacements de clés : un pour une clé de chiffrement, un pour une clé de signature et un pour une clé d'authentification. Ceci correspond exactement aux trois sous-clés que nous avons généré. Remarquez également que dans Key attributes
il est indiqué de quel type doivent etre les clés en question. Par défaut, c'est en général du RSA 2048 bits. Pensez à modifier ce paramètre si vous utilisez un autre type de clés (voir plus bas).
Dans le shell interactif, vous pouvez utiliser la commande help
pour liste l'ensemble des commandes possibles. Notez que passer en mode admin avec la commande du même nom débloque des commandes supplémentaires.
gpg/card> help
quit quit this menu
admin show admin commands
help show this help
list list all available data
fetch fetch the key specified in the card URL
passwd menu to change or unblock the PIN
verify verify the PIN and list all data
unblock unblock the PIN using a Reset Code
gpg/card> admin
Admin commands are allowed
gpg/card> help
quit quit this menu
admin show admin commands
help show this help
list list all available data
name change card holder's name
url change URL to retrieve key
fetch fetch the key specified in the card URL
login change the login name
lang change the language preferences
sex change card holder's sex
cafpr change a CA fingerprint
forcesig toggle the signature force PIN flag
generate generate new keys
passwd menu to change or unblock the PIN
verify verify the PIN and list all data
unblock unblock the PIN using a Reset Code
factory-reset destroy all keys and data
kdf-setup setup KDF for PIN authentication
key-attr change the key attribute
Paramétrez la carte comme bon vous semble. Les paramètres les plus utiles sont :
passwd
: change le code PIN de la carte, le code PIN d'administration et le code de remise à zéro ;key-attr
: modifie le type de clé que la carte peut stocker (voir section suivante pour certaines restrictions d'usage) ;url
: vous permet d'indiquer une URL d'où votre clé publique (votre fichier public_key.asc
précédemment généré) est téléchargeable ;login
: vous permet d'indiquer le nom d'utilisateur dans le cadre d'une authentification ;Modifier les différents codes (PIN, PIN d'admin et code de remise à zéro) est très important. Si vous ne le faites pas, un individu pourrait administrer votre carte en utilisant les codes par défaut. Soit dit en passant, si vous avez créé votre carte vous-même avec SmartPGP, le code PIN par défaut est 123456
et le code PIN d'admin par défaut est 12345678
.
Si vous spécifiez une URL pour votre clé publique, vous serez en mesure, lorsque vous utiliserez votre carte, d'utiliser la commande fetch
afin d'importer la dite clé publique dans GnuPG.
S'il est possible d'utiliser GnuPG pour configurer le type de clés utilisées une carte à puce OpenPGP, il y a un défaut à cette méthode : lorsque l'on change le type de clé secrète, GnuPG n'active pas une option dont le but est d'envoyer le composant publique de la clé en même temps que la clé secrète. Or, certaines cartes comme mon ACOSJ 40K dual ne peuvent fonctionner que si ce composant publique est présent. Afin de changer le type de clés gérées par notre carte, il nous faut donc utiliser le script fourni avec SmartPGP qui, lui, inclue ce composant.
Le script en question utilise Python 2, assurez-vous que cette version soit installée sur votre système. Cette version de Python étant ancienne, il y a des chances pour que votre système utilise Python 3 par défaut. Si c'est le cas, nous allons utiliser pipenv
pour créer un environnement virtuel Python 2.
Les commandes de cette section sont à lancer depuis la racine du projet SmartPGP.
$ pipenv --python 2.7
$ pipenv install pyasn1 pyscard
Maintenant que notre environnement virtuel est créé et que les dépendances sont installées, nous pouvons lancer le script. Regardons tout d'abord les commandes possibles grâce à pipenv run ./bin/smartpgp-cli --help
. Afin de vérifier que tout fonctionne bien, listons les lecteurs : pipenv run ./bin/smartpgp-cli list-readers
. En cas de soucis, pensez à retirer votre carte du lecteur puis à l'y réinsérer.
Si tout est bon, nous pouvons procéder au changement du type de clés supportées. Pour ma part, j'ai choisi la courbe elliptique NIST P-256.
$ pipenv run ./bin/smartpgp-cli switch-p256
Select OpenPGP Applet
90 00
Verify Admin PIN
90 00
Switch to P-256 (sig)
90 00
Switch to P-256 (dec)
90 00
Switch to P-256 (auth)
90 00
À l'aide de GnuPG, vérifions que le changement se soit bien opéré.
$ gpg --card-status | grep 'Key attributes'
Key attributes ...: nistp256 nistp256 nistp256
Notre carte étant correctement configurée, il ne nous reste plus qu'a y transférer les clés. Pour ceci nous allons éditer notre clé principale puis passer en mode clé secrète avec toggle
. Enfin, pour chaque sous-clé, nous allons sélectionner cette dernière à l'aide de la commande key
puis la transférer sur la carte avec la commande keytocard
. Notez que lorsque vous sélectionnez une clé ou sous-clé, GnuPG affiche à nouveau un résumé des clés avec *
après sec
ou ssb
suivant la clé que vous avez sélectionné. Il est possible de sélectionner plusieurs clés, alors n'oubliez pas de dé-sélectionner (toujours avec key
) la clé précédente.
$ gpg --homedir gpg_keytransfert_tmp --expert --edit-key ACCE0B5B4C26D8E67009FB3AFDD2ACBDEA2DEBB5
Secret key is available.
sec nistp256/FDD2ACBDEA2DEBB5
created: 2019-11-06 expires: never usage: SC
trust: unknown validity: unknown
ssb nistp256/C05D2B351B116707
created: 2019-11-06 expires: never usage: E
ssb nistp256/B2620C09BD33B5F9
created: 2019-11-06 expires: never usage: S
ssb nistp256/D94E475F4FFC8416
created: 2019-11-06 expires: never usage: A
[ unknown] (1). Derp Derpson <derp.derpson@example.com>
gpg> toggle
gpg> key C05D2B351B116707
gpg> keytocard
gpg> key C05D2B351B116707
gpg> key B2620C09BD33B5F9
gpg> keytocard
gpg> key B2620C09BD33B5F9
gpg> key D94E475F4FFC8416
gpg> keytocard
gpg> save
Si une erreur du genre « selecting openpgp failed » arrive lorsque vous tentez un keytocard
, tuez scdaemon en utilisant killall scdaemon
. Vous devrez peut-être vous y reprendre à plusieurs fois, exécutez la commande jusqu'à ce que pgrep scdaemon
ne retourne plus rien.
Vérifions que le transfert se soit bien déroulé :
$ gpg --card-status
[…]
Signature key ....: E99A 3508 3858 079D DCC2 B298 B262 0C09 BD33 B5F9
created ....: 2019-11-06 13:46:18
Encryption key....: 0FBF 1F9E B46F 8DF7 0EDF 56C8 C05D 2B35 1B11 6707
created ....: 2019-11-06 13:45:09
Authentication key: 0E76 EB33 DCC5 BF1B 8EF7 9B55 D94E 475F 4FFC 8416
created ....: 2019-11-06 13:46:58
[…]
Si tout est bon, alors félicitations, vous avez correctement configurée votre carte à puce OpenPGP ! Nous pouvons donc supprimer notre dossier temporaire servant uniquement au transfert des clés :
$ rm -rf gpg_keytransfert_tmp
Lorsque vous utilisez votre carte OpenPGP dans un nouvel environnement, il vous faut importer votre clé publique, par exemple avec gpg --recv-key
ou, si vous avez renseigné une URL sur votre carte, gpg --edit-card
puis fetch
.
Désormais, les opérations de déchiffrement, de signature ou d'authentification vous demanderont d'insérer votre carte et de la débloquer avec votre code PIN.