jeudi 20 décembre 2018
Ce billet a été vu pour la première fois sur le blog de Synbioz le 20 December 2018 sous licence CC BY-NC-SA.

Une assez bonne intimité

Si vous êtes utilisateur de MacOS, il y a de fortes chances que vous utilisiez Apple Mail pour échanger des courriels. Et comme vous êtes sensible à la confidentialité des informations que vous échangez, vous signez et chiffrez vos courriels avec GPG ! Sous MacOS, le plus simple pour ce faire est d’installer GPG Suite. Mais récemment une petite ligne a attiré mon attention dans le changelog de cet outil ; et la page d’accueil du site web présentant ce dernier vient confirmer mes soupçons :

GPG Suite includes a one-month trial of GPG Mail. For continued use of GPG Mail, please purchase a support plan

Eh oui, ça nous pendait au nez ! GPG Mail, le plugin de chiffrement pour Apple Mail livré avec GPG Suite, l’outil phare de cette dernière, se voit dorénavant accompagné d’un support plan et son utilisation par le biais de la version packagée de GPG Tools est sujette à paiement.

Release notes: blah blah blah Mojave, oh and btw if you're still reading,
it's now paid software, but we won't explain what you're paying for, just give
the money… This isn't clear at all, you won't get anything from me until I
know exactly what I'm buying! Really bad move…

Il est à noter que la licence logicielle reste libre et que le code source est disponible sur le site de GPG Tools et sur GithHub.

Bon, on ne va pas se plaindre, c’est bien pratique de pouvoir télécharger une image disque toute prête à installer et ce n’est pas non plus une ruine. Mais nous sommes des développeurs et payer pour un outil qu’on pourrait bidouiller nous-même, ça ne nous ressemble pas !

Challenge accepted!

Alors je vous propose ceci : plutôt que de forker GPG Mail, si on essayait de comprendre un peu mieux comment fonctionne GPG, comment déchiffrer un courriel, et puisqu’on est joueur, si on faisait tout ça dans Vim ? Juste pour le plaisir de découvrir et d’apprendre des trucs, hein, loin de moi l’idée de rabaisser le caquet aux utilisateurs d’emacs convaincus d’être les seuls à pouvoir tout faire dans leur éditeur favori !

GPG ou PGP ?

GPG ou GnuPG (pour GNU Privacy Guardoui, on aime les acronymes récursifs imbriqués dans le monde du libre) est une implémentation libre du protocole standard OpenPGP (RFC 4880), lui-même basé sur PGP 5.X (ici PGP signifie Pretty Good Privacy) mais que l’on nomme généralement « PGP 3 ». C’est tout de suite plus clair, non ?

Le standard OpenPGP se base sur une combinaison de clés publiques fortes et de chiffrement asymétrique pour fournir des services de sécurité à l’usage des communications électroniques et du stockage de données. Ces services incluent confidentialité, gestion des clés, authentification et signatures numériques.

Note sur les RFC pour briller en société

On parle de protocole, de standard, et discrètement je vous glisse un petit lien vers une RFC, mais quésaco ?

Wikipédia nous apprend qu’une RFC, Request For Comments, littéralement « demande de commentaires », est un document officiel décrivant les aspects techniques d’Internet, ou de différents matériels informatiques (routeurs, serveur DHCP). Peu de RFC sont des standards, mais tous les documents publiés par l’IETF sont des RFC.

L’IETF, Internet Engineering Task Force, élabore et promeut des standards Internet. Sa particularité réside dans le fait qu’il s’agit en réalité d’un groupe informel, sans statut, sans membre, sans adhésion. Le travail technique est accompli dans une centaine de groupes de travail ; groupes généralement constitués d’une liste d’adresses e-mail. Pour en apprendre davantage à ce sujet, je vous conseille la page Wikipédia de l’IETF comme point d’entrée !

GPG, comment ça marche ?

GPG utilise un système de chiffrement asymétrique. Pour en comprendre l’intérêt, voyons d’abord comment fonctionne un système symétrique.

Dans un système symétrique, la même clé est utilisée pour chiffrer et déchiffrer un message. Ainsi, on voit vite venir le souci : comment communiquer cette clé en toute sécurité au destinataire de mon message, afin qu’il puisse le déchiffrer ? Et c’est bien là que le bât blesse, car s’il y a échange de clé, si discret soit-il, il réside toujours une possibilité que celle-ci soit subtilisée par un gredin durant l’échange.

La solution à ceci, celle qui est proposée par le protocole OpenPGP, consiste à disposer d’une paire de clés ; l’une publique, l’autre privée. Ces deux clés sont intrinsèquement liées grâce à une formule mathématique complexe.

Ainsi chacune de ces deux clés a un rôle bien précis. La clé publique est librement diffusée et accessible à tous. C’est elle qui sert à chiffrer un message. En revanche, pour déchiffrer ce dernier il vous faudra disposer de la clé privée liée à celle-ci. Il s’entend qu’il est de votre responsabilité de garder bien précieusement votre clé privée et de ne la divulguer sous aucun prétexte.

Nous avons donc un système de chiffrement asymétrique, basé sur une paire de clés publique-privée, nous affranchissant de tout échange de clé. La sécurité d’un tel système tient de la complexité même des clés utilisées et du fait qu’il est virtuellement impossible de « deviner » la clé privée à partir de la clé publique ; du moins avec la puissance de calcul et les connaissances techniques actuelles.

Déchiffrer des lettres

Concentrons-nous sur le déchiffrement. Plus précisément, amusons-nous à déchiffrer des courriels. Et oui, rien de tel qu’un bon vieux courriel chiffré pour échanger des identifiants avec un collègue quand on n’a pas un joli petit coffre-fort pour manier ça efficacement et en toute sécurité.

Si votre logiciel de courriel n’intègre pas un plugin GPG, vous devriez vous trouver confronté à un obscur fichier .asc en pièce jointe à celui-ci.

encrypted_mail.png

Un fichier .asc (ASCII Armored) est un fichier chiffré ne contenant que des caractères ASCII imprimables et qui ressemble à ceci :

–----BEGIN PGP MESSAGE-----
Version: OpenPrivacy 0.99

hQEMA0ul78Xi7kyWAQf9GH8tNFNNIymdfJ0YHDDtEUIe1fWHglSb+JbE4nH9fW3e
OmHq/7pnQ2eppyjwe52M2neA8IPjn3jYrulJATVo4fLYJVLpSHuchMSxs42d96rf
N932r94g5PAidHeRMWDDSfD+8b3+3ngWW4GoPkx6ruNnyiM7CsVWlYNolSl4Kewx
m7s/jKdqqYMj98UXkiyYTGxPY2NRLoaP0laFC/zqsu9f0BQ+yPiLYE6ek2yFafpW
YT3xtjQOsY7PLa7BSNnq9kcG2RV2zuk8vzMs8aGQpp/kA4yHgMdn8gezW1j5d0yy
fvQ4maC7QOn2YKUt8XUv18rFzaQ90CSHOt92pWvCsNLAAQH0IFzeKezxDJ7FVnqa
w8TAIjo/Wdy+UIuRqk6NwB0i4Palr55vnt2cwu5QFKdzeSdYRuMiYw0wKKbzvz7G
AP5VUh5Oex/bcI6/44eB5iy1zx47tNe+aKacSUBmncaASE2dPUq9q6pKSFnxCXFq
hA/hYy0BB/WwwdpoTCOMOaa46po4GjQ4HBwFHGNPZU48G6chlm77H/hMcXIpFTJL
zxM+NDz9XuegP58J/vzY4vR2mcZhfBFUs6VsLJ0+7KOE2xU=
=MYEb
–----END PGP MESSAGE-----

On y distingue plusieurs sections :

  1. Une ligne d’en-tête appropriée au type de données ;
  2. Des en-têtes « armor » (optionnelles) ;
  3. Une ligne vide
  4. Nos données chiffrées ;
  5. Une somme de contrôle ;
  6. Une ligne de fin de fichier relative à la ligne d’entête.

Si ce message ne nous est pas adressé et qu’on tente tout de même de le déchiffrer, GPG va nous rappeler à l’ordre :

❯ gpg --decrypt patamoi.asc
gpg: Remarque : l'expéditeur a demandé « à votre seule attention »
Can't anyone keep a secret around here?

Notez l’humour des développeurs de GPG ;)
Si en revanche, ce message nous est bien destiné, il sera alors déchiffrable :

❯ gpg --decrypt zephyr.asc
gpg: chiffré avec une clef RSA de 2048 bits, identifiant 4BA5EFC5E2EE4C96, créée le 2016-09-05
      « François Vantomme <akarzim@gmail.com> »
Dès Noël où un zéphyr haï me vêt de glaçons würmiens je dîne d’exquis rôtis de bœuf au kir à l’aÿ d’âge mûr & cætera !

GPG nous précise tout d’abord la clé qui a servi au chiffrement du message, l’identité du propriétaire de cette clé publique — c’est censé être vous, mais il ne vous est pas interdit de posséder plusieurs paires de clés, utilisées à discrétion dans des contextes distincts — puis enfin le corps de message.

Vim & GPG

À l’aide du bien-nommé plugin vim-gnupg, Vim peut désormais lire (déchiffrer) et écrire (chiffrer) des fichiers .asc, .gpg ou pgp sans avoir à taper une seule commande. C’est tout de même bien pratique !

vim-gpg.png

Alors, excusez-moi de vous demander pardon, mais ça, c’est bien joli, mais c’est juste un pangramme bourré de diacritiques, ça n’a rien à voir avec un mail à ce que je sache ! Et puis d’ailleurs, on ne devait pas le faire nous-même avec nos petites mimines ce plugin ?!
— un lecteur impatient

Très bien.

Vous l’aurez deviné, un courriel c’est un peu plus que quelques lignes de texte brut. Ces lignes sont structurées et respectent un… protocole standard, tout à fait ! Vous la voyez venir la RFC ?

Et le MIME c’est pour demain ?

La RFC qui nous intéresse ici décrit comment formater des messages électroniques amenés à être transférés à travers le réseau Internet. Ces messages peuvent contenir du texte (plus ou moins complexe : diacritiques, idéogrammes…), mais aussi des images, des vidéos, ou encore tout à la fois. Il s’agit de la RFC 1521 MIME : Multipurpose Internet Mail Extensions.

Tant qu’on y est, sa petite sœur nous sera utile également, j’ai nommé la RFC 1847 Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted.

Et juste pour redonner un peu de contexte, on parle ici de standards définis respectivement en septembre 1993 et octobre 1995 ! Oui, j’ai bien conscience qu’une partie d’entre vous était à peine née à l’époque. À l’heure où un nouveau framework web fait son apparition tous les quatre matins, une telle pérennité donne à réfléchir !

Voici donc à quoi ressemblerait un courriel que vous aurait envoyé un de vos collègues, une fois déchiffré :

Content-Type: multipart/signed;
	boundary="100D825B-AAA7-4DCE-ADFA-FD088247453E";
	protocol="application/pgp-signature";
	micalg=pgp-sha512

--100D825B-AAA7-4DCE-ADFA-FD088247453E
Content-Type: multipart/alternative; boundary="5be16a3a_49f1d5d6_122c5"

--5be16a3a_49f1d5d6_122c5
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

D=C3=A8s No=C3=ABl o=C3=B9 un z=C3=A9phyr ha=C3=AF me v=C3=AAt de gla=C3=A7=
ons w=C3=BCrmiens je d=C3=AEne d=E2=80=99exquis r=C3=B4tis de b=C5=93uf au =
kir =C3=A0 l=E2=80=99a=C3=BF d=E2=80=99=C3=A2ge m=C3=BBr & c=C3=A6tera=C2=
=A0!

