26 avril 2024 - Le collectif IndieHosters
Voici un article de blog illustré pour tenter d’expliquer plus en détail le chiffrement sur Element et Matrix.
Comprendre les bases : Matrix, Element, Synapse ?
Pour commencer, parcourons les différents éléments qui composent le système de chat :
Element le client
Element c’est le client, c’est-à-dire l’interface pour faciliter la communication avec le serveur (pour ne pas communiquer en ligne de commande). C’est l’application sur votre ordinateur ou téléphone qui dialogue avec les serveurs de chat pour vous connecter ou pour envoyer des messages.
Matrix : le protocole
L’ensemble des techniques utilisées pour le déploiement, la communication serveur, certaines requêtes du client, le chiffrement… constitue un protocole, c’est le protocole Matrix.
Synapse : le serveur
Le serveur c’est l’endroit où est déployé l’instance de chat. Derrière, la technologie utilisée par IndieHosters c’est Synapse (mais il existe d’autres manières de déployer un serveur de chat compatible au protocole Matrix comme Conduit, Construct…). Sur ce serveur, quelques informations sont stockées notamment certaines informations liées au comptes et les salons créés sur le serveur (pas forcément les messages). Les messages reçus et non lus sont forcément stockés sur le serveur de réception (du destinataire du message).
L’envoi d’un message non chiffré
Commençons par le plus simple, l’envoi de messages non chiffrés. Par exemple Alex sur le serveur A (nom d’utilisateur.ice : @Alex:serveurA) veut parler avec Sacha sur le serveur S (@Sacha:serveurS). Dans cet exemple, le serveur A et le serveur S ne sont pas chiffrés.
Initialisation
Alex se connecte à Element avec son identifiant et son mot de passe. Element fait ensuite une requête à son serveur, :serveurA pour valider la connexion et récupérer les informations comme les paramètres des ses salons, s’il y a des messages en attente…
Envoi du message
0. Ecriture
Alex écrit son message
1. Copie
Le message est ensuite copié puis stocké sur le client Element d’Alex, soit localement soit sur son espace cloud dédié. Cela permet par la suite à Alex d’avoir accès à ses messages sans faire de nouvelles requêtes inutiles.
2. à 5. Envoi du message et chiffrement
Lorsqu’Alex appuie sur “envoyer” son client fait une requête depuis son serveur A vers le serveur de Sacha (serveurS) pour avoir l’autorisation d’envoyer le message. Si l’autorisation est accordée, le message est envoyé sur le serveur S.
Le message est chiffré lors de cet envoi via une requête sécurisée (via le protocole MatrixSSL). Cela permet d’éviter les potentielles interceptions de messages pendant le transfert, néanmoins, le message est accessible et lisible sur les serveurs où il transite et où il est stocké.
Réception du message
Le message est reçu sur le serveur S. Il est déchiffré et donc lisible par les administrateur.ices notamment. Il est stocké sur le serveur en attendant d’être lu.
1. et 2. Récupération du message
Sacha se connecte à son client Element avec son identifiant et son mot de passe (voir la phase d’initialisation). Element fait donc une requête à son serveur, :serveurS pour valider la connexion et récupérer les informations sur ses salons et pour vérifier les nouveaux messages.
S’il y a un nouveau message, alors celui-ci est envoyé via une requête sécurisée (chiffrement du message lors de la transmission via MatrixSSL) sur le client Element de Sacha.
3. Lecture et copie
Le message est maintenant sur le client Element de Sacha qui peut donc le lire sur son interface. Le message est copié sur son client (localement ou espace dédié).
Cet exemple reste identique si Alex et Sacha sont sur le même serveur. Il n’y a alors qu’un seul serveur de connexion et le serveur est à la fois serveur d’envoi et de réception.
Ici il s’agit d’un exemple d’envoi de message privé non chiffré entre 2 personnes mais c’est la même chose pour des salons non chiffrés entre plusieurs personnes.
Le chiffrement
Maintenant, comment cela marche-t-il avec des serveurs où le chiffrement est activé (par défaut ou volontairement) ?
Le chiffrement E2E (end to end encryption) signifie chiffrement de bout en bout. Ce protocole permet de rendre les messages d’Alex indéchiffrables dès l’envoi du message depuis son ordinateur jusqu’à la réception par Sacha sur son ordinateur (ou téléphone).
D’abord, les clés, publique et privée
Dès que le chiffrement est activé sur un serveur (ou sur un salon chiffré) alors Element génère des clés de chiffrement aux participant.es des salons. Une paire de 2 clés est générée. La combinaison de plusieurs clés (au moins 2) permet de chiffrer ou déchiffrer un message.
La clé publique
Elle est publiquement accessible, envoyée et stockée sur le serveur de la personne qui crée ses clés. Donc sur le serveur A pour Alex et le serveur S pour Sacha. Il suffit de faire une requête au serveur pour avoir accès à la clé.
La clé publique d’une personne est nécessaire lors de l’envoi d’un message par une autre personne pour chiffrer le message. Autrement dit, Alex a besoin de la clé publique de Sacha pour lui envoyer un message.
La clé privée
La clé privée est… privée, c’est-à-dire qu’elle ne doit pas être partagée. Elle est donc stockée coté client, donc sur Element, soit localement soit dans son espace cloud dédié. La clé privée est nécessaire lors de l’envoi pour chiffrer son propre message et lors de la réception pour déchiffrer un message qu’une autre personne a chiffré avec notre clé publique. Autrement dit :
- Sacha a besoin de sa clé privée pour chiffrer n’importe quel message qu’iel souhaite chiffrer, donc pour envoyer un message chiffré à Alex.
- Mais Sacha a aussi besoin de sa clé privée pour déchiffrer un message chiffré qui lui est adressé, par exemple les messages chiffrés qu’Alex lui envoie.
L’envoi d’un message chiffré
Initialisation : récupération des clés publiques
Lorsque Sacha se connecte à un salon chiffré (voir l’étape d’initialisation], Element envoie une requête au serveur du salon pour récupérer les clés publiques des membres des salons.
Envoi d’un message chiffré
0. Ecriture du message
Sacha écrit son message sur son client Element (donc en local). Le message est lisible.
1. Stockage du message
Le message écrit (et non encore chiffré) est alors stocké sur Element (localement ou sur son espace cloud dédié). Le stockage en local permet, là aussi, de ne pas avoir de protocole supplémentaire pour relire son message.
2. Copie du message
Le message est ensuite copié.
3. Chiffrement E2E du message
C’est cette copie du message de Sacha qui est chiffrée puis envoyée.
Pour chiffrer le message, il lui faut la clé privée de la personne qui envoie le message (Sacha) et la clé publique de la personne qui reçoit le message (Alex).
La clé publique d’Alex a été récupérée lors de la connexion. Avec la combinaison de ces 2 clés, sa clé privée et celle publique d’Alex, Sacha chiffre son message pour Alex.
Dans un salon chiffré où il y a plusieurs personnes, les clés publiques sont récupérées lors de la connexion au salon. Les messages sont alors chiffrés avec l’ensemble des clés publiques des personnes présentes dans le salon et la clé privée de la personne qui envoie le message.
4. Sécurisation supplémentaire
En plus du chiifrement, Matrix déploie un autre procole appélé MLS afin de surveiller, garantir et protéger le chiffrement de bout en bout du message (via des systèmes d’autentification, de signature, de détection…).
5. et 6. Envoi du message
Comme pour les messages non chiffrés, une requête est faite via le serveur S de Sacha vers le serveur A d’Alex afin d’autoriser l’envoi du message. Si l’autorisation est accordée, la copie du message chiffré est alors envoyée via une requête sécurisée (toujours via matrixSSL) qui vient chiffrer le message une seconde fois.
Réception du message
1. Sécurisation supplémentaire
Le message de Sacha, chiffré par le protocole E2E et “surveillé” par MLS, est stocké sur le serveur A en attendant d’être lu. Il est donc indéchiffrable par les administrateur.ices ou autres personnes ayant accès au serveur.
Ce protocole MLS est continu depuis le départ du message du client de Sacha jusqu’a ce qu’il arrive sur le client d’Alex. De la même manière que pour l’envoi du message, le chiffrement lors de la réception du message est aussi garanti et protégé via le même procotole MLS.
2. Récupération du message
Alex se connecte à son serveur A via son client Element. Comme il y a un nouveau message, ce message chiffré est envoyé puis reçu sur le client Element d’Alex via une requête sécurisée qui chiffre le message.
3. Déchiffrement
Le message reçu, toujours chiffré, est copié sur puis enfin déchiffré. Pour déchiffrer le message, il faut :
- la clé publique de la personne qui a envoyé (et chiffré) le message (Sasha). Celle-ci a été récupéré lors de la connexion au serveur.
- la clé privée de la personne qui a reçu (et veut déchiffrer) le message (Alex). Celle-ci est stockée sur son client Element, elle est accessible sans nouvelle requête. Avec cette combinaison de ces 2 clés, le message est déchiffré localement et lisible par Alex.
4. Copie du message
Une copie déchiffrée du message est finalement copiée localement (ou sur un espace cloud dédié) sur le client d’Alex.
Simplification
Le processus décrit ici est en fait très simplifié. Il y a, comme expliqué, 3 niveaux de chiffrement :
- MLS qui assure que les communications sont chiffrés
- MatrixSSL qui chiffre les messages lors de sa transmission du client au serveur, entre les serveurs et du serveur au client.
- Et enfin le protocole de chiffrement de bout en bout E2E qui est appelé protocole Olm (pour les messages entres 2 personnes) et MegaOlm (pour les messages de groupes)
En réalité, les protolcoles de chiffrement Olm et MegaOlm ne chiffrent pas les messages avec seulement 2 clés.
En fait, il y a un mécanisme de génération et de changement de clés en permanence ce qui permet de renforcer la sécurité. Le principe reste identique, le chiffrement d’un message est réalisé par la combinaison d’une clé privée et d’une clé publique (ou plusieurs pour les groupes). Cependant, une personne n’a pas qu’une seule clé privée et une seule clé publique.
Le chiffrement se fait via un systéme de clés temporaires, de clés de signature et d’identification… (privée et/ou publique), elles-mêmes générées à partir de plusieurs combinaisons de ces clés ou encore d’autres clés temporaires.
Tout ces mécanismes de génération de clés et de transmission de nouvelles clés permettent de garantir qu’une personne non autorisée qui parvient à déchiffrer un message ne puisse accéder qu’à ce seul et unique message donc ni aux anciens messages, ni aux messages suivants.
Voici quelques liens pour aller plus loin sur ces protocoles de chiffrement :
-> Elment : End-to-end encryption
-> Matrix : End-to-End Encryption implementation guide
-> Matrix spec : messaging-algorithms
-> Matrix git : Olm, A Cryptographic Ratchet
-> Matrix git : Signature keys and user identity in libolm
-> Matrix git : Megolm group ratchet
-> NccGroup : Olm Cryptographic Review
Les sessions
C’est quoi ?
On pourrait définir une session comme un “espace actif de connexion” avec son serveur Synapse. Lorsque qu’il y a une déconnection, la session est terminée et il faut ouvrir une nouvelle session.
Ainsi, il y a une session par moment et par manière d’accéder au serveur. Le nombre de sessions varie en fonction de l’endroit depuis lequel on se connecte (via Element notamment).
Autrement dit :
- Une connexion depuis l’application mobile Element, une session
- une connexion depuis l’application desktop sur ordi, une autre session, même si on est aussi connecté.e depuis l’application mobile en même temps
- une connexion via l’interface web depuis Firefox, encore une autre session,
- une connexion via l’interface web depuis le navigateur Chromium, là aussi, une nouvelle session…
Il est donc possible d’avoir plusieurs sessions connectées en même temps. Cela renforce même la sécurité en permettant une double authentification. Si une session est corrompue, il est possible de le voir via ses autres sessions ouvertes.
Sauvegarde
Comme dit précédemment, dans le cas du chiffrement, Element génère une paire de clé publique et privée (plus exactement, un jeu de clé publique et privée réactualisé en permanence pour chaque salon).
En réalité, il y a un jeu de clés par session. Cela signifie qu’un message est chiffré lors d’une session et donc avec la clé privée de cette session pour ce message. Ce message n’est ni déchiffrable ni lisible par les clés d’une autre session.
Pour permettre la lecture entre ses différentes sessions, il faut donc permettre l’accès aux différentes clés entre les sessions.
Pour cela, Element propose de sauvegarder ses clés lors de sa première connexion ou avant de fermer une session.
Lorsque l’on sauvegarde ses clés, Element déploie un “coffre fort” où les différentes clés sont sauvegardées. Ce coffre est protégé par une phrase de passe ou une clé personnelle unique (en réalité la phrase de passe est utilisée pour générer une clé personnelle unique).
Pour déchiffrer les messages il suffit maintenant d’avoir accès aux clés des autres sessions ce qui est possible en accédant à son coffre fort via sa phrase de passe ou sa clé unique.
Il est également possible d’accéder à la clé de chiffrement d’un message en synchronisant sa session avec la session qui a chiffré le message. Pour cela il faut vérifier les sessions.
Vérification
Pour synchroniser les différentes sessions entre elles, il est possible de vérifier une session avec une autre session. Cette double authentification garantit que la personne derrière la session est bien la bonne personne. Cette vérification est alors notifiée sur les messages via un bouclier vert (voir le tuto pour vérifier ses sessions).
Ainsi Sacha peut vérifier depuis une de ses sessions si ses autres sessions sont corrompues. De même Sacha peut effectuer une vérification depuis sa session sur son ordi avec Alex pour être sûr.e qu’il s’agit d’Alex, et ainsi renforcer la sécurité de l’échange.