En effet, le protocole https est le même que le protocole http à une nuance près : avant même de communiquer entre eux sur le service demandé, les ordinateurs commencent par vérifier que le fournisseur du service est bien celui qu'il prétend. Une fois que cette vérification a été faite, les deux ordinateurs décident de crypter toutes leurs communications relatives au service (par exemple, des échanges de mot de passe) de façon à ce qu'un ordinateur au milieu de la communication ne puisse pas écouter et enregistrer les communications pour avoir accès à ces données. Il y a toujours des ordinateurs au milieu de vos communications, par exemple ceux de votre fournisseur d'accès (qui ne sont pas immunisés à des attaques hostiles de la part de pirates).

La technique est simple. Lorsqu'on parle à un ordinateur pour lui demander un service (par exemple : https://galerie.dubacq.fr pourrait être le nom de domaine auquel répond mon ordinateur pour présenter une galerie), celui-ci commence par présenter un certificat X509 garantissant qu'il est galerie.dubacq.fr. Je vais expliquer seulement le cas où c'est lui-même qui garantit cette exactitude (un certificat auto-signé). L'autre méthode est de faire signer le certificat par une autorité directement connue de votre navigateur web et la procédure est assez proche (mais dépend d'une société tierce, donc je ne vais pas m'étendre : c'est leur rôle).

La difficulté commence au moment où un ordinateur veut servir à la fois galerie.dubacq.fr et jean-christophe.dubacq.fr (ce blog) de façon sécurisée. En effet, comme aucune requête spécifique ne vient dire quel est le service demandé avant la vérification du certificat, on ne peut pas envoyer un certificat distinct selon que le service demandé est l'un ou l'autre. On est obligé de présenter un certificat qui présente deux noms (ou plus) avant de pouvoir communiquer pour savoir lequel des services est réellement demandé. Or la spécification X509 ne propose par défaut qu'un seul nom. Heureusement, une extension permet d'en mettre plusieurs. Il suffit de le savoir, et de comprendre la documentation (à la fois complète et complexe) qui va avec.

Voilà le script que j'ai fait qui me fabrique un certificat auto-signé tout propre pour un ou plusieurs domaines. Mon script garde tous les morceaux intermédiaires. J'espère qu'il sera utile à quelqu'un. Évidemment, un certificat auto-signé a ses limites (il repose sur le fait que l'utilisateur accepte une première fois le certificat à un moment où il est sûr qu'il est valide). Mais il n'y a pas à l'heure actuelle de certificat gratuit accessible au particulier et reconnu par défaut par les navigateurs web.

Le script est livré avec un petit fichier auxiliaire indispensable pour son bon fonctionnement, il ne faut pas hésiter à modifier les valeurs par défaut qui sont dedans. Il n'y a pas besoin d'être super-utilisateur (administrateur) pour exécuter ce script, mais il y a probablement besoin de l'être pour utiliser les fichiers produits.

Il est à noter qu'il y a en fait plusieurs fichiers produits: les trois plus utiles sont la clé non-protégée (extension key, à garder précieusement), le certificat proprement dit (extension crt qu'on doit rendre le plus public possible) et le certificat combiné (extension pem) qui regroupe les deux précédents (certaines applications de serveurs préfèrent ce format à la donnée des deux autres).

Je recommande que tous les serveurs en https aient une page web visible et trouvable qui donnent ces certificats à télécharger. Cela permet aux utilisateurs de les télécharger directement depuis un endroit sûr pour les utiliser plus tard dans un environnement hostile.

Au cas où votre fournisseur ne vous donne pas de page web avec le certificat, il est toujours possible de le récupérer (autant pour https que pour d'autres protocoles comme imaps ou pops qui servent à relever le courrier électronique). La commande suivante (sous linux ou autre système avec openssl installé le fait :

SITE="www.example.org"; PORT=993
openssl s_client -connect $SITE:$PORT -showcerts  $SITE.crt </dev/null | sed -ne '/BEGIN CERTIFICATE/,/END CERTIFICATE/ p' > $SITE.crt