Jonathan =46ran=C3=A7ois
Responsable d=E2=80=99unit=C3=A9.

www.synbioz.com
Libres d'=C3=AAtre ensemble.
--5be16a3a_49f1d5d6_122c5
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

<html><head><style>body{font-family:Helvetica,Arial;font-size:13px}</style>=
</head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; -web=
kit-line-break: after-white-space;"><div id=3D"bloop_customfont"style=3D"fo=
nt-family:Helvetica,Arial;font-size:13px;margin:0px;line-height:auto;">No=
=C3=ABl o=C3=B9 un z=C3=A9phyr ha=C3=AF me v=C3=AAt de gla=C3=A7ons w=C3=BC=
rmiens je d=C3=AEne d=E2=80=99exquis r=C3=B4tis de b=C5=93uf au kir =C3=A0 =
l=E2=80=99a=C3=BF d=E2=80=99=C3=A2ge m=C3=BBr & c=C3=A6tera=C2=A0!</div><br=
><div id=3D"bloop_sign_1541499413265878016" class=3D"bloop_sign"><div style=
=3D"font-family: Helvetica; font-size: 12px;">Jonathan Fran=C3=A7ois</div><=
div><font face=3D"Helvetica"><span style=3D"font-size: 12px;">Responsable d=
=E2=80=99unit=C3=A9.</span></font></div><div><font face=3D"Helvetica"><span=
 style=3D"font-size: 12px;"><br></span></font></div><div style=3D"font-fami=
ly: Helvetica; font-size: 12px;"><br><div>www.synbioz.com</div><div>Libres =
d'=C3=AAtre ensemble.</div></div></div></body></html>
--5be16a3a_49f1d5d6_122c5--

--100D825B-AAA7-4DCE-ADFA-FD088247453E
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=signature.asc
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: Message signed with OpenPGP using AMPGpg

–----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEk9invAb92k3WNXYwpRoFaZYFpwMFAlvhajoACgkQpRoFaZYF
pwME5BAAmAiWUsuTktN0se9u7ZO5Xl5lfWAiK6aRCkaHgLGu5ZhkwDF5n3w+5vqj
McHwYfr519DsR6SF4rfLmdN3Li8gikKkqLlKExQJtxJpV1F8y7FAOSr9cry9OlXS
LxtOBJZSkwVxzczH//+qOgiF3cBjTLU5dE1uAUURDOxAwIDf2iNBaoPaRrlMyXYv
TSZkfNUA+PiEkmuJkrUW8398LSxaRN5ONP8gNmgIGa5bZQ5BP59tX0lyWQr3OSLJ
OzfuC0Ago1VHoCGtC7AKVt+rmEXHrRAMRiq43gQzK67u7VdHtfoM6NUFHyCX5xOL
qa16uqCfNZXdqwRjWFv0kIG5c70Ru8wPNVroPuphnPJWkkr9N+KWnA1GZxlRSW1u
mjf7e1WoUEsADORj3njEv3Hdo1Z0MMFgAn3B2vXvWwLvRyx1ZFTFnDXd9fzzwEud
ghAKO27s8IfVhRwlKiIo6BsVJin/OQgSuFSz+qS5JEpaX16COxKg2Tg1Ppxqi8Tf
IoN4l3shakTlt51ali09etvyQkmbhfN4gky4cLgrHmlJBgDNFRKW3AHqTmaRyYEb
Ci9yTxgg6G5SrkLSDF1lHxIz4fkl4cOn+EXOOD/z1X46QLZFRGe0pjQzfyYB3Pym
ItCmm4yzPrQvkcy4T/nAM/D3VrT+tcxUNze6u822W8Ca0w0pU7A=
=UNzk
–----END PGP SIGNATURE-----

--100D825B-AAA7-4DCE-ADFA-FD088247453E--

Ah bah oui, c’est tout de suite moins digeste ! Ce n’est pourtant pas aussi abscons que ça en a l’air. Procédons méthodiquement.

