Bonnes pratiques en matière de sécurité : Chiffrement symétrique avec AES en Java et Android

Patrick Favre-Bulle
6 janv, 2018 – 11 min lu

Dans cet article, je vous mettrai au courant de l’Advanced Encryption Standard (AES), des modes de bloc courants, de la raison pour laquelle vous avez besoin de vecteurs de remplissage et d’initialisation et de la façon de protéger vos données contre la modification. Enfin, je vous montrerai comment mettre facilement cela en œuvre avec Java en évitant la plupart des problèmes de sécurité.

.

Ce que tout ingénieur logiciel devrait savoir sur AES

AES, également connu sous son nom d’origine Rijndael, a été choisi par le NIST en 2000 pour trouver un successeur à la norme de chiffrement des données (DES), qui était déjà dépassée. AES est un chiffrement par blocs, c’est-à-dire que le chiffrement se fait sur des groupes de bits de longueur fixe. Dans notre cas, l’algorithme définit des blocs de 128 bits. AES supporte des longueurs de clé de 128, 192 et 256 bits.

Chaque bloc passe par de nombreux cycles de transformation. Je vais omettre les détails de l’algorithme ici, mais le lecteur intéressé est renvoyé à l’article de Wikipedia sur AES. L’important est que la longueur de la clé n’affecte pas la taille du bloc mais le nombre de répétitions des cycles de transformation (une clé de 128 bits correspond à 10 cycles, celle de 256 bits à 14)

Jusqu’en mai 2009, les seules attaques publiées réussies contre l’AES complet étaient des attaques par canal latéral sur certaines implémentations spécifiques. (Source)

Vous voulez chiffrer plus d’un bloc?

Si AES ne chiffrera que 128 bits de données, mais si nous voulons chiffrer des messages entiers, nous devons choisir un mode bloc avec lequel plusieurs blocs peuvent être chiffrés en un seul texte chiffré. Le mode bloc le plus simple est le livre de code électronique ou ECB. Il utilise la même clé non altérée sur chaque bloc comme ceci :

Image de . Wikpedia

C’est particulièrement mauvais puisque des blocs de texte en clair identiques sont chiffrés en blocs de texte chiffré identiques.

L’image chiffrée avec le mode bloc de l’ECB. Le mode bloc révèle les motifs de l’original (essayez vous-même)

N’oubliez pas de ne jamais choisir ce mode, sauf si vous ne chiffrez que des données inférieures à 128 bits. Malheureusement, il est encore souvent mal utilisé car il ne nécessite pas de fournir un vecteur initial (nous y reviendrons) et semble donc plus facile à gérer pour un développeur.

Un cas doit cependant être géré avec les modes bloc : que se passe-t-il si le dernier bloc n’est pas exactement de 128 bits ? C’est là que le padding entre en jeu, c’est-à-dire le remplissage des bits manquants du bloc. La méthode la plus simple consiste à remplir les bits manquants avec des zéros. Il n’y a pratiquement aucune implication de sécurité dans le choix du padding dans AES.

Cipher Block Chaining (CBC)

Alors quelles sont les alternatives au CBC ? Il y a tout d’abord le CBC, qui effectue un XOR du bloc de texte en clair actuel avec le bloc de texte chiffré précédent. De cette façon, chaque bloc de texte chiffré dépend de tous les blocs de texte en clair traités jusqu’à ce point. En utilisant la même image que précédemment, le résultat serait un bruit impossible à distinguer de données aléatoires :

.

L’image chiffrée avec le mode bloc CBC semble aléatoire

Alors qu’en est-il du premier bloc ? Le moyen le plus simple est d’utiliser un bloc rempli de zéros, par exemple, mais alors chaque cryptage avec la même clé et le même texte en clair donnerait le même texte chiffré. De plus, si vous réutilisez la même clé pour différents textes en clair, il sera plus facile de récupérer la clé. Une meilleure solution consiste à utiliser un vecteur d’initialisation aléatoire (IV). Il s’agit d’un terme sophistiqué pour désigner des données aléatoires de la taille d’un bloc (128 bits). Considérez-le comme le sel du cryptage, c’est-à-dire qu’un IV peut être public, doit être aléatoire et n’être utilisé qu’une seule fois. Gardez à l’esprit, cependant, que ne pas connaître l’IV ne fera qu’entraver le décryptage du premier bloc puisque le CBC XORs le texte chiffré et non le texte en clair du précédent.

Lors de la transmission ou de la persistance des données, il est courant de simplement ajouter l’IV au message chiffré réel. Si vous êtes intéressé sur la façon d’utiliser correctement AES-CBC consultez la partie 2 de cette série.

Mode compteur (CTR)

Une autre option est d’utiliser le mode CTR. Ce mode bloc est intéressant car il transforme un chiffrement par bloc en un chiffrement par flux, ce qui signifie qu’aucun rembourrage n’est nécessaire. Dans sa forme de base, tous les blocs sont numérotés de 0 à n. Chaque bloc sera maintenant chiffré avec la clé, le IV (également appelé nonce ici) et la valeur du compteur.

.

Image de Wikpedia

L’avantage est , contrairement au CBC, le cryptage peut être effectué en parallèle et tous les blocs dépendent de l’IV, pas seulement le premier. Une grosse mise en garde est, qu’un IV ne doit jamais être réutilisé avec la même clé car un attaquant peut trivialement calculer la clé utilisée à partir de cela.

