gpg

Published: 16-07-2023

Updated: 23-07-2023

By: Maxime de Roucy

tags: gpg

généralitées

max@host % gpg --list-secret-keys --with-subkey-fingerprint
/home/max/.gnupg/pubring.kbx
----------------------------
sec#  rsa4096 2012-10-01 [SC] [revoked: 2017-02-06]
      60ADE6F57D9B2DE4B4B339DDD9372AFD10931D71
uid           [ revoked] Maxime de Roucy <maxime.deroucy@gmail.com>
uid           [ revoked] Maxime de Roucy <maxime1986@wanadoo.fr>
uid           [ revoked] Maxime de Roucy <maxime.deroucy@oxalide.com>

sec#  rsa4096 2018-12-16 [SC]
      4F3897929DE4618301B426673803C67BA14CE632
uid           [ultimate] Maxime de Roucy <maxime.deroucy@oxalide.com>
uid           [ultimate] Maxime de Roucy <maxime.deroucy@gmail.com>
uid           [ultimate] Maxime de Roucy <maxime.deroucy@fr.clara.net>
ssb#  rsa4096 2018-12-16 [E]
      835E5E07C7907569F38768A734C5FD5D631B4403
ssb   rsa4096 2018-12-16 [S]
      36F94EE7AB8DB18046C022E65FFA526C839248CB
ssb   rsa4096 2018-12-16 [E]
      AE0F1925441657AA46713F1DE9F162D1E102E412

Ici j’ai deux master keys (secret key: sec), l’une est révoquée (60ADE6F57D9B2DE4B4B339DDD9372AFD10931D71), l’autre est encore valide (4F3897929DE4618301B426673803C67BA14CE632).

max@host % gpg --list-secret-keys --with-subkey-fingerprint 4F3897929DE4618301B426673803C67BA14CE632
sec#  rsa4096 2018-12-16 [SC]
      4F3897929DE4618301B426673803C67BA14CE632
uid           [ultimate] Maxime de Roucy <maxime.deroucy@oxalide.com>
uid           [ultimate] Maxime de Roucy <maxime.deroucy@gmail.com>
uid           [ultimate] Maxime de Roucy <maxime.deroucy@fr.clara.net>
ssb#  rsa4096 2018-12-16 [E]
      835E5E07C7907569F38768A734C5FD5D631B4403
ssb   rsa4096 2018-12-16 [S]
      36F94EE7AB8DB18046C022E65FFA526C839248CB
ssb   rsa4096 2018-12-16 [E]
      AE0F1925441657AA46713F1DE9F162D1E102E412

E=encryption, S=signing, C=certification, A=authentication

Cette master key permet de :

Le suffix # indique que la clé n’est pas réellement présente dans le homedir.
Le suffix > indique que la clé est stoqué sur une smartcard (dans cette exemple je n’en ai pas).

Trois sub-keys (secret sub-key: ssb) lui sont associée :

Je n’est pas trouvé de moyen simple d’associer un commentaire à chaque sous-clé (e.g. pour définir son usage).

homedir

A chaque fois que vous switché de homedir, je vous conseil de kill le gpg-agent (l’agent est restart automatiquement sur le homedir suivant).

gpg …
pkill gpg-agent
gpg --homedir X …
pkill gpg-agent
gpg --homedir Y …
pkill gpg-agent
gpg …

subkey

Source: man gpg

Pour forcé l’utilisation/l’export/… d’une subkey en particulier il faut suffixer sont ID/Hash d’un ! :

When using gpg an exclamation mark (!) may be appended to force using the specified primary or secondary key and not to try and calculate which primary or secondary key to use.

Dans cette exemple, ces deux clés sont des subkey d’une même clé master :

max@host % gpg --encrypt-files -r '6FD22AB720151CD0672B9AA4BB579231A3659CFD' -r '7FD6798B5B230D994DF42AB9969DC552FBA21F06' toto
gpg: 6FD22AB720151CD0672B9AA4BB579231A3659CFD : ignoré : clef publique déjà présente

toto est chiffré avec une clé choisi par gpg (même pas sur que ça soit l’une des deux mensionnée)

max@host % gpg --encrypt-files -r '6FD22AB720151CD0672B9AA4BB579231A3659CFD!' -r '7FD6798B5B230D994DF42AB9969DC552FBA21F06!' toto

→ OK, toto est chiffré avec les deux clé indiqué en paramètre

précautions

Il est recommandé de ne pas utilisé la master key pour autre chose que créer les subkeys et sont propre certificat de révocation. De plus la master key devrait être stocké dans un endroit particulièrement sécurisé (pas le homedir standard quoi), genre une clé usb ou du papié dans un coffre, une smartcard… Personnellement j’ai choisi d’utiliser du papier… par ce que je suis radin ☺

Il n’est pas possible de supprimer une sous-clé d’un homedir sans supprimer la clé principal (2023/07/16 apparement c’est fixed). En revanche il est possible d’exporté une ou plusieurs sous-clés. Je ne veut pas que ma master key soit disponible dans mon homedir par défault. Je créé donc un homedir temporaire dans lequel je créé la master key et toutes les subkeys. J’export les subkeys et les importes dans les homedir pour lesquel elles sont destinées (la subkey de mon ordi sur l’ordi, la subkey du téléphone sur le téléphone…). Puis j’export la master key et toutes ses subkeys sous forme de paperkey (ASCII mais aussi QR Code ; je détaille la procédure dans la suite de l’article. Et je supprime le homedir temporaire.

password

ajout

max@host % gpg --homedir … --edit-key 4F3897929DE4618301B426673803C67BA14CE632
…
gpg> passwd

gpg m’a demandé quatre password, un pour la master key et un pour chaque subkey.

Il est possible de mettre des password différent pour chaque key sec & ssb… mais je le deconseille (en tout cas dans un même homedir).

Pour ajouter un password sur seul des subkey :

max@host % gpg --homedir gnupg-test --edit-key 4F3897929DE4618301B426673803C67BA14CE632
…
gpg> key 9C52A3B4E78EBB7E
… un * devrait apparaitre sur la ligne de la subkey …
gpg> passwd

modification

max@host % gpg --homedir gnupg-test --edit-key 4F3897929DE4618301B426673803C67BA14CE632
…
gpg> passwd

Il s’agit de la même commande que pour ajouter un mot de passe à une clé qui n’en possède pas, mais ici gpg applique le même mot de passe pour toutes les key sec & ssb ; il ne demande qu’une seul fois le nouveau mot de passe.

Pour changer le password d’une seul des subkey :

max@host % gpg --homedir … --edit-key 4F3897929DE4618301B426673803C67BA14CE632
…
gpg> key 9C52A3B4E78EBB7E
… un * devrait apparaitre sur la ligne de la subkey …
gpg> passwd

suppression

Note 2023/07/16: apparement il n’y a plus besoin d’utiliser --pinentry-mode loopback

max@host % gpg --homedir gnupg-test --pinentry-mode loopback --edit-key 4F3897929DE4618301B426673803C67BA14CE632
…
gpg> passwd

L’option --pinentry-mode loopback indique à gpg qu’il doit demander lui-même le mot de passe (sans utiliser d’outil externe). Vous devrez donc voir plusieurs prompt Enter passphrase: , le premier vous demandant le password actuelle, les autres les nouveaux password (un pour chaque key sec & ssb). Il suffit d’indiquer un password vide pour le supprimer.

check password

Pour verifier qu’un clé/sous-clé est bien protégé par mot de passe.

sous-clé de signature

pkill gpg-agent ; echo "1234" | gpg --armor --local-user '36F94EE7AB8DB18046C022E65FFA526C839248CB!' --sign - > /dev/null && echo "The correct passphrase was entered for this key" ; pkill gpg-agent

Je fait des pkill gpg-agent pour forcer la création de nouveau agent et clear tout les caches éventuel.

sous-clé de chiffrement

pkill gpg-agent ; echo "1234" | gpg --armor --recipient 'AE0F1925441657AA46713F1DE9F162D1E102E412!' --encrypt - | gpg --decrypt - ; pkill gpg-agent

Je fait des pkill gpg-agent pour forcer la création de nouveau agent et clear tout les caches éventuel.

key-server

Il faut utiliser hkps://keys.openpgp.org et pas les autres serveur

C’est pour éviter une attack de certificate poisoning (?).

send-keys

Avec le serveur hkps://keys.openpgp.org pour upload ses clé public il faut utiliser :

gpg --export 4F3897929DE4618301B426673803C67BA14CE632 |  curl -T - https://keys.openpgp.org

source: https://keys.openpgp.org/about/usage#gnupg-upload

generer une nouvelle clé privé

generer la subkey dans le repo “secure” (ici gnupg-master) qui ne doit pas être stocké sur la machine (genre une clé usb), sans password :

gpg --homedir gnupg-master --edit-key 4F3897929DE4618301B426673803C67BA14CE632
 …
gpg> addkey
 …
ssb  rsa4096/F1A963424748BDEF
 …
gpg> save

Copier le repo temporairement et ajouter un password :

cp -a gnupg-master to_remove
gpg --homedir to_remove --edit-key 4F3897929DE4618301B426673803C67BA14CE632
 …
gpg> key F1A963424748BDEF
 …
gpg> passwd
 …
gpg> save

export la subkey et remove le dossier temporaire :

gpg --homedir to_remove --list-secret-keys --with-subkey-fingerprint 4F3897929DE4618301B426673803C67BA14CE632
 …
      B4139B22F599101254779AAAF1A963424748BDEF
 …
gpg --homedir to_remove --export-secret-subkeys 'B4139B22F599101254779AAAF1A963424748BDEF!' > galaxy-a7.gpg
rm -r to_remove

paperkey

Sources: https://wiki.archlinux.org/title/Paperkey

backup

Attention, les (sous)clé protégées par mot de passe sont exportées avec leur protection. Pour avoir un export sans mot de passe il faut d’abord supprimer le password des (sous)clé dans le keyring source (ce que je ne montre pas ici).

Export de la clé principale et d’une des sous-clé qui me servent à chiffrer mes passwords :

gpg --homedir gnupg-master --export-secret-keys '4F3897929DE4618301B426673803C67BA14CE632!' 'AE0F1925441657AA46713F1DE9F162D1E102E412!' > 4F3897929DE4618301B426673803C67BA14CE632.gpg

ou

gpg --homedir gnupg-master --export-secret-keys 'AE0F1925441657AA46713F1DE9F162D1E102E412!' > 4F3897929DE4618301B426673803C67BA14CE632.gpg

Pas besoin de spécifier la clé princial, --export-secret-keys l’export de toute façon.

Export de la clé principale uniquement :

gpg --homedir gnupg-master --export-secret-keys '4F3897929DE4618301B426673803C67BA14CE632!' > 4F3897929DE4618301B426673803C67BA14CE632.gpg

Export d’une subkey uniquement (sans la clé principal) :

gpg --homedir gnupg-master --export-secret-keys '716DAE0D56BB01B30A72C5BCE6B6DA98337A3C7C!' > 716DAE0D56BB01B30A72C5BCE6B6DA98337A3C7C.gpg

Verification que l’imprimante est bien detectée :

lpstat -p -d
    printer Samsung-M2070 is idle.  enabled since dim. 02 juil. 2023 18:17:55
    system default destination: Samsung-M2070

ASCII

Export au format ASCII :

paperkey --secret-key 4F3897929DE4618301B426673803C67BA14CE632.gpg --output paperkey.ascii

Impression :

lpr -o fit-to-page -o media=a4 paperkey.ascii

QRCode

Export brute :

paperkey --secret-key 4F3897929DE4618301B426673803C67BA14CE632.gpg --output-type raw --output paperkey.raw

qrencode permet de split automatiquement le fichier avec l’option --structured, mais je n’ai trouvé aucune qrcode reader permettant de lire les fichier généré. Le plus simple et de passer le fichier en base64 (pour être en alphanumeric) et de split :

base64 -w0 paperkey.raw > paperkey.raw.base64
split -b 1273 paperkey.raw.base64 paperkey.raw.base64.split.

1273 est la taille maximal autorisé dans notre cas :

Pour le mode alphanum standard, version 40, level H : 3706 - 2430 = 1276 Mais en fait le qrcode à besoin de 3 octet pour stoqué le mode et la taille, ce qui nous donne 1273.

Encodage des fichiers :

for i in paperkey.raw.base64.split.*
 do
 qrencode --symversion=40 --level=H --read-from=$i --output=$i.png
 done

Impression :

lpr -o fit-to-page -o media=a4 paperkey.raw.base64.split.*.png

restore

Il faut récupérer 4F3897929DE4618301B426673803C67BA14CE632 et le convertir au format gpg:

wget -O 4F3897929DE4618301B426673803C67BA14CE632.pub https://keys.openpgp.org/vks/v1/by-fingerprint/4F3897929DE4618301B426673803C67BA14CE632
gpg --dearmor 4F3897929DE4618301B426673803C67BA14CE632.pub

On obtient le fichier 4F3897929DE4618301B426673803C67BA14CE632.pub.gpg

ascii

cat paperkey.ascii | paperkey --pubring 4F3897929DE4618301B426673803C67BA14CE632.pub.gpg --output 4F3897929DE4618301B426673803C67BA14CE632.gpg
gpg --import 4F3897929DE4618301B426673803C67BA14CE632.gpg

qrcode

zbarimg --raw *.png | base64 -d | paperkey --pubring 4F3897929DE4618301B426673803C67BA14CE632.pub.gpg --output 4F3897929DE4618301B426673803C67BA14CE632.gpg
gpg --import 4F3897929DE4618301B426673803C67BA14CE632.gpg

verification

pass gpg/master

ou

gpg --decrypt ~/.password-store/gpg/master.gpg

→ all good

notes

J’ai essayé datamatrix (paquet dmtx-utils) mais dmtxread n’arrive plus à lire les fichier une fois imprimé/scanné.

notes

certificat

utiliser un certificat de revokation : https://mwl.io/archives/2192

list-packkets

gpg --list-packets  …fichier…

Permet d’afficher exactement le contenu d’un fichier.

…dummy…: indique que les metadata sont là mais pas la clé en elle meme

gpg-connect-agent

max@host % gpg-connect-agent 'help keyinfo' /bye
# KEYINFO [--[ssh-]list] [--data] [--ssh-fpr] [--with-ssh] <keygrip>
#
# Return information about the key specified by the KEYGRIP.  If the
# key is not available GPG_ERR_NOT_FOUND is returned.  If the option
# --list is given the keygrip is ignored and information about all
# available keys are returned.  If --ssh-list is given information
# about all keys listed in the sshcontrol are returned.  With --with-ssh
# information from sshcontrol is always added to the info. Unless --data
# is given, the information is returned as a status line using the format:
#
#   KEYINFO <keygrip> <type> <serialno> <idstr> <cached> <protection> <fpr>
#
# KEYGRIP is the keygrip.
#
# TYPE is describes the type of the key:
#     'D' - Regular key stored on disk,
#     'T' - Key is stored on a smartcard (token),
#     'X' - Unknown type,
#     '-' - Key is missing.
#
# SERIALNO is an ASCII string with the serial number of the
#          smartcard.  If the serial number is not known a single
#          dash '-' is used instead.
#
# IDSTR is the IDSTR used to distinguish keys on a smartcard.  If it
#       is not known a dash is used instead.
#
# CACHED is 1 if the passphrase for the key was found in the key cache.
#        If not, a '-' is used instead.
#
# PROTECTION describes the key protection type:
#     'P' - The key is protected with a passphrase,
#     'C' - The key is not protected,
#     '-' - Unknown protection.
#
# FPR returns the formatted ssh-style fingerprint of the key.  It is only
#     printed if the option --ssh-fpr has been used.  It defaults to '-'.
#
# TTL is the TTL in seconds for that key or '-' if n/a.
#
# FLAGS is a word consisting of one-letter flags:
#       'D' - The key has been disabled,
#       'S' - The key is listed in sshcontrol (requires --with-ssh),
#       'c' - Use of the key needs to be confirmed,
#       '-' - No flags given.
#
# More information may be added in the future.
OK
max@host % gpg-connect-agent 'keyinfo --list' /bye
S KEYINFO 83A2BB6DB2D632E92EDFFD9A6F278134D2C76012 D - - - P - - -
S KEYINFO 3BF18C02C764451AD7CBD6504ED7936E571BB87C D - - - P - - -
S KEYINFO 7AD225A04E857C1FEA6D0C687D75848692D56CF5 D - - - P - - -
S KEYINFO D945ADA023667FCAFD9305552B3DBA6286946FD9 D - - - P - - -
S KEYINFO F0F148EF8B2A7A35BA48F175F861883BF3F5848E D - - - C - - -
S KEYINFO 3D60E5ADEDB55BFC10E7F212728C8C17E4D489F7 D - - - C - - -
S KEYINFO FF73871150A205DF1BC63A1F28544C9244749DFB D - - 1 P - - -
OK
max@host % l ~/.gnupg/private-keys-v1.d
total 28K
-rw------- 1 max users 2,1K  6 févr.  2017 3BF18C02C764451AD7CBD6504ED7936E571BB87C.key
-rw------- 1 max users  977  6 juin  19:40 3D60E5ADEDB55BFC10E7F212728C8C17E4D489F7.key
-rw------- 1 max users 2,1K  8 févr.  2017 7AD225A04E857C1FEA6D0C687D75848692D56CF5.key
-rw------- 1 max users 2,1K  6 févr.  2017 83A2BB6DB2D632E92EDFFD9A6F278134D2C76012.key
-rw------- 1 max users 2,1K  8 févr.  2017 D945ADA023667FCAFD9305552B3DBA6286946FD9.key
-rw------- 1 max users  977  6 juin  19:40 F0F148EF8B2A7A35BA48F175F861883BF3F5848E.key
-rw------- 1 max users  361 10 oct.  20:03 FF73871150A205DF1BC63A1F28544C9244749DFB.key
max@host % gpg --list-secret-keys --with-keygrip  | grep -C6 F0F148EF8B2A7A35BA48F175F861883BF3F5848E
      Keygrip = 3BF18C02C764451AD7CBD6504ED7936E571BB87C
ssb   rsa4096 2012-10-01 [E]
      Keygrip = 7AD225A04E857C1FEA6D0C687D75848692D56CF5

sec   rsa2048 2018-06-06 [SC]
      E5FD72F728F94FBF85453FA06C5CF27EBC044A8C
      Keygrip = F0F148EF8B2A7A35BA48F175F861883BF3F5848E
uid           [ unknown] learnybox
ssb   rsa2048 2018-06-06 [E]
      Keygrip = 3D60E5ADEDB55BFC10E7F212728C8C17E4D489F7

Content of private-keys-v1.d: https://lists.gnupg.org/pipermail/gnupg-users/2017-February/057625.html