Tout d’abord, la première ligne nous informe que nous nous trouvons en présence d’un message signé (Content-Type: multipart/signed) tel que défini dans la RFC 1847. Pour ce faire le protocole application/pgp-signature a été utilisé, ainsi nous savons comment vérifier cette signature. Les différentes parties du message (multipart) seront délimitées (boundary) par la chaîne 100D825B-AAA7-4DCE-ADFA-FD088247453E. La dernière information, micalg, pour Message Integrity Check (MIC) algorithm est un peu trop technique pour le cadre de cet article, mais très bien détaillée dans la RFC si cela vous titille.

Si nous synthétisons, nous avons donc un message en plusieurs parties, décomposé comme ceci :

Content-Type: multipart/signed;
	boundary="100D825B-AAA7-4DCE-ADFA-FD088247453E";
	protocol="application/pgp-signature";
	micalg=pgp-sha512

--100D825B-AAA7-4DCE-ADFA-FD088247453E

corps du message à signer

--100D825B-AAA7-4DCE-ADFA-FD088247453E

signature

--100D825B-AAA7-4DCE-ADFA-FD088247453E--

C’est la consigne !

Nous n’allons pas nous attarder sur cette partie du message, mais en quelques mots, le format d’une signature de type application/pgp-signature est décrit dans la RFC 3156 MIME Security with OpenPGP. Celle de notre courriel ressemble à ceci :

Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=signature.asc
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: Message signed with OpenPGP using AMPGpg

—----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEk9invAb92k3WNXYwpRoFaZYFpwMFAlvhajoACgkQpRoFaZYF
pwME5BAAmAiWUsuTktN0se9u7ZO5Xl5lfWAiK6aRCkaHgLGu5ZhkwDF5n3w+5vqj
McHwYfr519DsR6SF4rfLmdN3Li8gikKkqLlKExQJtxJpV1F8y7FAOSr9cry9OlXS
LxtOBJZSkwVxzczH//+qOgiF3cBjTLU5dE1uAUURDOxAwIDf2iNBaoPaRrlMyXYv
TSZkfNUA+PiEkmuJkrUW8398LSxaRN5ONP8gNmgIGa5bZQ5BP59tX0lyWQr3OSLJ
OzfuC0Ago1VHoCGtC7AKVt+rmEXHrRAMRiq43gQzK67u7VdHtfoM6NUFHyCX5xOL
qa16uqCfNZXdqwRjWFv0kIG5c70Ru8wPNVroPuphnPJWkkr9N+KWnA1GZxlRSW1u
mjf7e1WoUEsADORj3njEv3Hdo1Z0MMFgAn3B2vXvWwLvRyx1ZFTFnDXd9fzzwEud
ghAKO27s8IfVhRwlKiIo6BsVJin/OQgSuFSz+qS5JEpaX16COxKg2Tg1Ppxqi8Tf
IoN4l3shakTlt51ali09etvyQkmbhfN4gky4cLgrHmlJBgDNFRKW3AHqTmaRyYEb
Ci9yTxgg6G5SrkLSDF1lHxIz4fkl4cOn+EXOOD/z1X46QLZFRGe0pjQzfyYB3Pym
ItCmm4yzPrQvkcy4T/nAM/D3VrT+tcxUNze6u822W8Ca0w0pU7A=
=UNzk
—----END PGP SIGNATURE-----

On y apprend qu’il s’agit d’une pièce jointe (Content-Disposition: attachment) qui aura pour nom signature.asc. La signature en elle-même est comprise entre les lignes -----BEGIN PGP SIGNATURE----- et -----END PGP SIGNATURE-----.

Vous vous demandez à présent comment extraire une pièce-jointe d’un courriel ! En effet, ici il s’agit de la signature et il y a peu de chances qu’on ait besoin de la manipuler directement. Par contre, il pourrait tout aussi bien s’agir d’un document PDF ou d’une image que vous souhaiteriez récupérer.