Puis-je être sûr que personne n’a modifié mon message ?

La dure vérité : le cryptage ne protège pas automatiquement contre la modification des données. Il s’agit en fait d’une attaque assez courante. Lisez ici une discussion plus approfondie sur cette question.

Alors que pouvons-nous faire ? Nous ajoutons simplement un code d’authentification de message (MAC) au message crypté. Un MAC est similaire à une signature numérique, à la différence que la clé de vérification et la clé d’authentification sont pratiquement les mêmes. Il existe différentes variantes de cette méthode, le mode qui est recommandé par la plupart des chercheurs est appelé Encrypt-then-Mac. C’est-à-dire qu’après le cryptage, un MAC est calculé sur le texte chiffré et ajouté. Vous utiliserez généralement le code d’authentification de message basé sur le hachage (HMAC) comme type de MAC.

Alors, maintenant, ça commence à se compliquer. Pour l’intégrité/authenticité, nous devons choisir un algorithme MAC, choisir un mode de balise de chiffrement, calculer le mac et l’annexer. Cela est également lent puisque l’ensemble du message doit être traité deux fois. Le côté opposé doit faire de même mais pour le décryptage et la vérification.

Cryptage authentifié avec GCM

Ce ne serait pas génial s’il y avait des modes qui gèrent tous les trucs d’authentification pour vous ? Heureusement, il existe une chose appelée cryptage authentifié qui fournit simultanément des assurances de confidentialité, d’intégrité et d’authenticité sur les données. L’un des modes de bloc les plus populaires qui supporte cela est appelé Galois/Counter Mode ou GCM pour faire court (il est par exemple également disponible en tant que suite de chiffrement dans TLS v1.2)

GCM est fondamentalement un mode CTR qui calcule également une balise d’authentification de manière séquentielle pendant le chiffrement. Cette balise d’authentification est ensuite généralement annexée au texte chiffré. Sa taille est une propriété de sécurité importante, elle doit donc avoir une longueur d’au moins 128 bits.

Il est également possible d’authentifier des informations supplémentaires non incluses dans le texte en clair. Ces données sont appelées données associées. Pourquoi sont-elles utiles ? Par exemple, les données cryptées ont une méta-propriété, la date de création, qui est utilisée pour vérifier si le contenu doit être re-crypté. Un attaquant pourrait maintenant modifier trivialement la date de création, mais si elle est ajoutée en tant que donnée associée, GCM vérifiera également cet élément d’information et reconnaîtra le changement.

Une discussion animée : Quelle taille de clé utiliser ?

L’intuition dit : plus c’est gros, mieux c’est – il est évident qu’il est plus difficile de forcer brutalement une valeur aléatoire de 256 bits qu’une de 128 bits. Avec nos connaissances actuelles, le forçage brutal de toutes les valeurs d’un mot de 128 bits nécessiterait une quantité astronomique d’énergie, ce qui n’est pas réaliste pour quiconque à une époque raisonnable (je vous regarde, NSA). Donc la décision est fondamentalement entre l’infini et l’infini fois 2¹²⁸.

AES a en fait trois tailles de clés distinctes parce qu’il a été choisi comme un algorithme fédéral américain apte à être utilisé dans divers domaines sous le contrôle du gouvernement fédéral américain . (…) Les fins cerveaux militaires ont donc eu l’idée qu’il devait y avoir trois « niveaux de sécurité », afin que les secrets les plus importants soient cryptés avec les méthodes lourdes qu’ils méritent, mais que les données de moindre valeur tactique puissent être cryptées avec des algorithmes plus pratiques, bien que plus faibles. (…) Le NIST a donc décidé de suivre formellement la réglementation (demander trois tailles de clés) mais aussi de faire le plus intelligent (le niveau le plus bas devait être incassable avec une technologie prévisible)(Source)

L’argument est le suivant : un message chiffré en AES ne sera probablement pas cassé par brute forcing de la clé, mais par d’autres attaques moins coûteuses (non connues actuellement). Ces attaques seront aussi néfastes au mode de clé de 128 bits qu’au mode de 256 bits, donc choisir une taille de clé plus grande ne sert à rien dans ce cas.

Donc, fondamentalement, une clé de 128 bits est une sécurité suffisante pour la plupart des cas d’utilisation, à l’exception de la protection par ordinateur quantique. De plus, l’utilisation d’une clé de 128 bits permet de chiffrer plus rapidement qu’une clé de 256 bits et le schéma de clés pour les clés de 128 bits semble être mieux protégé contre les attaques par clé connexe (cependant, cela n’est pas pertinent pour la plupart des utilisations dans le monde réel).

En guise de note latérale : les attaques par canal secondaire

Les attaques par canal secondaire sont des attaques qui visent à exploiter des problèmes spécifiques à certaines implémentations. Les schémas de chiffrement eux-mêmes ne peuvent pas être intrinsèquement protégés contre elles. Les implémentations AES simples peuvent être sujettes à des attaques de synchronisation et de cache, entre autres.

A titre d’exemple très basique : un algorithme simple qui est sujet à des attaques de synchronisation est une méthode equals() qui compare deux tableaux d’octets secrets. Si la equals() a un retour rapide, c’est-à-dire qu’après la première paire d’octets qui ne correspondent pas, elle termine la boucle, un attaquant peut mesurer le temps que met la equals() à se terminer et peut deviner octet par octet jusqu’à ce que tous correspondent.

Laisser un commentaire

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