(J'ai trouvé un fil sur Twitter avec une explication très sympa des chiffres symétriques. Il a été écrit par Colm MacCárthaigh, l'un des principaux contributeurs d'Apache. J'ai demandé à Colm la permission de traduire, il a gentiment accepté).
Je vais vous expliquer en langage clair ce qui se passe lorsque les données sont cryptées. J'espère que sans le mysticisme et les choses complexes qui ont été inventées par les cryptographes.
Ainsi, le cryptage symétrique est exactement ce que nous utilisons dans la plupart des cas lorsque nous voulons crypter un tas de données. Votre navigateur envoie et reçoit des données à l'aide d'un cryptage symétrique. Si vous cryptez des fichiers ou un disque, le cryptage symétrique fonctionne également dans ce cas. iMessage, Signal, WhatsApp - tous utilisent un cryptage symétrique pour la sécurité de votre correspondance.
Si vous pensez que lors du cryptage, les données sont mélangées afin que personne ne puisse les lire sans clé, la façon dont cela se passe réellement.
Voici un exemple simple. Supposons que j'ai une chaîne Ovaltine et que je veuille la crypter. Je pourrais utiliser rot13 - le chiffrement très simple de César, qui fait une danse ronde de lettres où a et z se tiennent par la main, et remplace chaque lettre par une autre lettre de l'alphabet, qui est à 13 caractères de la lettre remplacée. Ainsi, "O" se transforme en "B", et "v" devient "i", par conséquent, "Ovaltine" se transforme en "Binygvar". Bien sûr, ce n'est pas très sûr. Il s'agit d'un exemple naïf, qui est très facile à déchiffrer, car l'attaquant peut trouver quelle lettre est le plus souvent trouvée (généralement dans le texte d'origine, c'est «e») et trouver les lettres restantes de cette manière.
Vous pouvez maintenant imaginer qu'il devrait y avoir des façons plus délicates de «mélanger» les lettres. Par exemple, un schéma complexe dans lequel "a" passe à "p", mais lorsqu'il est rechiffré, à "f". Peut-être même que parfois ce schéma commence à crypter "a" avec deux lettres, par exemple, "jd" ou autre chose. Ainsi, ce schéma compliqué peut chiffrer "Ovaltine" dans la chaîne "FGyswDmweeRq" (notez qu'il est devenu plus long). Des algorithmes de cryptage sont apparus dans le passé et fonctionnaient de la même manière, mais ce n'est pas du tout ainsi que fonctionne le cryptage moderne.
Au lieu de "mélanger" les lettres, le cryptage moderne prend votre chaîne secrète et la combine astucieusement avec des données aléatoires. Ceci est similaire à rot13 uniquement sous deux aspects: le chiffrement et le déchiffrement sont essentiellement la même opération, et tout se passe «en place». En effet, avez-vous remarqué que rot13 est à la fois un algorithme de chiffrement et de déchiffrement? rot13 (Ovaltine) -> Binygvar, rot13 (Binygvar) -> Ovaltine. Je crois que c'est une très belle symétrie dans le cryptage symétrique. Mais revenons à notre sujet. L'astuce est que nous utilisons l'opération XOR au niveau du bit. En cryptographie, logique formelle et code, les programmes XOR peuvent être désignés différemment, mais j'utiliserai une notation que vous connaissez probablement. Cela ressemble à ceci: ^.
XOR signifie "OU exclusif". Il s'agit d'un opérateur (ou d'une fonction, si vous préférez), qui prend deux arguments et renvoie le résultat. A ^ B = C. Cet opérateur est appelé "au niveau du bit" car il s'applique aux bits correspondant les uns aux autres. Si A et B sont des octets, alors nous pouvons supposer que A ^ B = C est essentiellement 8 opérations différentes qui se produisent simultanément. ^ compare le premier bit A et le premier bit B, puis place le résultat dans le premier bit C. Il répète encore 7 fois les mêmes pour les bits restants. Les règles sont simples: si le bit de A est «1» OU le bit de B est «1», alors nous mettons le bit C correspondant à «1», mais seulement si «A» et «B» ne sont pas «1» en même temps. Ceci est la partie exclusive. Voici une table de vérité à l'ancienne:
A|B|C 0|0|0 1|0|1 0|1|1 1|1|0
Le plus cool à propos de XOR est qu'il ressemble à rot13. Nous pouvons l'utiliser pour le chiffrement et le déchiffrement. Je vais le montrer avec un exemple simple. Imaginons que nous voulons chiffrer le nombre habituel "3" et que notre clé de chiffrement soit un autre nombre "7". Ainsi 3 ^ 7 = 4. Autrement dit, le résultat du chiffrement est "4". Décryptons maintenant le nombre. Je ferai juste la même chose encore: 4 ^ 7 = 3. Prenez n'importe quel nombre que vous aimez ou n'importe quelles données, et cela fonctionnera toujours - XOR pourra toujours se décrypter.
Petit à petit - c'est ainsi que nous chiffrons et déchiffrons les données, il n'y a pas de mixage, seulement XOR-ing. La partie difficile est de trouver des données auxquelles nous pouvons appliquer XOR. Une approche consiste à prendre une grande partie des données secrètes à portée de main et à les utiliser comme deuxième argument de XOR. Dans ce cas, tous les participants au processus de transmission de données cryptées doivent utiliser le même ensemble de données secrètes pour le cryptage et le décryptage. Et ça marchera. Certes, il y a plusieurs problèmes.
Le premier problème. Les données secrètes devraient sembler aléatoires. Vous ne pouvez pas prendre le texte d'un livre ou quelque chose comme ça. Tous les modèles apparaîtront dans les données cryptées. C'est précisément ce qui a rendu les forces alliées supérieures pendant la Seconde Guerre mondiale.
Le deuxième problème. Vous ne pouvez pas réutiliser des données sensibles, car les modèles réapparaîtront. Ainsi, vous devez en quelque sorte fournir de gros morceaux de données secrètes à tous ceux qui en ont besoin, comme le bloc à usage unique. C'est trop dur.
Dans le chiffrement moderne, nous «générons» les données secrètes dont nous avons besoin à partir de petites clés. Ces clés sont beaucoup plus faciles à transporter et à protéger. C'est ce que sont réellement les algorithmes de chiffrement symétrique - des schémas pour la génération déterministe de données aléatoires à partir d'une clé. La partie sur le «déterminisme» est très importante: deux personnes avec la même clé doivent générer absolument le même ensemble de données, sinon elles ne pourront pas se comprendre. Vous avez probablement entendu parler de tels algorithmes: AES, 3DES, DES, RC4, ChaCha20. Ils le font tous.
Il s'avère que le problème mathématique de la génération d'un flux de données aléatoire (dans lequel il n'y a aucun modèle sous aucune forme prévisible) à l'aide de la clé est très difficile. De cette liste, seuls AES et ChaCha20 sont considérés comme sûrs aujourd'hui. D'autres algorithmes ont été piratés: les gens ont pu les prédire. De plus, AES a une réputation légèrement ternie, car les cryptographes disent ce qui suit:
AES est l'algorithme de chiffrement principal et le plus analysé. Absolument Gold Standard! : lunettes de soleil foncées:
Mais en même temps, ils ajoutent:
Les implémentations AES dans les logiciels (et non dans le matériel) sont soit dangereuses, soit lentes, et parfois non sûres et lentes. Il n'a pas été conçu en tenant compte du fait qu'il peut être piraté à l'aide de l'analyse du cache. : facepalm:
N'ayez pas trop peur si cela ne vous est pas clair. L'idée principale est la suivante: AES est magnifique du point de vue des mathématiques, mais il est très compliqué dans la mise en œuvre logicielle. Mais ne vous inquiétez pas - nous avons presque toujours un support AES au niveau matériel (une liste de tous les processeurs avec support matériel AES peut être trouvée ici https://en.wikipedia.org/wiki/AES_instruction_set , - note du traducteur).
Quoi qu'il en soit, nous continuons ... Comment ces algorithmes fonctionnent-ils réellement? Comment prendre une clé et générer en toute sécurité un flux de données aléatoire? Je vais simplifier un peu les choses ici et commencer par des blocs.
Ces algorithmes reçoivent trois paramètres en entrée et diffusent le texte chiffré en sortie. Paramètres d'entrée - une clé, du texte crypté et ... surprise - quelque chose d'étrange appelé "vecteur d'initialisation" (vecteur d'initialisation, IV).
AES(key, IV, plaintext) -> encrypted_data.
La clé et IV sont combinés pour créer un ensemble de "conditions de départ" pour l'algorithme; ceci est similaire à l'échange ou au brassage initial des tuiles dans un jeu de Scrabble. La même combinaison de clé et IV créera toujours le même ensemble de conditions de départ. Vous demandez, pourquoi avons-nous même eu besoin de IV alors? Nous avons besoin d'un IV pour pouvoir crypter plusieurs messages en utilisant la même clé. Sans IV, chaque flux de données généré serait le même, ce qui est mauvais. Cela violerait l'une des règles dont nous avons parlé plus tôt: nous ne pouvons pas réutiliser les mêmes données pour le chiffrement. Nous avons donc besoin d'un IV pour mélanger le résultat. Mais contrairement à la clé IV, elle peut être publique.
Ainsi, lorsque vous cryptez un message et l'envoyez à quelqu'un, vous pouvez également ajouter: "Hé, voici le IV que j'ai utilisé." Il est toujours essentiel de ne pas réutiliser la combinaison de clé et IV, car ils nous donneraient des données aléatoires répétées. Il existe deux façons de réaliser cette condition: 1) IV est une sorte de compteur que nous augmentons à chaque nouveau message. 2) IV est généré de manière aléatoire, alors qu'il a une valeur assez élevée, nous n'avons donc pas à nous soucier beaucoup des collisions. Quoi qu'il en soit, j'ai mentionné que je parlerai des blocs.
Les clés et IV sont «mélangées» ou combinées de manière à créer un ensemble de conditions de démarrage ... ces conditions sont en fait le «bloc» initial de données aléatoires. La longueur de ce bloc est de 128 bits pour AES128, 256 bits pour AES256 et 512 bits pour ChaCha20. Et ici, la vraie magie et l'individualité d'un algorithme de cryptage particulier se manifestent. En fait, leur essence réside dans la façon dont la séquence de blocs est générée et comment chaque bloc est associé à ses voisins. La relation entre ces blocs reste prévisible même pour ceux qui n'ont pas de clé.
Je ne vais pas approfondir le fonctionnement de ces algorithmes, mais si vous voulez en savoir plus, je vous conseille de commencer à explorer ce sujet avec les générateurs linéaires congruentiels (LCG). LCG est une fonction qui crée des blocs de données "circulaires" de manière aléatoire et non répétitive. Jetez ensuite un œil aux réseaux Feistel, le prochain niveau de développement de LCG. Ensuite, traitez avec les S-Box, puis regardez comment la Salsa20 crée l'entrelacement dans l'algorithme ChaCha20. Tout cela est beaucoup plus abordable que vous ne le pensez!
Donc, nous savons maintenant comment un flux de données aléatoire peut être combiné avec du texte pour le crypter et le décrypter, et nous sommes déjà un peu dans le sujet de la façon dont ces flux de données aléatoires sont créés. N'est-ce pas tout ce dont nous avons besoin? Pour le chiffrement de disque, c'est vraiment presque tout. Nous pouvons chiffrer chaque bloc ou secteur du stockage en utilisant une clé et IV, qui peuvent être obtenus à partir de la "position" sur le disque. Ainsi, nous pouvons toujours décrypter n'importe quel bloc de données n'importe où sur le disque, tant que nous avons la clé. Mais il y a un problème ... quelqu'un peut ruiner nos données cryptées. Si je change la valeur d'un octet, même si je n'ai pas de clé, nous ne pourrons finalement pas décrypter le bloc. Et il n'y a aucune protection contre ce genre d'ingérence. Dans le cas de l'envoi de messages et de données sur le réseau, cela devient encore plus critique. Nous ne voulons pas que quiconque gâche nos données transmises. Nous devons donc ajouter un contrôle d'intégrité! Il existe plusieurs schémas pour ce faire.
HMAC, GCM et Poly1305 sont les schémas de vérification d'intégrité modernes les plus courants. Ces algorithmes fonctionnent essentiellement comme ceci: ils sont fournis avec des données et une autre clé (la clé dite d'intégrité). Après les calculs, ils donnent le MAC (code d'authentification de message) ou la balise, qui à son tour n'est qu'une autre donnée qui agit comme une signature.
Ainsi, pour le chiffrement et la protection, notre schéma peut ressembler à ceci:
AES(key, IV, "Ovaltine") -> encrypted_output HMAC(key, encrypted_output) -> MAC
puis par fil nous envoyons:
IV | encrypted_output | MAC
Pour le décryptage, nous vérifions le MAC, le générons à nouveau et comparons le résultat avec le MAC reçu, puis décryptons les données. Il existe des différences internes dans la façon dont HMAC, GCM et Poly1305 génèrent ces signatures, mais vous n'avez pas à vous en soucier. À ce jour, cette combinaison d'opérations est généralement enveloppée dans une fonction appelée "AEAD" (Authenticated Encryption with Additional Data). Sous le capot, elle fait tout ce dont j'ai parlé plus tôt:
AEAD(key, IV, plaintext, additional_data) -> IV_encrypted_data_MAC
Un morceau appelé "additional_data" n'est que des données avec lesquelles vous pouvez vous assurer que l'expéditeur a ces données, bien qu'elles ne leur aient pas été envoyées. C'est comme des métadonnées qui définissent les droits d'accès. Souvent, ce champ est laissé vide.
Néanmoins, vous pouvez avoir des problèmes avec AEAD si vous utilisez le même IV. C'est mauvais! Il y a des tentatives pour améliorer cette situation: mon collègue, dont le nom est Shay, travaille sur un schéma SIV sympa qui ajoute une couche de protection contre ce problème. Mais si vous utilisez un IV unique, le cryptage moderne est très sécurisé. Autrement dit, vous pouvez publier le texte chiffré dans le New York Times, et personne ne peut le déchiffrer. Le chiffre restera inaccessible même si "une" partie du texte est connue. Par exemple, dans les protocoles Internet, une grande quantité de texte est connue. Les serveurs HTTP répondent toujours de la même manière et les premiers octets sont toujours connus. Mais ce fait n'a pas d'importance du tout - cela n'aidera pas l'attaquant à trouver un seul morceau des données restantes ... Nous avons parcouru un long chemin depuis la Seconde Guerre mondiale.
Mais il y a des attaques qui fonctionnent! Si vous envoyez des données sur un réseau et que quelqu'un suit l'heure et la taille des messages, les données cryptées peuvent être piratées à l'aide de l'analyse du trafic.

Voyons d'abord la longueur. De toute évidence, la longueur n'est pas une caractéristique cachée. Et cela est normal si vous essayez de protéger votre mot de passe ou votre numéro de carte de crédit quelque part au milieu du message. Pas un gros problème. Mais cela signifie que n'importe qui peut déterminer le type de contenu que vous soumettez. Un exemple simple: si vous envoyez un gif en utilisant un messager et si la taille de cette image est unique, l'attaquant interceptant vos données peut suggérer quel GIF vient d'être envoyé. Il existe des versions plus délicates de cette attaque pour Google Maps, Netflix, Wikipedia, etc. Pour vous protéger contre cette attaque, vous pouvez "terminer" les messages envoyés avec des octets supplémentaires, de sorte que tous les messages envoyés soient de la même longueur quoi qu'il arrive. Le chiffrement utilisé dans les réseaux militaires «termine» toujours le trafic avec des données supplémentaires, c'est-à-dire que pour l'intercepteur, il a toujours la même apparence! Un autre problème associé à la longueur est que si vous utilisez la compression et donnez à l'attaquant la possibilité de modifier n'importe quelle partie du contenu de la page que l'utilisateur voit, cela permet à l'attaquant de découvrir même les plus petits secrets. Recherchez une attaque appelée CRIME. Elle est magnifique et effrayante.
J'ai également dit que l'autre problème est le timing. Évidemment, l'heure d'envoi de chaque message est une information ouverte. Serait-ce un problème? Peut-être! Par exemple, si vous envoyez un message chaque fois que vous appuyez sur une touche, il est trivial de savoir ce qui est imprimé exactement à l'aide de l'analyse du temps. Cool! Un autre exemple est VOIP. Si votre application d'appel envoie des données uniquement lorsque les gens parlent, mais pas pendant le silence, cela suffit pour restaurer 70% de la parole en anglais. Juste hors du silence. Cool effrayant.
Ces exemples ne sont que la pointe de l'iceberg. Même lorsque vous utilisez des algorithmes et des schémas de chiffrement qui s'améliorent depuis 80 ans, il existe encore des lacunes qui peuvent être utilisées pour casser la sécurité. C'est pourquoi il est important de le savoir!
Quoi qu'il en soit, c'est le niveau d'explication sur lequel je veux m'attarder maintenant, mais nous avons considéré les choses les plus nécessaires à savoir. Si vous lisez jusqu'à ce point - merci! Vous devriez maintenant mieux comprendre ce qui se passe pendant le chiffrement et ce à quoi vous devez faire attention.
N'hésitez pas à poser des questions.
La traduction est publiée sous licence CC BY-NC-SA 4.0