Rien de plus simple ! Il existe un petit utilitaire en ligne de commande à installer nommé Mpack (MIME mail packing and unpacking). Il suffit de lui donner en entrée notre courriel déchiffré pour qu’il en extraie automatiquement les pièces-jointes dans le dossier courant.

❯ gpg -d zephyr.asc | munpack
munpack: reading from standard input
gpg: chiffré avec une clef RSA de 2048 bits, identifiant 4BA5EFC5E2EE4C96, créée le 2016-09-05
      « François Vantomme <akarzim@gmail.com> »
signature.asc (application/pgp-signature)

Dissection du corps

Le corps de notre message est lui de type multipart/alternative. La RFC 1521 nous apprend que cela signifie que les mêmes données (ici, le message de notre collègue) seront représentées de plusieurs manières. En l’occurrence, une première fois en texte brut (Content-Type: text/plain), puis au format HTML (Content-Type: text/html). Concentrons-nous sur la partie en texte brut :

Content-Type: multipart/alternative; boundary="5be16a3a_49f1d5d6_122c5"

--5be16a3a_49f1d5d6_122c5
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

D=C3=A8s No=C3=ABl o=C3=B9 un z=C3=A9phyr ha=C3=AF me v=C3=AAt de gla=C3=A7=
ons w=C3=BCrmiens je d=C3=AEne d=E2=80=99exquis r=C3=B4tis de b=C5=93uf au =
kir =C3=A0 l=E2=80=99a=C3=BF d=E2=80=99=C3=A2ge m=C3=BBr & c=C3=A6tera=C2=
=A0!

Jonathan =46ran=C3=A7ois
Responsable d=E2=80=99unit=C3=A9.

www.synbioz.com
Libres d'=C3=AAtre ensemble.
--5be16a3a_49f1d5d6_122c5

alternative HTML

--5be16a3a_49f1d5d6_122c5--

Alors je ne sais pas vous, mais moi j’aurais tendance à penser qu’en termes de lisibilité on pourrait faire nettement mieux ! Regardez-moi ce texte, c’est à peine si on en distingue quelques mots ! Que s’est-il passé ?

La réponse se trouve dans cette simple ligne :

Content-Transfer-Encoding: quoted-printable

Notre texte a tout simplement été encodé dans un format permettant son transfert par courriel sans encombre. Ce format, quoted-printable, est défini, je vous le donne en mille, au sein de la RFC 1521.

Ainsi, pour pouvoir lire notre message, il va nous falloir le convertir en UTF-8. Il existe bien quelques outils en ligne de commande, tel qprint auquel on passe une option -d pour décoder notre message :

❯ qprint -d <<EOF
D=C3=A8s No=C3=ABl o=C3=B9 un z=C3=A9phyr ha=C3=AF me v=C3=AAt de gla=C3=A7=
ons w=C3=BCrmiens je d=C3=AEne d=E2=80=99exquis r=C3=B4tis de b=C5=93uf au =
kir =C3=A0 l=E2=80=99a=C3=BF d=E2=80=99=C3=A2ge m=C3=BBr & c=C3=A6tera=C2=
=A0!

Jonathan =46ran=C3=A7ois
Responsable d=E2=80=99unit=C3=A9.

www.synbioz.com
Libres d'=C3=AAtre ensemble.
EOF

Ce qui aura pour résultat :

Dès Noël où un zéphyr haï me vêt de glaçons würmiens je dîne d’exquis rôtis de bœuf au kir à l’aÿ d’âge mûr & cætera !

Jonathan François
Responsable d’unité.

www.synbioz.com
Libres d'être ensemble.

Mais voilà, nous ne souhaitons pas décoder l’ensemble de notre fichier, seulement les parties qui ont été encodées.

Alors, puisqu’on sait lire nos courriels chiffrés avec Vim grâce au plugin vim-gnupg, pourquoi ne pas s’essayer à la création d’un petit plugin pour décoder un bloc de texte quoted-printable ?

C’est ce que nous verrons en détails ensemble la semaine prochaine dans un article intitulé Vim, un plugin à la mimine !