Couches 5 & 6 : Cryptographie et TLS.

Cryptographie : motivations & besoins

Nous pouvons désormais envoyer un message de l'expéditeur au service destinataire. Cependant, les donnés échangées peuvent être sensibles, et ainsi nécessiter une protection. Imaginez par exemple qu'un intermédiaire malhonnête soit entre vous et un service bancaire. Il pourrait alors :
Nous souhaitons donc que nos canaux de communications garantissent les propriétés de sécurité suivantes :
💡 L'intégrité est souvent présentée comme l'impossibilité de modifier le message. Ce n'est pas exact dans le sens où on ne peut pas empêcher l'altération des bits qui circulent.
Pour cela on utilise le protocole cryptographique TLS (couches 5 & 6) afin de sécuriser les canaux de communications. On distingue :
Les protocoles cryptographiques sont construits autours de briques cryptographiques permettant de garantir différentes propriétés répondant à des besoins spécifiques. Ces briques sont usuellement basées sur des problèmes mathématiques :
Les protocoles cryptographiques apportent des preuves de sécurité face à différents modèles d'attaquants. Un attaquant est une personne qui va tenter de compromettre la sécurité du système et pour lequel on va faire différentes hypothèses quant à ses capacités. On peut alors établir des preuves formelles de sécurité pour le modèle d'attaque étudié. Une brique cryptographique peut ainsi tomber si le problème mathématique à sa base devient facile.
On distingue généralement 2 niveaux de sécurité d'un protocole (ou d'une brique) :
La sécurité ad hoc désigne un système dont la sécurité dépend d'une série de raisonnements sans preuve réelle de sécurité. Il est donc difficile d'avoir confiance en la sécurité d'un tel système. Le raisonnement peut être juste, mais peut négliger des hypothèses ou des cas d'attaques possibles. Par exemple, le cas d'un attaquant envoyant des messages ne respectant pas le protocole.
La sécurité par l'obscurité désigne un système dont la sécurité dépend du secret de son fonctionnement. Un tel système est considéré comme étant très peu sûr : le fonctionnement du système peut fuiter, être retrouvé par reverse engineering, etc.
Les systèmes de sécurité peuvent dépendre d'un secret, appelé clef. En cas de clef compromise, il suffit alors de changer la clef. Le système cryptographique en lui-même n'est alors pas compromis. Idéalement, on vise aussi le backward secrecy et le forward secrecy, i.e. la compromission du système à un instant t ne compromet ni les échanges précédents, ni les échanges futurs.
💡 Les briques cryptographiques peuvent aussi être utilisées pour divers usages, e.g. :

Hachage

Une fonction de hashage est une fonction transformant des données en une empreinte de taille inférieure et fixe. Permettant ensuite plusieurs usages, e.g. :
Lorsque deux données différentes produisent le même hash, on parle alors de collision. L'objectif est bien évidemment d'éviter les collisions. Par exemple, le SHA-512 est un hash sur 512 bits (64 octets), avec une probabilité de collision de 2-512, ce qui est considéré improbable.
De même, on souhaite prendre en entrée des données de tailles arbitraires. Pour cela on va utiliser des fonctions éponges. Pour faire simple, elle va absorber des données puis les essorer afin qu'ils rentrent dans son état interne de taille fixe. On peut alors extraire des données de taille fixe en sortie.
Les hash cryptographiques sont des hash résistants à diverses attaques et grantissant certaines propriétés :
La non-inversibilité implique que la sortie ne doit pas permettre de déduire d'informations sur l'entrée, i.e. une absence de corrélations. Notamment, des données similaires doivent produire des hashs dissimilaires. En effet, dans le cas contraire, la fonction de hachage serait vulnérable au hill climbing attack : on part d'une donnée qu'on modifie progressivement pour que son hash se rapproche du hash qu'on souhaite inverser. En effet, dans ce cas, des hashs similaires correspondant à des données similaires, la modification effectuée nous rapproche donc des données originelles.

Mots de passes hashés

