Extension du module de chiffrement

Cette nuit, d’importantes modifications ont été apportées aux modules de chiffrement du portail et du serveur de jeu. Cela du fait de limitations rencontrées avec la première version du module. Cet article est l’occasion de revenir sur cette évolution et d’en partager les différents éléments techniques. Commençons par remettre en place le contexte.

Récemment, nous avons implémenté les factions dans le jeu ! Créées depuis le portail, elles comprennent un nom et une description. Lors de la création d’une nouvelle partie, l’administrateur du portail sélectionne les factions participantes, dont les données sont ensuite envoyées de manière chiffrée au serveur de jeu en plus des données de base déjà présentes dans l’appel. Pour la sécurisation des données, un module de chiffrement RSA avait déjà bien souvent été mis à l’épreuve ces dernières semaines. Tout devait être simple lors de l’ajout des données de factions, malheureusement, ce ne le fut pas !

Avec stupeur, nous fîmes la découverte d’une erreur de déchiffrement. Soupçonnant un problème lié à la taille du payload envoyé, le test fut réalisé de mettre des descriptions de faction courtes. La requête dans ce cas était traitée avec succès. La nature de l’obstacle était confirmée, il n’y a plus qu’à trouver une solution !

L’origine du problème est qu’un chiffrement RSA fonctionne avec une longueur maximale dépendant de la taille du modulus. Une contrainte vraisemblablement non contournable de manière propre. Il fallait donc une nouvelle piste. Heureusement, Stack Overflow possède souvent la réponse à nos questions, et ce fut encore le cas ! Notre solution fut donc d’utiliser un chiffrement symétrique pour le payload, à l’aide d’une clé AES générée à la volée, pour ensuite chiffrer la clé AES elle-même à l’aide de RSA. Nous obtenons donc un chiffrement hybride, où le contenu est protégé par une seule clé, elle-même protégée par les deux paires de clés publiques/privées que nous utilisions jusqu’ici.

Côté Symfony, peu de modifications à faire, étant donné que l’extension openssl_* manipule très bien ce genre de cas. Nous générons donc une clé aléatoire sur 32 octets et un IV de 16 octets. Avec ces éléments, nous chiffrons donc le contenu, qui ne subit plus aucune contrainte de taille. La clé et l’IV sont ensuite chiffrés en RSA sur 512 octets. Nous avons désormais les différentes parties de la requête qui sont sécurisées. Il ne reste plus qu’à les transmettre !

En Symfony, rien de très compliqué

Après avoir codé l’extension du module, côté API du serveur de jeu (écrit en Go), les premiers tests sont effectués ! La requête comprend en contenu le payload chiffré avec AES, tandis que la clé et l’IV sont stockés dans deux entêtes HTTP distincts (Application-Key et Application-Iv). Cependant, première surprise, le résultat de la requête est une 400, Bad Request donc.

La raison ne fut pas longue à découvrir, en effet, envoyer des entêtes HTTP chiffrés n’est pas très standard ! Il fallu donc les encoder en base64 et le tour fut joué.

En revanche, seconde surprise, du côté de l’API on notait une erreur de parsing du payload JSON après déchiffrement. Après avoir effectué un relevé des valeurs aux différents stades de déchiffrement, une suite d’octets similaires en fin de chaîne furent découvert. C’est ici que fut rencontré le concept de Padding, inhérent à AES, qui comble une chaîne d’octets pour atteindre une taille égale à un multiple de bloc bien précis. Il fallait donc supprimer ces octets de remplissage pour pouvoir correctement récupérer le JSON final.

Au secours, nous avons créé un monstre

Une fois ceci effectué, il fallut reproduire le même schéma de chiffrement et de déchiffrement dans l’autre sens, c’est à dire de l’API vers le portail. C’est par exemple nécessaire pour récupérer le JSON Web Token du joueur lors de sa connexion, et prochainement pourquoi pas pour des exports de classement ou d’autres données vers le portail.

Le nouveau module de chiffrement enfin opérationnel, nous pouvons désormais assurer une sécurité totale des transferts de données entre une instance du portail et les serveurs de jeu !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *