Ted écrit des trucs

Sur des sujets en lien avec la vie privée, ou parfois pas.

Gérer ses mails en local : étape 4, tout chiffrer avec GPG !

— modifié le

Ce billet fait partie d'une série d'articles présentant la façon dont je gère mes mails en local. Si vous êtes arrivés là sans lire l'introduction, c'est probablement une bonne idée de commencer par le début =)


Notre configuration, jusqu'ici, n'est pas très sécurisée. Le problème principal est que tous nos mots de passe sont stockés en clair sur le disque dur : si quelqu'un y a accès, il peut non seulement lire nos mails mais il a un accès direct à notre serveur IMAP et SMTP, tant qu'on ne change pas la configuration. On pourrait rétorquer que si l'on fait attention, on peut faire en sorte que personne n'ait un accès à la machine ; et dans la majorité des situations, avec quelques précautions évidentes - verrouiller l'écran de son laptop dès qu'on s'en éloigne, etc. - c'est un argument qui se tient. Le problème, c'est que si le disque dur est non chiffré et que quelqu'un a un accès physique et prolongé à la machine (par exemple, si on vous l'a volé, ou que vous l'avez laissé sans surveillance pendant un temps suffisamment long pour laisser le temps à un attaquant de lancer un Live CD), les données seront compromises (et l'attaque peut très bien ne laisser quasiment aucune trace).

Pour résoudre ce problème grave, on va installer GPG (Gnu Private Guard) et modifier notre configuration pour planquer les données sensibles. Ça sera par ailleurs une excellente occasion pour se servir du même logiciel pour signer électroniquement les mails qu'on envoie, et les chiffrer quand c'est possible.

Si vous n'avez jamais entendu parler d'OpenPGP (le protocole implémenté par GnuPG) et que vous ne savez pas du tout ce que c'est qu'une paire de clés publique/privée, c'est probablement une bonne idée d'aller lire quelques ressources sur le sujet (par exemple, la page Wikipédia consacrée au principe de la cryptographie asymétrique). Dans toute la suite, je vais supposer que vous comprenez les notions de clé privée, clé publique, et que vous comprenez l'idée de base que l'on va implémenter ici.

Premiers pas

Installation

Pour l'installation, on installe GnuPG, ainsi qu'un autre paquet dont on va détailler l'utilité plus tard. La commande qui invoque le logiciel est gpg mais le nom du paquet est gnupg :

aptitude install gnupg gnupg-agent pinentry-gtk2

Ensuite, il faut se créer (au minimum) une paire clé publique / clé secrète si l'on veut pouvoir chiffrer quoi que ce soit. Lancez donc la commande :

gpg --gen-key

et laissez-vous guider. Les choix par défaut sont en général très bien (même si je pense que ça ne coûte pas grand-chose de toujours sélectionner la taille de clé la plus grande disponible). On va vous demander une phrase de passe, évidemment, parce que si la clé secrète (qui se trouve sur votre disque dur) n'est pas elle-même chiffrée, quelqu'un qui vous vole votre disque dur pourra la lire et déchiffrer ce qu'il veut avec. Inutile de préciser qu'il faut choisir une phrase de passe solide, je recommande pour ça la méthode XKCD (pour les non-anglophones : quelques (au moins quatre) mots aléatoires de la langue française les uns à la suite des autres - comme correctchevalbatterieagrafe - forment un mot de passe à la fois plus sûr et plus facile à retenir qu'un truc rempli de transformations bizarres comme Tr0ub4doUr&3).

On a notre paire de clés, disons que son identifiant est EA627AA3. On peut s'amuser à chiffrer et déchiffrer des documents :

echo "Encryptons joyeusement un fichier inutile" > inutile.txt
cat inutile.txt
gpg --encrypt -r EA627AA3 --armor inutile.txt
cat document.txt.asc
gpg --decrypt document.txt.asc

mais je ne m'étendrais pas sur l'étendue des possibilités de GPG ; ce tutoriel cherche juste à expliquer comment se servir en pratique de GPG pour augmenter la sécurité de sa configuration. Si vous voulez des informations plus détaillées, vous pouvez allez jeter un œil du côté de la documentation officielle, qui est à la fois complète et très lisible (et en français).

Configuration

GnuPG requiert une quantité assez minime de configuration. Par contre, par défaut, il va vous demander votre phrase de passe dès qu'il essaie d'accéder à vos clés : en pratique, dès que vous envoyez un mail signé, que vous recevez un mail chiffré, ou qu'il tente de déchiffrer un fichier - donc, tout le temps.

Pour que ça ne soit pas trop pénible, on utilise gpg-agent, qui nécessite un peu plus de configuration. Commencez par décommenter la ligne contenant use-agent dans le dossier ~/.gnupg/gpg.conf (si ce fichier n'existe pas, lancez gpg dans un terminal, puis appuyez sur Ctrl-D).

Puis, créez et éditez le fichier ~/.gnupg/gpg-agent.conf, et entrez-y les lignes suivantes :

pinentry-program /usr/bin/pinentry-gtk-2
default-cache-ttl 43200
max-cache-ttl 43200

en remplaçant 43200 par le temps, en secondes, pendant lequel vous voulez que gpg-agent se souvienne de votre phrase de passe (donc la fréquence à laquelle il va vous la redemander). Ici, toutes les 12 heures. Pour vérifiez que ça fonctionne, lancez la commande suivante dans un terminal :

eval "$(gpg-agent --daemon)"

et lancez une commande qui nécessite votre phrase de passe (par exemple, chiffrez un fichier quelconque); vous allez pouvoir constater que c'est gpg-agent qui s'occupe de vous la demander et que si vous faites ça plusieurs fois de suite, il l'aura gardé en mémoire entre deux fois consécutives.

Ne pas stocker ses mots de passe en clair

On a pour l'instant des mots de passe en clair dans les configurations de msmtp, et de OfflineIMAP. À la place, on va plutôt les stocker dans des fichiers à part, qui seront chiffrés. Commencez par créer un répertoire où vous voulez dans votre système (~/.mdp, par exemple), c'est là que l'on va les mettre.

msmtp

Dans la configuration de msmtp, pour l'instant, on a une ligne qui ressemble à :

password gungjbhyqunirorraorggre

supprimez cette ligne, et copiez le mot de passe dans ~/.mdp/msmtp, par exemple. Il faut que ce fichier contienne votre mot de passe et rien d'autre : pas d'espace ni de retour à la ligne. Chiffrez ce fichier, et supprimez-le de façon sécurisée :

cd ~/.mdp/msmtp
gpg --encrypt -r EA627AA3 --armor msmtp
shred -z -v msmtp

maintenant, à la place de la ligne qui contenait votre mot de passe, ajoutez la ligne :

passwordeval gpg --batch -d --use-agent --yes /home/votreidentifiant/.mdp/msmtp.gpg 2>/dev/null

(évidemment, en changeant « votreidentifiant » par votre nom d'utilisateur). Vous êtes en train de lui dire « pour trouver le mot de passe, exécute la commande suivante » au lieu de directement « voilà le mot de passe ». À chaque fois qu'il va avoir besoin du mot de passe, il va déchiffrer le fichier ~/.mdp/msmtp.gpg, en utilisant gpg-agent pour ne pas vous demander votre mot de passe si il s'en souvient.

Votre mot de passe SMTP n'est donc plus disponible en clair sur votre disque dur, mais mis à part un mot de passe que vous devez rentrer régulièrement (à intervalles que vous choisissez), rien n'a changé dans l'utilisation quotidienne de msmtp. Si vous utilisez msmtp avec plusieurs comptes différents, n'oubliez pas de créer un fichier par mot de passe et de faire les modifications partout, bien sûr.

OfflineIMAP

Pour OfflineIMAP, on va faire essentiellement la même chose. Seulement, le fichier de configuration n'a pas d'option aussi simple que le passwordeval de msmtp, mais permet à la place d'utiliser un script Python. Téléchargez donc le fichier suivant, enregistrez-le quelque part (par exemple, comme ~/.offlineimap.py), et rectifiez la ligne contenant votreidentifiant.

Puis, dans le fichier de configuration d'OfflineIMAP (~/.offlineimaprc), ajoutez la ligne

pythonfile = ~/.offlineimap.py

dans la section [general], puis remplacez la ligne remotepass par :

remotepass = mailpasswd("offlineimap")

en supposant que, de façon similaire à tout à l'heure, vous aviez stocké votre mot de passe dans le fichier ~/.mdp/offlineimap.gpg. Choisissez des noms plus spécifiques si vous gérez plusieurs comptes à la fois, et stockez autant de mots de passe que vous voulez de la même façon.

Cron fait des siennes

Si vous êtes arrivés jusque là, tout devrait normalement bien marcher… Sauf cron. En effet, on utilise gpg-agent pour mettre la phrase de passe de la clé GPG en cache, gpg-agent a besoin de variables d'environnements pour fonctionner, et cron n'a pas accès aux mêmes variables d'environnements que vous. Ça engendre des situations qui sont un cauchemar à débugger, mais voilà la solution que j'ai fini par trouver après avoir sué sang et eau pour faire marcher l'automatisation de tout ça.

Éditez le fichier de configuration de cron avec crontab -e. Commencez par y ajouter, au tout début, la ligne :

DISPLAY=:0

pour que lorsque gpg-agent aura oublié votre phrase de passe GPG, il sache sur quel écran afficher sa petite fenêtre qui va vous la demander. Ensuite, pour chacune des lignes où vous invoquez soit offlineimap, soit msmtp (ou msmtp-queue), ajoutez au début de la commande :

. /home/votreidentifiant/.gpg-agent-info && export GPG_AGENT_INFO &&

par exemple, la commande d'OfflineIMAP de quelques articles en arrière était :

*/2 * * * * /usr/bin/offlineimap > /dev/null 2> /dev/null

et elle va devenir :

*/2 * * * * . /home/votreidentifiant/.gpg-agent-info && export GPG_AGENT_INFO && /usr/bin/offlineimap > /dev/null 2> /dev/null

(mais vous feriez mieux, dans un premier temps, de remplacer les /dev/null par des emplacements où vous pouvez lire les messages que renvoie la commande, pour pouvoir débugger en cas de problème).

Et comme ça, ça devrait fonctionner - on utilise un fichier créé par gpg-agent qui contient la variable d'environnement qu'il faut, ce qui permet aux futurs appels à gpg de savoir où trouver (ou demander) la phrase de passe.

Chiffrez et signez vos messages

Passons aux choses sérieuses : on va utiliser notre jolie paire de clés pour signer tous les messages envoyés via mutt, et chiffrer ceux qui sont possibles. Déjà, si vous avez des amis qui utilisent GPG, c'est le moment d'aller ajouter leurs clés publiques dans votre trousseau :

gpg --search-keys lenomdevotrepote

(suivez les instructions pour les ajouter à votre trousseau) et d'exporter la vôtre sur le serveur officiel de GnuPG :

gpg --send-keys EA627AA3

remplacez bien sûr ici et dans toute la suite EA627AA3 par l'identifiant de votre clé.

Dans le fichier de configuration de mutt, ajoutez une ligne du style source ~/.mutt/gpg pour mettre dans un même fichier tout ce qui concerne GPG (et si vous comptez utilisez plusieurs clés différentes plus plusieurs comptes différents, faites plusieurs fichiers, et sourcez-les au bon endroit).

Dans le fichier en question, glissez donc tout un tas de commandes compliquées pour dire quelles commandes utiliser : mutt connaît le principe d'OpenPGP, mais est prévu pour pouvoir utiliser n'importe quel logiciel qui parle le même protocole. Du coup, il faut lui indiquer à la main toutes les commandes de chiffrement, de déchiffrement, de signature, etc. En pratique, recopiez tout ça : à part l'identifiant de la clé, vous n'avez rien à changer.

# Commandes à utiliser avec gpg
set pgp_decode_command="gpg --no-verbose --batch --output - %f"
set pgp_verify_command="gpg --no-verbose --batch --output - --verify %s %f"
set pgp_decrypt_command="gpg --no-verbose --batch --output - %f"
set pgp_sign_command="gpg --no-verbose --batch --output - --armor --detach-sign --textmode %?a?-u %a? %f"
set pgp_clearsign_command="gpg --no-verbose --batch --output - --armor --textmode --clearsign %?a?-u %a? %f"
set pgp_encrypt_only_command="/usr/lib/mutt/pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust --encrypt-to 0xEA627AA3 -- -r %r -- %f"
set pgp_encrypt_sign_command="/usr/lib/mutt/pgpewrap gpg --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust --encrypt-to 0xEA627AA3 -- -r %r -- %f"
set pgp_import_command="gpg --no-verbose --import -v %f"
set pgp_export_command="gpg --no-verbose --export --armor %r"
set pgp_verify_key_command="gpg --no-verbose --batch --fingerprint --check-sigs %r"
set pgp_list_pubring_command="gpg --no-verbose --batch --with-colons --list-keys %r" 
set pgp_list_secring_command="gpg --no-verbose --batch --with-colons --list-secret-keys %r" 
set pgp_good_sign="^gpg: Good signature from"

Ensuite vient la « vraie » configuration. Dans l'ordre, on va indiquer :

  • qu'on utilise gpg-agent,
  • la clé qu'on utilise pour signer,
  • qu'on veut signer tous les messages sortants,
  • qu'on chiffre automatiquement les réponses à des messages signés (parce que quand on sait que quelqu'un signe ses mails, on va pouvoir chiffrer les messages qu'on lui envoie),
  • qu'on chiffre aussi automatiquement les réponses à des messages chiffrés,
  • et qu'on souhaite vérifier la signature de tous les messages reçus (ce qui, en supposant que vos contacts protègent suffisamment bien leurs clés secrètes, garantit que personne n'est en train d'usurper leur identité).
set pgp_use_gpg_agent
set pgp_sign_as=0xEA627AA3
set crypt_autosign
set crypt_replyencrypt
set crypt_replysignencrypted
set crypt_verify_sig

Voilà un bon début, et ça peut même vous suffire. Sachez quand même que certains clients de messagerie (notamment des vieuuux Outlook) n'aiment pas recevoir des messages signés, et n'affichent qu'une erreur lorsqu'ils en reçoivent (ce qui est incroyablement stupide, vu qu'une signature n'est rien de plus qu'un petit fichier texte joint à chaque mail, mais bon). Dans ce cas, on peut avoir envie de rajouter des hooks du genre :

send-hook '~t @vetagro-sup\.fr' "set crypt_autosign=no"

dans la configuration de mutt. Notez que si vous mettez la ligne précédente telle quelle et que vous envoyez un mail à un des destinataires concernés par le hook, l'option crypt_autosign vaudra no pour toute la suite de cette exécution de mutt. Il faut donc ajouter, avant la ligne précédente, un hook qui remet l'option dans son état désiré :

send-hook . "set crypt_autosign=yes"

Si après, ponctuellement, vous avez envie de ne pas signer un mail (ou de le chiffrer, ou de façon générale de changer les paramètres sur un mail envoyé), c'est la touche p qui permet de faire ça, juste avant l'envoi d'un message.

À part ça, il manque une fonctionnalité pourtant assez naturelle : le fait de chiffrer automatiquement les messages lorsqu'on a la clé publique du destinataire dans son trousseau. Il n'y a pas d'option pour ça, donc j'utilise un hack très crade : un script qui génère automatiquement un fichier de configuration mutt avec des lignes du type :

send-hook "!~l ~t machin\\.truc@bidule\\.wat" "set pgp_autoencrypt pgp_autosign"

pour chaque adresse machin.truc@bidule.wat présente dans le trousseau. Le script est trouvable par ici, et pour l'utiliser, il suffit de le rendre exécutable, de l'exécuter et de sourcer le fichier obtenu dans la configuration de mutt (il s'appelle par défaut pgp_auto). Vous pouvez aller jeter un œil au code du script si ça vous amuse, c'est du beau sed bien violent. Lancez le script à nouveau de temps en temps, lorsque votre trousseau grossit (demandez à cron de le faire une fois par semaine, par exemple).

Considérations de sécurité

Vous avez peut-être l'impression que vous avez fait dépendre plusieurs de vos mots de passe d'un mot de passe unique, ce qui n'a pas vraiment l'air d'améliorer la sécurité du système. C'est une remarque qui n'est pas totalement infondée, c'est pourquoi la phrase de passe GPG est extrêmement importante, et doit donc être solide et n'être stockée à aucun endroit du système (si il y a un mot de passe que vous devriez retenir par cœur et ne recopier nulle part, c'est celui-ci).

Néanmoins, maintenant, si on vous vole votre disque ou qu'on pirate votre ordinateur, l'attaquant n'a pas un accès direct aux mots de passe de vos comptes de messagerie - et si votre phrase de passe GPG est bonne, il ne pourra pas disposer des ressources matérielles nécessaires pour les trouver (ça lui est totalement impossible sans votre phrase de passe). Vous me direz « mais gpg-agent retient mon mot de passe, donc il doit bien être quelque part… » : vous avez raison, mais gpg-agent stocke ce mot de passe dans la RAM : dès que votre ordinateur est éteint, il disparaît en quelques secondes (à moins de plonger ladite RAM dans de l'azote liquide - mais ça paraît raisonnable de supposer que le risque est minime). Pas de problème à ce niveau-là non plus, donc !

Si vous voulez faire les choses jusqu'au bout et suivre les conseils avancés des professionnels de la sécurité des systèmes d'information, cette page (en anglais) répertorie les pratiques à adopter pour limiter les risques au maximum.

Conclusion

C'est à peu près tout, je crois. Et comme je ne crois pas avoir raté quoi que ce soit de majeur, j'imagine que ça conclut cette série sur la gestion locale de ses mails avec des outils légers, bien conçus et configurables à l'infini ; le tout avec une bonne couche de sécurité. N'hésitez pas à m'envoyer corrections et suggestions pour améliorer cette série de tutoriels !

Au risque de me répéter d'article en article, un grand merci à a3nm pour ses remarques et suggestions ayant permis de compléter et d'améliorer ce billet.

Tout ce que je raconte ici sont mes opinions personnelles, pas celles de mon employeur.
Je suis toujours ravi de recevoir des réactions, critiques, questions, ou autres commentaires sur ce que j'écris. Envoyez-moi ce qui vous chante à se.niatnofsed@neimad.