Les hashs cryptographiques sont notamment utilisés pour stocker des mots de passes, sans qu'ils soient compromis par une fuite de la base de donnée. Cependant, les mots de passes sont généralement courts, pas vraiment aléatoires, réutilisés entre plusieurs comptes, etc. rendant l'inversion de leur hash plus facile. Le craquage de mot de passe consiste alors souvent à tester des mots de passes possibles (appelés candidats), et d'en comparer le hash.
Une première attaque est donc une attaque par force brute, i.e. de tester toutes les possibilités (avec potentiellement quelques heuristiques issues de l'étude du comportement humain). Par exemple, si le mot de passe est une date de naissance, on aura ~36 500 possibilités à tester. Sachant qu'un ASIC spécialisé dans le minage de cryptomonnaie est capable de tester plusieurs trilliards de hash par seconde (1012/s). La sécurité d'un mot de passe dépend donc du temps nécessaire à le craquer. Par exemple un mot de passe de 12 caractères alphanumériques, représente 8x1066 possibilités, sera donc cassé en ~6x1048 années.
Les mots de passes étaient usuellement courts, on va aussi tenter de réduire le nombre de hashs calculable à la seconde, en augmentant les ressources nécessaires à son calcul (e.g. temps, mémoire). Pour cela on utilise des algorithmes de hachage dédié au stockage de mot de passe, comme bcrypt qui intègre une notion de tours (round), i.e. au lieu de ne hasher le mot de passe qu'une seule fois, on le hash plusieurs fois afin d'en augmenter le coût.
Un attaquant ne cherche aussi généralement pas à attaquer un mot de passe, mais un ensemble de mot de passes. Si on peut comparer les mots de passes entre eux à l'aide de leur hash, le système a alors 2 vulnérabilités :
Pour s'en protéger, avant de hasher le mot de passe, on peut lui ajouter un sel, i.e. un aléa connu et unique à chaque entrée. Ainsi les hash ne sont plus comparables entre eux, et un attaquant doit calculer des hashs pour chaque entrées.
Il est cependant toujours possible d'effectuer une attaque par dictionnaire, i.e. de tester des mots de passes déjà connus, venant par exemple de bases déjà craquées. Pour s'en protéger, on peut aussi ajouter un poivre au mot de passe avant de le hasher. Contrairement au sel, qui est stocké avec hash, le poivre est un secret partagé avec toutes les entrées, mais qui n'est pas stocké dans la base de données.

Autres usages

Les MAC

Les MAC (à ne pas confondre avec les adresses MAC), sont une sorte de hash avec clef secrète. Comme on ne peut calculer le MAC qu'en ayant connaissance de la clef secrètes, ils sont ainsi utlilisés dans les protocoles réseaux pour garantir non seulement l'intégrité, mais aussi l'authenticité des messages.
💡 Les HMAC sont est un MAC basé sur une fonction de hachage, quand CBC-MAC est basé sur une fonction de chiffrement. Pour faire simple HMAC revient à concaténer la clef avec la donnée, avant de hasher le tout.

Les générateurs

Une fonction de hachage peut être utilisée comme d'un générateur de nombre pseudo-aléatoire. Cela est notamment utilisé dans la dérivation de clefs, i.e. générer des secrets à partir d'un secret maître.

Preuve de connaissances

Un hash peut être utilisé dans le cadre de protocoles de preuve de connaissances (e.g. authentifications). En effet, être capable de calculer un hash est la preuve qu'on a soit connaissance du hash, soit de la donnée à l'origine du hash.

Chiffrement symétrique

Le chiffrement symétrique consiste à transformer les données à l'aide d'un secret, de sorte à ce que l'inversion ne soit possible qu'à l'aide de ce même secret. On utilise alors le vocabulaire suivant :
Les algorithmes de chiffrements sont usuellement basés sur un chiffrement de Vernam (aussi appelé one-time pad), consistant à effectuer un xor des données avec la clef secrète. Sans la connaissance du secret, il est alors mathématiquement impossible de retrouver les données originelles à partir du chiffré. Même avec une puissance de calcul infini, le chiffré ne dévoile aucune information sur les données originelles. On parle alors de chiffrement parfait.
Par exemple un chiffré de 2 bits peut correspondre à : Tous les textes clairs sont ainsi possibles et équiprobables, dépendant entièrement de la clef secrète. Le chiffré ne dévoile ainsi aucune information.
Cependant ce chiffrement a deux limitations : Or, si on peut échanger une clef de la taille des données via un canal sécurisé... autant y envoyer les données directement...
Deux stratégies sont alors employées :
Utilisé seul, le chiffrement par bloc est grandement vulnérable à diverses attaques. Par exemple, si un même bloc de donnée produit le même bloc chiffré, des attaques par analyse de fréquence, par rejeux, etc. deviennent alors possibles. Les chiffrements par blocs sont ainsi généralement utilisé avec un mode opératoire (e.g. AES-XTS) permettant de pallier à ces vulnérabilités. Certains modes opératoires transforment un chiffrement par blocs en chiffrement par flot (e.g. AES-CTR).
Le chiffrement par flot a lui aussi ses vulnérabilités, liées au générateur pseudo-aléatoire :
On distingue alors généralement 4 types de modèle d'attaquant :
💡 Une clef symétrique peut être générée à partir du hash d'un mot de passe. C'est par exemple ce qui est utilisé pour les disques/fichiers chiffrés par mot de passe (e.g. mot de passe maître d'un gestionnaire de mot de passe). Pour permettre le changement du mot de passe sans avoir à re-chiffrer tout le disque/fichier, le mot de passe sert usuellement à déchiffrer la clef symétrique (stockée chiffrée) permettant à son tour de (dé)chiffrer le disque/fichier. Ainsi le changement du mot de passe nécessite juste de re-chiffrer la clef.

Cryptographie asymétrique.

Contrairement à la cryptographie symétrique où un unique secret est partagé entre l'expéditeur et le destinataire, la cryptographie asymétrique possède 2 clefs :
On distingue alors le chiffrement de la signature : Ainsi, le chiffrement asymétrique garantie le destinataire (confidentialité), le seul à pouvoir déchiffrer, quand la signature asymétrique garantie l'expéditeur (authenticité), le seul à pouvoir chiffrer. Ce sont des fonctions avec trappe, i.e. difficile à inverser sauf en connaissance d'un secret supplémentaire.
💡 Les fonctions avec trappe sont notamment utilisée afin de permettre aux autorités compétentes de lever la confidentialité e.g. de données stockées. Que ce soit pour des raisons d'enquêtes/investigations, d'espionage, ou pour déchiffrer des données lorsque leur propriétaire ne peut le faire (e.g. perte du mot de passe, comas -dans les deux cas, c'est une perte de connaissance 🤡-).
La cryptographie asymétrique est relativement coûteuse. Ainsi la signature d'un fichier sera généralement une signature de son hash. De même, le chiffrement d'un fichier sera généralement le chiffrement d'une clef symétrique permettant de le chiffrer/déchiffrer.
Par exemple, le handshake TLS utilise la cryptographie asymétrique afin de garantir le destinataire (et/ou l'expéditeur) et d'échanger une clef qui servira au MAC ainsi qu'au chiffrement symétrique. C'est aussi à ce moment là que le client et le serveur négocient des paramètres de sécurités.
💡 Une attaque consiste alors à tenter de dégrader les paramètres de sécurité afin de faciliter les attaques.
L'échange de clef est aussi de la cryptographie asymétrique. Une manière de le faire est de simplement chiffrer une clef symétrique et de la transmettre au serveur. En pratique, on utilise un algorithme d'échange de clef : Diffie-Hellman (DH), le secret est en pratique calculé à partir d'un nombre aléatoire choisi par le client, et un nombre aléatoire choisi par le serveur. DH se base sur le problème du logarithme discret ( gx mod p, g et p connus, difficile de retrouver x ):
  1. 2 nombres publiques: p (nombre premier) et g ("générateur").
  2. Le client et le serveur choisissent un secret, respectivement a et b.
  3. Le client envoie ga mod p, le serveur envoie gb mod p (difficile à inverser).
  4. Le client calcule (gb)a mod p, le serveur calcule (ga)b mod p.
  5. Ils partagent alors le même secret : gab mod p
RSA est basé sur le problème de la factorisation d'entiers. Cependant, les ordinateurs quantiques rendent ce problème plus difficile. Heureusement, il faut intriquer ~2N qbits pour casser une clef RSA de N bits (algorithme de Shor). Les ordinateurs quantiques ayant du mal à intriquer de nombreux qbits (record à ~50qbit actuellement ?), il suffit pour le moment d'augmenter les tailles des clefs RSA.
Pour DSA et DH, on utilise actuellement le problème des logarithmes discrets sur des courbes elliptiques (ECC). On parle alors de ECDH, et ECDSA, permettant d'avoir le même niveau de sécurité avec des tailles de clefs plus petites. Cependant, ce système aussi sera cassé par des ordinateurs quantiques assez puissants.
Plusieurs propositions d'algorithmes post-quantiques existent, mais sont actuellement peu déployés. Il est en effet peu utile de remplacer les algorithmes existants, qui ont passé l'épreuve du temps, alors même qu'il n'est pas sûr que la création d'ordinateur quantiques assez puissant soit possible. En effet, intriquer des qbits et les garder intriqué est très compliqué. Les ordinateurs quantiques ne sont d'ailleurs pas récent, le premier datant de 1998 (IBM).

Autres usages de la cryptographie

Le chiffrement homomorphe permet d'effectuer des opérations dans l'espace des chiffrés. Il est ainsi utilisé pour faire effectuer des calculs par un tiers, sans lui divulger les données ou le résultat.
Le chiffrement fonctionnel, permet de "chiffrer" une fonction. On lui passe des données chiffrées et il nous donne le résultat en clair. Utilisé pour qu'un tiers puisse faire des calculs et en connaître le résultats.
Calculs multi-parti sécurisé, plusieurs entités ont des données sur lesquelles ils veulent faire un calcul en n'en révélant que le résultat (e.g. votes).
Cryptosystème à seuil, au moins N personnes sont requises pour chiffrer (ou déchiffrer).
Harvest now decrypt later