Académique Documents
Professionnel Documents
Culture Documents
DUVERGER Kévin
25 janvier 2024
1 Introduction : 2
1.1 Généralités sur le cours : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Un historique de la cryptographie : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 LFSR : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4 Chiffrements par blocs : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.5 Fonctions de hachage : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.6 Chiffrement à clé publique : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3 TD 1 - Attaques algébriques : 9
3.1 LFSR et attaques algébriques : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Un exemple sur un LFSR simple : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 Exemple d’attaque sur un registre filtré : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.4 Généralisation de l’attaque : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.5 Rendre l’inversion de matrice plus rapide : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.6 Le concept d’immunité algébrique : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.7 Application de ce concept à l’attaque algébrique sur le LFSR : . . . . . . . . . . . . . . . . . . . . . . 16
3.8 Attaque sur TOYOCRYPT : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4 Authentification : 17
4.1 Quelques propriétés des blocs de base en cryptographie asymétrique : . . . . . . . . . . . . . . . . . . . 17
4.2 Authentification symétrique : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.3 Authentification asymétrique : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.4 Un exemple sur le schéma d’authentification Fiat-Shamir (1986) : . . . . . . . . . . . . . . . . . . . . . 18
1
DUVERGER Kévin Révisions - Mécanismes cryptographiques Université de Limoges
5 Magic crypto : 20
5.1 Définition du problème et une première solution : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.2 Rappels sur la notion de résidu quadratique et carrés : . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.3 Un exemple : le chiffrement de Rabin : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.4 Le protocole d’Ostrovsky : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.5 Analyse de la complexité du protocole précédent : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.6 Chiffrement homomorphe : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6 Protocoles Zero-Knowledge : 23
6.1 Exercice 18 page 40 : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.2 Création d’algorithmes de signature : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
7 Courbes elliptiques : 25
7.1 Introduction : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.2 Définition de l’addition : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.3 Courbes elliptiques sur des entiers : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
7.4 Trouvons les points de quelques courbes : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.5 Quelques exemples d’additions : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
11.10.2 GGH : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
11.10.3 NTRU : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
12 L’interpolation lagrangienne : 63
12.1 Le but : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
12.2 Cas particuliers : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
12.3 Une base de polynômes : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
12.4 Quelques exemples : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
17.3.1 Sujet : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
17.3.2 Réponses : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
17.4 Exercice 3 - Courbes elliptiques : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
17.4.1 Sujet : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
17.4.2 Réponses : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
17.5 Exercice 4 : Fonction de hachage et signature : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
17.5.1 Sujet : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
17.5.2 Réponses : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
17.6 Exercice 5 : Un échange de clé léger, trop léger : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
17.6.1 Sujet : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
17.6.2 Réponses : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
17.7 Exercice 6 : authentification : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
17.7.1 Sujet : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
17.7.2 Correction : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
17.8 Exercice 7 : Chiffrement : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
17.8.1 Sujet : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
17.8.2 Réponses : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
1 Introduction :
1.1 Généralités sur le cours :
Il y aura un partiel vers fin novembre et un examen au début du mois de dévrier et également une note de projet (ce
dernier se faisant à au moins 2 personnes). Le projet se présentera sous une forme de liste de sujets : chaque sujets
donnera lieu à 1 / 2 papiers de recherche à lire et finalement une présentation sur ces derniers pour montrer que l’on
a compris, cette présentation se ferait dans le courant du mois de janvier.
Les CM du mercredi démarreront à 15 heures 30 pile et le second TD de la journée se finira au plus tard à 18 heures
30. Le cours sera mis sur internet (et apparemment c’est le même que l’année dernière ou sinon on peut le choper sur
discord), et pour le reste il n’y aura que des supports écrits.
1.3 LFSR :
La difficulté derrière le chiffrement de Vernam repose sur l’aléatoire de la clé : pour avoir ce flot de clé indistinguable
de l’aléatoire, la notion de LFSR a été créée. Un LFSR est tout simplement défini par un certain nombre de bits,
appellons ce dernier k, une seed et la chaine qui sera générée après (appelés si ) et pour finir un ensemble de connexions
Pk
que nous appellerons ai . La relation sur lequel ce LFSR va se baser sera si+1 = j=1 aj × si+1−j . Le polynôme de
rétroaction sera tout simplement définit par 1 + a1 × x + ... + ak × xk .
Ces derniers datent des années 1960 et ont beaucoup d’avantages : une très bonne propriété statistique, rapides et
”pas chers”. Notez qu’ils permettent de créer des suites de au plus 2k − 1 éléments (toutes les suites binaires de k bits
sauf 0).
Les attaques linéaires peuvent permettre de tout retrouver avec une attaque à clair connu, c’est pourquoi des variations
ont été nécessaires : les registres combinés, ... : nous les verrons dans la suite.
Les schémas utilisés à la base étaient : MD4 (128 bits, Message Direct 4) puis MD5 (128 bits aussi) ont été créées par
Rivest. Sur ces dernières, nous pouvons toujours faire une attaque par paradoxe des anniversaires qui donnera lieu à
une racine carrée : pour avoir une sécurité de 64 bits il faut 128 bits de haché.
En 1993, MD4 a été attaqué et en 1991 le NIST a introduit SHA (Secure Hash Algorithm) : SHA0 a montré une faille
de sécurité c’est pourquoi SHA1 a très vite vu le jour. En 1993, Antoine Joux et Chabaut ont proposé une attaque
en cascade qui ont amené à 2004 avec des chinois (Wang) qui ont proposé une attaque sur SHA1 en 271 . Une attaque
concrète a vu le jour sur ce dernier en 2017.
Ensuite, nous avons une nouvelle fois eu une compétition du NIST (en 2008) pour créer un nouveau standard : SHA-3
a donc été créé à partir de Keycchak qui est en ”structure éponge”.
En 1977, RSA est inventé et basé sur la factorisation, ce dernier permet de faire du chiffrement et de la signature.
En 1983, le chiffrement El Gamal voit le jour et ce dernier se base sur le problème du logarithme discret.
En 1984, ce problème du logarithme discret est généralisé sur les courbes elliptiques (par Koblitz et Miller).
Après nous avons les pairing (”accouplements”) : qui sont tout simplement des courbes elliptiques avec des propriétés
particulières (en particulier homomorphes) : c’est comme si nous avions un degré de liberté supplémentaire dans les
données (on peut faire plein de choses en plus) : c’est un chiffrement avancé, on peut faire du chiffrement basé sur
l’identité, des signatures de groupe, et plein de variations de ce type de chiffrement que l’on ne pouvait pas faire avant.
Les premières applications ont vu le jour en 2001 pour faire des attaques sur les courbes elliptiques.
Une petite ombre sur tout cela est l’apparition du chiffrement quantique : Peter Schor en 1994 a proposé un algorithme
quantique qui casse la factorisation en temps polynomial à condition d’avoir un ordinateur quantique suffisamment
puissant. L’idée générale est que les qbits peuvent être dans plusieurs états à la fois : si nous avons n qbits, il nous est
possible de tout parallélise et donc faire 2n opérations en même temps avec seulement n qbits : nous pouvons donc
gagner un facteur exponentiel.
ATTENTION : ça ne marche pas tout le temps, c’est ce qu’on peut gagner au mieux, en pratique, on les fait tous
travailler ensemble pour récupérer un résultat particulier et on peut y arriver uniquement dans certains cas particu-
liers : Schor pour calculer l’ordre d’un élément d’un groupe en temps polynomial (lié à la factorisation et aux courbes
elliptiques donc ça dégage), le second algorithme de Grover est beaucoup plus général et s’applique sur beaucoup plus
de situations (il permet de regarder plus vite si un élément
√ appartient à une liste) et il permet d’avoir un gain en
racine carrée (donc la complexité passe de O(n) à O( n)).
Actuellement on est à 100 qbits et on prévoit que l’on soit à plusieurs dizaines de milliers de qbits d’ici la fin de la
décennie. En 2015, la NSA a sorti un communiqué : vu l’anvacée des ordis quantiques, il faut passer au post quantique :
ce sont juste des algos qui sont résistants à l’ordinateur quantique. A priori un problème NP-dur en classique reste
NP-dur en quantique : il n’y aura donc pas d’attaque sur les problèmes les plus durs (codes, lattices, isogénies, ...).
Le NIST a organisé une nouvelle compétition en 2017 pour définir un standard qui serait post quantique : des schémas
de réseaux euclidiens, codes correcteurs, résolution de systèmes multivariés, signatures sur les fonctions de hachage
ont été proposés. Au premier tour il y avait 25 réseaux, 20 codes, 15 multivariés et 5 hash et quelques divers. Après
ce premier tour ils ont gardé 16 chiffrements et après un second tour plus que 9 (3 réseaux (NTRU / Kyber et 2
autres), 5 codes, 1 isogénie). Les isogénies sont des courbes elliptiques en beaucoup plus pourries. Ils ont également
fait un groupe de candidats alternatifs (3 codes : McEliece, Bike et HQC). Kyber a été standardisé, au 4ème tour il
faut choisir entre McEliece, Bike et HQC. Un nouvelle appel pour les signatures a été lancé.
Question b : Comment doit-on procéder pour échanger de façon optimale en temps avec quelqu’un une grande
taille de données chiffrées, sans avoir de clé secrète partagée au préalable ?
Question c : Quelles sont les grandes propriétés qu’on attend d’une fonction de hachage ?
Question d : Quels sont les paramètres du DES et sur quoi repose sa sécurité ? Est-ce que le DES est un schéma de
chiffrement sûr ?
2.1.2 Correction :
Question a : L’avantage est la rapidité du chiffrement à clé secrète comparé au chiffrement à clé publique, on gagne
environ un facteur 1000 en temps avec du chiffrement à clé secrète. Quelques exemples d’algorithmes à clé secrète sont
AES et DES, pour les algorithmes à clé publique nous avons par exemple RSA, El-Gamal, Rabin, ...
Question b : Nous pouvons tout d’abord remarquer qu’utiliser du chiffrement à clé publique pour toutes ces données
va être extrêmement long. La méthode à utiliser consiste à d’abord réaliser un échange de clé (en utilisant de la cryp-
tographie asymétrique) puis échanger les données en chiffrement à clé secrète grâce à la clé échangée précédemment.
Question c : Il y a 2 points importants qu’une fonction de hachage doit respecter : elle doit être résistante aux
collisions (c’est à dire qu’il est extrêmement difficile de trouver 2 entrées tels que le hash de ces dernières est le même)
et compresser les données qui lui sont envoyées.
Question d : Pour DES, ce sont les S-Box qui permettent la sécurité car c’est la seule composante non linéaire
de ce chiffrement. Ce n’est plus un algorithme de chiffrement sûr car sa sécurité repose sur du 256 ce qui est bien en
dessous des capacités de calcul actuelles et de plus il a déjà été cassé : les premières attaques sur DES ont eu lieu en
1998 et cela s’est fait sur une puce spéciale dédiée à cela, elle a cassé DES en 39 jours. Actuellement sur nos ordinateurs
personnels, une journée permet de le casser.
Question a : On suppose tout d’abord que Alice et Bob ont en commun la clé K = 102201, on suppose qu’Alice veut
envoyer le message M = 222222 chiffré par la clé K. Que vaut le chiffré de M par K ?
Question b : On suppose maintenant que Eve intercepte un chiffré C = 011101 (mais ne connait pas la clé secrète
utilisée), est-ce que le clair peut valoir M = 102 ?
Question c : Quels sont tous les clairs possibles qui peuvent donner le chiffré C = 011101 ?
Question d : A partir des questions précédentes, montrer qu’un tel schéma n’est pas bon, en ce sens qu’il y a
de l’information qui fuit et que ce schéma n’est pas parfaitement sûr. On pourra montrer que tous les chiffrés c1 , c2
(où c1 est un bit) n’ont pas la même probabilités d’exister.
Question e : Proposer un autre schéma à base de modulo qui serait parfaitement sûr.
2.2.2 Correction :
Question a : nous avons K = 102201 et M = 222222
Commençons par mettre K et M en binaire :
K : 01 00 10 10 00 01
M : 10 10 10 10 10 10
Question b : mettons nos 2 paramètres sur 2 lignes pour voir comment faire :
C : 01 11 01
M : 01 00 10
Comme vous pouvez le voir, il est impossible que le clair soit la valeur donnée car il faudrait que le second chiffre soit
11 = 3 pour que le XOR fonctionne et donne bien C ce qui est impossible.
Question d : nous allons tout simplement faire comme le prof le dit et lister pour chaque caractère toutes les
possibilités de message et clé qui donnent un certain chiffré :
Pour avoir 00 dans le chiffré : 3 couples (00, 00), (01, 01), (10, 10)
Pour avoir 01 dans le chiffré : 2 couples (01, 00), (00, 01)
Pour avoir 10 dans le chiffré : 2 couples (10, 00), (00, 10)
Pour avoir 11 dans le chiffré : 2 couples (10, 01), (01, 10)
Vous pouvez donc voir qu’il est plus probable d’obtenir 00 ce qui constitue donc une fuite d’informations.
Question e : un schéma qui est parfaitement sûr consiste tout simplement faire M +K (mod 3) pour chaque caractère
du messsage et de la clé.
Si nous reprenons le premier exemple :
K = 102201
M = 222222
Nous avons finalement comme chiffré C = 021120 (le premier 0 est obtenu en faisant 1 + 2 modulo 3).
Re-listons tous les couples possibles :
Pour avoir 0 dans le chiffré : 3 couples (0, 0), (1, 2), (2, 1) marchent.
Pour avoir 1 dans le chiffré : 3 couples (1, 0), (0, 1), (2, 2) marchent.
Pour avoir 2 dans le chiffré : 3 couples (2, 0), (0, 2), (1, 1) marchent.
Nous venons donc de confirmer qu’il s’agit bien d’un schéma de chiffrement sécurisé.
2.3.2 Correction :
Il faut tout d’abord se souvenir que pour un LFSR, nous avons C = M ⊕ K. K est tout simplement la suite de bits s
générée par le LFSR. Nous avons donc :
c = 10001110010101
m = ????101010????
Si nous faisons un XOR entre ces 2 valeurs, nous obtenons :
s = ????010011????
L’étape suivante va consister à trouver les ai qui vont permettre le calcul de tous les termes de la suite des si . Il
nous est dit que la complexité linéaire est d’au plus 3, commençons donc par 3 valeurs de ai .
Nous allons nous baser sur les bits 5 à 7 : 010.
Grâce à la relation du LFSR nous pouvons créer le système suivant :
Bit 8 : a2 × s5 + a1 × s6 + a0 × s7 = s8 ⇔ a2 × 0 + a1 × 1 + a0 × 0 = 0
Bit 9 : a2 × s6 + a1 × s7 + a0 × s8 = s9 ⇔ a2 × 0 + a1 × 0 + a0 × 1 = 1
Bit 10 : a2 × s7 + a1 × s8 + a0 × s9 = s10 ⇔ a2 × 1 + a1 × 0 + a0 × 0 = 1
Nous pouvons déduire de ces équations que a2 = 1, a1 = 0, a0 = 1.
Question c : supposons qu’on veuille envoyer la lettre ’D’ que l’on écrira 4 sous forme numérique. Quel est alors
le chiffré de ’D’ sous forme numérique pour ces paramètres ?
Question d : déchiffrer la valeur numérique obtenue pour le chiffré de ’D’ et montrer qu’on retrouve la valeur
numérique associée à ’D’.
2.4.2 Correction :
Question a : φ(21) = φ(7) × φ(3) = 6 × 2 = 12
Question c : c = me (mod n) = 45 (mod 21) : 40 = 1 (mod 21), 41 = 4 (mod 21), 42 = 16 (mod 21), 43 = 1
(mod 21), nous pouvons donc voir que l’ordre multiplicatif de 4 est 3 et donc que 45 = 43+2 = 43 × 42 = 1 × 16 = 16
(mod 21), le chiffré est donc 16.
Question d : d = cd (mod n) = 165 (mod 21) = 410 (mod 21) = 43×3+1 (mod 21) = 4 (mod 21) (43×3 = 1
(mod 21) car 3 est l’ordre multiplicatif de 4).
Question b : afin d’améliorer la sécurité des messages Bob choisit deux exposants e1 et e2 et demande à Alice
de chiffrer d’abord son message par e1 , pour obtenir c1 = me1 puis de re-chiffrer par e2 pour obtenir c2 = ce12 . Alice
va ensuite envoyer c2 . Est-ce que ce double chiffrement améliore la sécurité ? Si oui pourquoi et sinon pourquoi ?
Question c : on suppose qu’on chiffre un message m en calculant m3 (mod 101). Comment peut-on déchiffrer ?
C’est à dire trouver d tel que cd = m (mod 101), on remarquera que 101 est premier.
Question d : les exposants e = 1 et e = 2 ne doivent pas être utilisés comme exposants publics pour RSA, pourquoi ?
Question e : on suppose qu’on sait que deux personnes utilisent deux modules RSA n1 et n2 qui ne sont pas
premiers entre eux. Expliquer alors comment on peut casser les deux systèmes.
2.5.2 Correction :
Question a : il nous faut déjà voir ce à quoi a accès l’adversaire : il connaı̂t n, eA , eB ainsi que les 2 messages qu’il voit
passer qui sont meA et meB . Il suffit donc à l’adversaire de trouver u et v tels que eA × u + eB × v = 1 (cela ne marche
que parce que pgcd(eA , eB ) = 1 vu qu’ils sont premiers entre eux). Une fois cela fait, il lui suffit tout simplement de
calculer (meA )u × (meB )v = meA ×u+eB ×v = m1 = m.
Question b : non, cela est identique à un chiffrement RSA ”normal” avec la clé publique e1 × e2 nous ne gagnons
donc pas en sécurité.
Question c : il nous faut trouver 3−1 (mod 100) ce qui vaut 67 car 3 × 67 = 201. Pour déchiffrer, il suffira donc de
calculer c67 (mod 101).
Question d : voici les raisons qui font que ces 2 exposants ne peuvent pas être utilisés :
e = 1 : à ne pas utiliser car le message n’est pas chiffré !
e = 2 : c’est également tout simple, il faut pouvoir trouver d = e−1 (mod φ(n)), ce dernier n’existe que si e et
φ(n) sont premiers entre eux, or φ(n) = (p − 1) × (q − 1) qui est un produit de nombres pairs et est donc pair :
du coup e et φ(n) ne sont pas premiers entre eux et on ne pourra pas trouver d.
Notez qu’il existe tout de même un cryptosystème qui permet d’utiliser e = 2 : le crytposystème de Rabin. Il se base
sur le résidu quadratique et à cause de cela chaque chiffré peut donner lieu à plusieurs messages ce qui peut être
compliqué à gérer.
Question e : vu que les 2 modules ne sont pas premiers entre eux, ils ont un facteur premier en commun, il suffit
donc de calculer pgcd(n1 , n2 ) = p et puis retrouver q1 = n1 /p et q2 = n2 /p.
L’idée derrière ce protocole est que le message ne passe jamais en clair (bien évidemment) et également que seul S
peut enlever le x qu’il a rajouté et seul R peut enlever le y qu’il a rajouté.
Question b : que se passe-t-il précisément du point de vue mathématique lorsque S élève M xy à la puissance z ?
Question c : quelles sont précisément les opérations mises en oeuvre par R pour enlever y et pourquoi lui permettent-
elels de retrouver M ?
Question d : expliquez en vous servant par exemple du théorème de Bezout, pourquoi x et y doivent être pre-
miers avec P − 1.
Question e : en définitive, à quel schéma à clés publiques vu en cours le procédé décrit par J. H ; Ellis se ramène-t-il ?
Justifiez votre réponse ?
Question f : S et R ont choisir de travailler avec P = 101. Les valeurs utilisées par S sont 3 et 67, celles utilisées par
R sont 13 et 77. Au total, combien de multiplications seront effectuées au cours de l’échange, si les exponentiations se
font par la méthode rapide ?
2.6.2 Correction :
Question a : M zx (mod P ) = M k×(P −1)+1 (mod P ) = (M P −1 )k × M (mod P ) = 1 × M (mod P ) = M (mod P ).
Question c : R commence par trouver w tel que wy = 1 (mod P − 1) puis calcule M yw = M (mod P ).
Question d : supposons que x n’est pas premier avec P −1, la relation de Bézout nous dit qu’il sera possible de trouver
z et a tels que xz + a × (P − 1) = pgcd(x, P − 1), nous voyons donc qu’il sera impossible de trouver un inverse modu-
laire de x car ce dernier n’est pas premier avec P −1 : pgcd(x, P −1) ̸= 1. Le même raisonnement peut être appliqué à y.
Question e : ce schéma est très similaire à l’échange de clé diffie-hellman car les 2 parties génèrent une valeur
aléatoire, font une exponentiation modulaire puis arrivnet à dériver le même message en faisant des opérations sur les
exposants.
Question f : dans une exponentiation rapide, nous aurons 1 multiplication si le bit est à 0 et 2 multiplications
si le bit est à 1. Nous allons donc écrire les différents nombres en binaire et calculer le nombre de multiplications :
M x = M 3 : 3 = 11, 2 multiplications (on retire le premier 1)
M xy = (M x )13 : 13 = 1101, 5 multiplications.
M xyz = (M xy )67 : 67 = 1000011, 8 multiplications.
M wy = (M y )77 : 77 = 1001101, 9 multiplications.
Question b : êtes-vous d’accord avec Bob et Alice sur la sécurité du protocole ? Justifiez ?
2.7.2 Correction :
Question a : soit c = r ⊕ k, Alice va tout simplement calculer c ⊕ k et voir si c’est égal à r : si oui elle sait que c’est
bien Bob.
Question b : absolument pas, un attaquant qui voit passer le premier message contenant seulement r et le se-
cond message contenant r ⊕ k peut très bien calculer r ⊕ (r ⊕ k) = k et donc obtenir la clé secrète (ce qui est un peu
con).
3 TD 1 - Attaques algébriques :
3.1 LFSR et attaques algébriques :
Le problème avec les LFSR ”normaux” est qu’ils sont linéaires : c’est cette propriété de linéarité qui rend l’attaque
par texte clair connu possible. Il existe 2 solutions :
Les registres filtrés où un LFSR ”normal” est utilisé mais toutes ses k sorties précédentes sont sauvegardées et
un sous-ensemble de ces sorties sont envoyées à une fonction booléenne non-linaire f .
Les registres combinés où k LFSR sont utilisés et leurs sorties sont envoyées dans une fonction booléenne f
encore une fois non-linéaire pour casser la linéarité.
Voici une première image vous montrant un LFSR ”conventionnel” avec un polynôme de rétroaction de degré 10 :
Et voici une seconde image pour montrer le fonctionnement d’un registre filtré :
Mais vous pouvez remarquer que ce système ne nous permet pas de retrouver la graine, il peut à la limite permettre
de trouver les k bits après la graine ou encore de retrouver les k valeurs des ai (c’est même ce système qui nous justifie
qu’il faut au moins 2k bits de s pour pouvoir retrouver les ai sinon il nous manquerait des équations).
De cette façon, si nous arrivons à trouver A, il nous suffira de l’inverser et de multiplier l’équation par ce résultat pour
trouver la graine. Notez de plus que la matrice donnée sera constituée des ai que nous connaissons également.
Mais trouver la matrice A de cette façon risque d’être très dur, voire impossible, une manière plus simple de la trouver
consiste à chercher :
s2 s1
... = A × ...
sk+1 sk
Cette matrice est très simple à trouver, la voici :
0 1 0 0 ··· 0 0 0 0
s2 s1
s3 0 0 1 0 ··· 0 0 0 0 s2
. .. .. .. .. .. .. .. .. ×
... =
.
. . . . . . . . .
...
sk
sk−1
0 0 0 0 ··· 0 0 0 1
sk+1 ak ak−1 ak−2 ak−3 ··· a4 a3 a2 a1 sk
Une fois que nous l’avons trouvée, nous pouvons tout simplement dire que :
sk+1 s1
... = Ak × ...
sk+k sk
Notez également pour finir que cette représentation matricielle n’est possible que parce que le LFSR ”standard” est
une primitive linéaire. Il est aussi important de voir que le calcul de Ak devra se faire modulo 2.
Finalement, pour retrouver la graine il nous suffira de calculer l’inverse de cette matrice :
s1 sk+1
k −1
... = (A ) × ...
sk sk+k
Commençons par quelques notations : X0 , ..., X5 sera la graine (l’initialisation) donnée au LFSR, les Xi suivants seront
obtenus en passant à l’état suivant du LFSR. Le bit de sortie sera noté zi . Nous définirons également k = 4 dans
notre cas qui indiquera le nombre d’entrées de la fonction booléenne. Pour finir df = 2 sera le degré de notre fonction
booléenne (le degré de la fonction est tout simplement le degré du monome de plus haut degré).
Notre but sera tout simplement de trouver une relation entre les Xi initiaux et la sortie z.
Nous admettrons la connaissance d’autant de bits de la sortie z que nécessaire et notre but sera de retrouver l’initia-
lisation.
Tout d’abord, commençons par la relation nous permettant de trouver l’évolution du LFSR ”conventionnel” :
X1 0 1 0 0 0 0 X0
X2 0 0 1 0 0 0 X1
X3 0 0 0 1 0 0
(1) × X2 = A × X (0)
X = X4 = 0 0 0 0
1 0
X3
X5 0 0 0 0 0 1 X4
X6 1 1 0 0 1 0 X5
Maintenant que nous avons fait cela, nous pouvons faire passer toutes ces entrées dans la fonction booléenne :
z0 = f ([X (0) ]4 ) = f (X1 , X2 , X3 , X5 ) = X1 X2 + X3 X5
z1 = f ([X (1) ]4 ) = f (X2 , X3 , X4 , X6 ) = X2 X3 + X4 (X0 + X1 + X4 ) = X2 X3 + X0 X4 + X1 X4 + X4 X4
z2 = f ([X (2) ]4 ) = f (X3 , X4 , X5 , X7 ) = X3 X4 + X5 (X1 + X2 + X5 ) = X3 X4 + X1 X5 + X2 X5 + X5 X5
z3 = f ([X (3) ]4 ) = f (X4 , X5 , X6 , X8 ) = X4 X5 + (X0 + X1 + X4 )(X0 + X1 + X2 + X3 + X4 ) = X4 X5 + ...
z4 = f ([X (4) ]4 ) = f (X5 , X6 , X7 , X9 ) = X5 X6 + X7 X9 = ...
Et ainsi de suite. C’est ici que la remarque précédente va nous servir : vu que les Xi , i >= 6 sont des combinaisons
linéaires des Xi , i <= 5, le degré du système sera le même degré que celui de la fonction ! Pour le voir prenez X6 × X8 ,
le résultat ne sera composé que de monomes de degré au plus 2. Notez également que vu que nous sommes en binaire
X4 X4 = X4 .
Nous allons donc obtenir un système multivarié où chaque monome sera de degré au plus 2. Résoudre un système
linéaire (où chaque monome est de degré exactement 1) est assez facile, il suffit de trouver la matrice du système,
l’inverser et faire une multiplication et c’est bon. En revanche pour un système multivarié comme celui que nous avons
actuellemment c’est plus compliqué : une façon de s’en sortir consiste à créer plein d’autres variables, appelons les
Yi,j qui seront égales à Xi Xj , cela nous permet en quelque sorte de ”linéariser” le système mais comme vous pouvez
vous en douter le nombre d’inconnues et donc le nombre d’équations nécessaires va croı̂tre. Une bonne question à se
poser est : combien de nouvelles variables aura-t-on ? La réponse à cette question est simple : il suffit tout simplement
de prendre 2 indexs i et j (sachant que i peut être égal à j) ce qui nous ferait N 2 nouvelles inconnues. En revanche,
souvenez vous que la multiplication est commutative, nous pouvons donc enlever tous les doublons (c’est à dire les
1 2
Yi,j , Yj,i ) et notre nombre d’inconnues possibles passe donc à CN + CN = N + N (N − 1)/2 = N (N + 1)/2 (1 parmi
N pour tous les monomes du type Xi et 2 parmi N pour tous les monomes du type Xi Xj ).
Dans notre cas, voici un tableau représentant les différentes combinaisons de variables qu’il est possible d’avoir :
× X0 X1 X2 X3 X4 X5
X0 Y0,0 = X0 Y0,1 = X0 X1 Y0,2 = X0 X2 Y0,3 = X0 X3 Y0,4 = X0 X4 Y0,5 = X0 X5
X1 Y1,0 = Y0,1 Y1,1 = X1 Y1,2 = X1 X2 Y1,3 = X1 X3 Y1,4 = X1 X4 Y1,5 = X1 X5
X2 Y2,0 = Y0,2 Y2,1 = Y1,2 Y2,2 = X2 Y2,3 = X2 X3 Y2,4 = X2 X4 Y2,5 = X2 X5
X3 Y3,0 = Y0,3 Y3,1 = Y1,3 Y3,2 = Y2,3 Y3,3 = X3 Y3,4 = X3 X4 Y3,5 = X3 X5
X4 Y4,0 = Y0,4 Y4,1 = Y1,4 Y4,2 = Y2,4 Y4,3 = Y3,4 Y4,4 = X4 Y4,5 = X4 X5
X5 Y5,0 = Y0,5 Y5,1 = Y1,5 Y5,2 = Y2,5 Y5,3 = Y3,5 Y5,4 = Y4,5 Y5,5 = X5
Vous pouvez remarquer que nous avons 21 inconnues, il nous faudra donc 21 bits de la sortie zi pour obtenir 21
équations et pouvoir nous en sortir. Une fois ce système résolu nous aurons les bits de la graine et nous aurons gagné !
Ce système aura des monômes de degré au plus df , cela veut dire que le nombre total d’équations qu’il faudra pour
1 2 df
pouvoir espérer résoudre le système est : α = CN + CN + ... + CN
Spoiler : par exemple pour N = 128, n = 64 et df = 64, nous avons que le nombre d’équations nécessaires est
1 2 64
C128 + C128 + ... + C128 ≃ 2128 /2 = 2127 valeurs de zi . La complexité serait (2127 )3 = 2381 : énorme !
1 1 0 0 1 0 1
× 1 0 0 1 1
1 1 0 0 1 0 1
+ 1 1 0 0 1 0 1 -
+ 1 1 0 0 1 0 1 - - - -
= 1 1 1 0 1 1 1 1 1 1 1
Nous ferons en moyenne k/2 additions (avec k le nombre de bits des 2 nombres) et chaque addition se fera sur au plus
2k chiffres ce qui nous donne une complexité en O((k/2) × 2k) = O(k 2 ).
Il est possible de faire mieux ! Soient x et y, 2 nombres sur k bits en binaire, nous pouvons les décomposer en
x = a × 2k + b et y = c × 2k + d. Dans un produit ”normal” nous ferions en quelque sorte 4 multiplications :
Et du coup, en utilisant cette nouvelle méthode la complexité de l’opération passe de O(k 2 ) à O(k log2 (3) ) ≃ O(k 1.585 ).
Il existe une méthode très similaire pour améliorer le produit de matrices. Commençons par rappeler comment le
produit fonctionne :
a1,1 a1,2 b b a1,1 × b1,1 + a1,2 × b2,1 a1,1 × b1,2 + a1,2 × b2,2
× 1,1 1,2 =
a2,1 a2,2 b2,1 b2,2 a2,1 × b1,1 + a2,2 × b2,1 a2,1 × b1,2 + a2,2 × b2,2
La complexité est très simple à trouver : chaque élément de la matrice résultat peut se voir comme un produit scalaire
entre une ligne de la première matrice et une colonne de la seconde. Du coup le nombre d’opérations pour trouver une
valeur de la matrice résultat est O(n) multiplications (nous pouvons négliger le coût des additions) et donc le nombre
d’opérations pour trouver la totalité de la matrice résultat est O(n3 ).
La méthode pour accélérer la multiplication de matrices se réalise encore une fois en ”divide and conquer” (diviser
pour mieux régner) comme nous l’avons vu précédemment, il suffit de diviser chaque matrice en sous-blocs, voici donc
la nouvelle forme de la multiplication ”normale” :
A1,1 A1,2 B1,1 B1,2 A1,1 × B1,1 + A1,2 × B2,1 A1,1 × B1,2 + A1,2 × B2,2
× =
A2,1 A2,2 B2,1 B2,2 A2,1 × B1,1 + A2,2 × B2,1 A2,1 × B1,2 + A2,2 × B2,2
La méthode plus rapide qui se nomme algorithme de Strassen va faire en sorte de ne plus avoir que 7 multiplications
au lieu de 8. Il y aura quelques calculs intermédiaires (à gauche) et les coefficients de la matrice finale sont donnés à
droite :
M1 = (A1,1 + A2,2 ) × (B1,1 + B2,2 )
M2 = (A2,1 + A2,2 ) × B1,1
C1,1 = M1 + M4 − M5 + M7
M3 = A1,1 × (B1,2 − B2,2 )
C = M + M
1,2 3 5
M4 = A2,2 × (B2,1 − B1,1 ) ,
C 2,1 = M 2 + M 4
M5 = (A1,1 + A1,2 ) × B2,2
C2,2 = M1 − M2 + M3 + M6
M6 = (A2,1 − A1,1 ) × (B1,1 + B1,2 )
M7 = (A1,2 − A2,2 ) × (B2,1 + B2,2 )
Ici, il est possible de le prouver en utilisant le théorème du maı̂tre, mais la nouvelle complexité est O(n2.8 ).
Pour l’inversion de matrice il suffit de voir qu’elle peut se faire par bloc :
Nous pouvons appliquer ce nouvel algorithme à notre cas ce qui nous donne 2127×2.8 ≃ 2355 !
Il existe d’autres méthodes d’inversion de matrice mais elles sont soit impraticables (exposant de l’algèbre linéaire
en n2.36 ) soit non adaptées au cas de figure étudié (matrices de Vandermonde / algorithme de Wideman pour un
système creux en n2 ).
x1 0 1 0 1 0 1 ... 0 1
x2 0 0 1 1 0 0 ... 1 1
.. .. .. .. .. .. .. .. .. ..
. . . . . . . . . .
xn 0 0 0 0 0 0 ... 1 1
f 1 1 0 1 0 0 ... 1 0
L’autre point important est que nous cherchons une fonction g qui sera égale à 0 pour tout x tel que f (x) = 1, dans
le cas contraire si f (x) = 0 peu importe la valeur de g nous obtiendrons 0 donc on s’en fout de ces x là !
Ce problème peut donc se réduire à résoudre un système de 2n /2 équations (car en moyenne la sortie de f aura 50%
de chances de valoir 0 et 50% de chances de valoir 1 et nous avons 2n entrées possibles) pour lesquelles chacune doit
valoir 0. Pour pouvoir résoudre un tel système, il nous faudra 2n /2 variables (correspondant à des monomes de xi ).
Or, nous avions dit précédemment que le nombre de variables correspondant à un xi était 1 parmi n, le nombre de
variables pour 2 xi est 2 parmi n et ainsi de suite jusqu’au degré maximal du monôme. Il nous suffit donc de chercher
Pdg
dg tel que i=1 Cni >= 2n /2 ce qui se produit pour dg = n/2 + 1.
Pour mieux comprendre comment cela fonctionne, faisons un exemple avec la fonction f suivante : f (x1 , x2 , x3 , x4 ) =
1 + x1 x2 + x1 x3 x4 + x3 . Voici le tableau décrivant les différentes valeurs de la fonction :
x1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
x2 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
x3 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
x4 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
f 1 1 0 0 1 1 0 0 1 1 0 1 0 0 1 0
Vous pouvez remarquer qu’il y a 8 valeurs à 1, nous aurons donc besoin de 8 variables. Vous pouvez remarquer qu’en
prenant 1 parmi 4 + 2 parmi 4, nous pouvons obtenir 10 ce qui est suffisant : l’IA de cette fonction boolénne est 2.
Toutes ces informations vont nous permettre de trouver des conditions sur la fonction booléenne g (j’appellerais ci le
coefficient devant xi , ci,j celui devant xi xj et ainsi de suite) :
g(0, 0, 0, 0) = 0 : donc le terme constant de g est à 0 (car tous les monômes de xi sont déjà nuls).
g(0, 0, 0, 1) = 0 : seul x4 peut donner un résultat à 1, il faut donc que c4 = 0.
g(0, 1, 0, 0) = 0 : donc c2 est nul.
g(1, 0, 0, 0) = 0 : donc c1 est nul.
g(0, 1, 0, 1) = 0 : x2 , x4 , x2 x4 sont les variables qui peuvent mettre le résultat à 1, nous savons que c2 et c4 sont
nuls donc nécessairement c2,4 est nul aussi.
g(1, 0, 0, 1) = 0 : donc c1,4 est nul.
g(1, 0, 1, 1) = 0 : x3 , x1 x3 , x3 x4 , x1 x2 x4 sont possibles et n’ont pas encore de coefficient attribué, nous en
déduisons donc 0 parmi 4 + 2 parmi 4 + 4 parmi 4 = 8 possibilités.
g(1, 1, 1, 0) = 0 : x3 , x1 x2 , x1 x3 , x2 x3 , x1 x2 x3 sont possibles et n’ont pas encore de coefficient attributé, et il y
a ici 0 parmi 5 + 2 parmi 5 + 4 parmi 5 = 16 possibilités.
Nous savons que IA(f ) = 2, nous allons donc nous restreindre aux polynômes de degré 2. Il faut que c = 0,
c1 = c2 = c4 = 0, c1,4 = c2,4 = 0, un polynôme qui marche est x3 + x1 x3 car il vérifie également les 2 dernières
conditions. Comme vous pouvez vous en douter il en existe également plein d’autres qui marchent, il suffit juste qu’ils
passent les conditions données.
Et ils arrivent à trouver une fonction g, apparemment IA(f) = 3 et du coup au lieu d’avoir 2350 équations, on en a 3
parmi 128 ≃ 218 ce qui nous donne un temps proporitionnel à 254 environ.
La solution implémentée en réalité est tout simplement de reprendre une nouvelle seed tous les 1000 bits générés
par exemple.
4 Authentification :
4.1 Quelques propriétés des blocs de base en cryptographie asymétrique :
Les 4 blocs sur lesquelles nous allons nous pencher seront : le chiffrement, l’échange de clé, la signature ainsi que
l’authentification.
Le chiffrement :
Échange de clé : POSSIBLE, allez voir les mécanismes d’encapsulation de clé. L’idée est tout simplement de
prendre une clé symétrique K, la chiffrer avec la clé publique du serveur puis envoyer ce chiffré au serveur.
Signature : IMPOSSIBLE, sauf dans le cas particulier de RSA où le déchiffrement est ”la même opération” que
le chiffrement.
Authentification : POSSIBLE, en mode ”défi-réponse” (comme nous le verrons après). Le serveur envoie tout
simplement le chiffré d’une valeur aléatoire avec la clé publique du client, le client déchiffre et renvoie cette
valeur aléatoire, cela fait bien de l’authentification car seul le détenteur de la clé privée peut déchiffrer.
La signature :
Chiffrement : IMPOSSIBLE
Échange de clés : IMPOSSIBLE
Authentification : POSSIBLE, encore une fois en mode ”défi-réponse”, le client va signer une valeur aléatoire
avec sa clé privée et le serveur pourra la vérifier avec la clé publique du client.
L’authentification : ne permet ni le chiffrement, ni l’échange de clés ni la signature sauf lorsque nous serons en
présence d’authentification zero knowledge.
Notez que vu que par exemple le chiffrement implique l’authentification, en faisant de l’authentification toute seule
(standalone) il est possible de gagner peut-être un peu en efficacité (au lieu que d’utiliser un algorithme de chiffrement
pour la réaliser) mais nous verrons un exemple plus loin.
1 seule passe :
Ici, nous allons étudier le schéma de Lamport. Ce dernier est très simple : le client et le serveur gardent chacun un
compteur qui sera incrémenté de 1 à chaque nouvelle authentification réussie, le client va tout simpelemtn envoyer
H n−i (password) avec n une valeur fixée par les 2 parties et i le compteur. Prenons par exemple n = 100 et un compteur
initial i = 0, à la première connexion le client enverra H 100 (password) = H(H 99 (password)) et à la seconde il enverra
H 99 (password). Ce schéma est effectivement sécurisé contre les attaques par rejeu mais notez que si la fonction de
hachage n’est pas résistante à la pré-image (c’est à dire que l’attaquant peut retrouver x si on ne lui donne que H(x))
alors il pourra prévoir le second message envoyé et s’authentifier.
Voici un schéma résumant ce protocole :
2 passes :
Avec 2 passes, nous verrons plutôt des schémas de type ”défi - réponse” : le serveur enverra un défi au client, le client
enverra une réponse qui lui permettra de prouver au serveur qu’il connaı̂t le mot de passe.
L’idée peut être représentée par le protocole suivant :
Une nouvelle fois, ce protocole permet de se protéger contre les attaques par rejeu et il est plus simple que le précédent
car il ne demande pas au 2 parties de synchroniser un compteur, il faut juste un nonce (Number used ONCE) généré
aléatoirement par le serveur. Notez que si la fonction de hachage n’est pas résistante à la pré-image, l’attaquant peut
encore une fois récupérer le mot de passe !
Le serveur pour autoriser l’authentification va tout simplement calculer H(password||NS ) et voir s’il est égal à la
valeur qu’il a reçue du client.
3 passes :
Pour finir, les schémas à 3 passes sont plus adaptés aux algorithmes de chiffrement asymétriques que nous verrons après.
Il est évident de voir que le prouveur peut toujours répondre au défi, il s’agit tout simplement d’une mise à la puissance
0 / 1.
Voyons maintenant les 2 cas quand il nous est possible de nous faire passer pour le prouveur P . Il nous faut tout
d’abord définir ce que veut dire ”se faire passer pour P ” : il s’agit tout simplement de lancer une exécution du pro-
tocole en tant que P et le défi sera de faire en sorte que le dernier message soit vérifié (sans connaı̂tre la clé privée).
Voici les 2 cas :
Si r = 0 : nous avons juste à renvoyer la valeur de k que nous connaissons.
Si r = 1 : nous ne pouvons pas prendre k = 0 sinon le manque d’aléatoire serait détectable, l’idée va être
d’envoyer k 2 /A dans le premier message, puis k dans le second : y 2 = (k)2 = k 2 et K × A1 = (k 2 /A) × A = k 2 ,
les 2 valeurs sont donc égales !
Nous pouvons donc en déduire qu’en jouant toujours le cas r = 0, nous avons 1 chance sur 2 de gagner, ce sera la
même probabilité pour le cas r = 1. Mais, vu qu’on ne connaı̂t pas r à priori et que les 2 engagements sont différents
dans les 2 cas il nous est impossible de faire mieux.
Prouvons maintenant que nous ne pouvons pas faire mieux que 1/2 : le premier message sera modifié en α et le dernier
message sera modifié en βi , de plus V va vérifier que βi2 = α × Ar . En nous servant de cette formule, nous pouvons
voir que pour r = 0, β02 = α et dans le cas r = 1, β12 = α × A. Le but de l’attaquant pour toujours réussir serait de
trouver β0 et β1 pour le même α, trouver β0 est facile, pour trouver l’autre il nous faudrait une relation β1 = β0 + ...
ou β1 = β0 × ... :
Méthode additive : β02 − β12 = (β0 + β1 ) × (β0 − β1 ) = α × (A − 1) ce qui ne permet de rien faire.
Méthode multiplicative : β12 /β02 = (β1 /β0 )2 = (α × A)/α = A : le seul moyen pour l’attaquant de trouver ce
rapport est de connaı̂tre une racine de A : ce problème est équivalent à la factorisation car pour résoudre le
résidu quadratique dans les nombres modulo N il faut connaı̂tre sa factorisation.
Donc au final, à chaque exécution du protocole, un attaquant a une chance sur 2 de se faire passer pour le prouveur. Ce
protocole peut donc voir sa sécurité modulée en fonction du nombre tentatives : t répétitions du protocoles donneront
lieu à une probabilité de se faire passer pour le prouveur dans tous les tests de (1/2)t .
Pour finir, pour prouver la propriété de zero knowledge, la méthodologie est la suivante : il faut simuler les échanges
entre un vrai prouveur et un vérifieur et montrer que d’un point de vue théorie de l’information il n’est pas possible
de les distinguer avec une exécution sur le même ordinateur.
Conclusion :
Soit t le nombre de tous et b le nombre de bits de N .
Le premier tour va envoyer b données, le second un seul bit et le dernier b données également. Cela nous fait un coût
de communication de 2b × t ce qui est beaucoup plus élevé que RSA.
En revanche, pour le nombre de multiplications il est simplement de 2 × t. Par exemple, pour une authentification à
2−100 , nous faisons 100 tours et donc 200 multiplications alors qu’avec un RSA il aurait fallu faire 1000 multiplciations.
Ce protocole n’est pas utilisé dans la pratique mais il a ouvert les portes pour d’autres protocoles tels que celui de
Guillou et Quisquater en 1988.
5 Magic crypto :
5.1 Définition du problème et une première solution :
Commençons par donner une définition de ce qu’est la magic crypto : c’est un problème qui à priori semble impossible
mais qui en réalité l’est.
Nous allons voir le problème du retrait d’information privé (ou ”Private Information Retrieval”) : supposons que
nous avons une base de données de films et un utilisateur qui veut télécharger un film depuis cette dernière sans que
la base de données sache quel film a été téléchargé : le but est d’avoir de la ”privacy”.
Une première méthode qui serait possible est de laisser l’utilisateur télécharge la totalité de la base de données et ce
dernier va ensuite choisir le film qu’il veut depuis ce qu’il a téléchargé.
Une autre méthode est d’utiliser un tiers de confiance, de cette manière la base de données ne sait pas qui a téléchargé
le film mais il faut avoir confiance en ce tiers de confiance.
Pour résoudre ce problème, il faudra forcément que la base de données soit lue en totalité (sinon il lui est possible de
gagner de l’information) mais nous avons un critère d’efficacité qui rentre en compte : la taille de la réponse est faible
(le mieux que l’on puisse espérer est la taille de l’élément voulu).
Un exemple de solution à ce problème est le protocole d’Ostrovsky et Kushilevitz que nous présenterons ci-dessous.
Prenons maintenant n = p × q, nous pouvons démontrer que chaque résidu quadratique a a exactement 4 racines.
La première chose à prouver est que tout résidure quadratique a modulo n est un résidu quadratique modululo p et
modulo q. La preuve est très simple, vu que x2 ≡ a (mod n), nous avons que ∃k ∈ Z, a = x2 + k × p × q qui donne
également x2 modulo p et modulo q.
Sachant cela, nous pouvons dire que a est un résidu quadratique modulo p et trouver les 2 racines que nous noterons
xp et p − xp . La même procédure peut être répétée pour le modulo q ce qui va nous donner xq et q − xq . Le problème
est que toute ces racines sont soit modulo p soit modulo q et nous les voulons modulo n : nous allons appliquer un
théorème chinois des restes à chaque paire de racines (une prise modulo p et une prise modulo q) ce qui nous donnera
nos 4 racines finales.
Notez pour finir que savoir si a (mod n) est un carré est équivalent à factoriser n (car il faut pouvoir récupérer les
racines modulo p et q pour trouver celles modulo n).
Et un petit programme en python pour trouver tous les résidus quadratiques : Voici un programme en python pour
recuperer la liste de tous les résidus quadratiques :
1 n = 391
2 listeCarres = []
3 for i in range (0 , n ) :
4 carre = ( i * i ) % n
5 if carre not in listeCarres :
6 listeCarres . append ( carre )
7 listeCarres = sorted ( listeCarres )
8 print ( listeCarres )
Pour le déchiffrement, en connaissant p et q, nous pouvons retrouver les 4 racines de c en utilisant le critère d’Euler.
Prenons l’exemple du modulo p, nous savons grâce au théorème de Fermat que ap−1 = 1 (mod p), nous pouvons donc
en déduire que a(p−1)/2 = ±1 (mod p) (car les 2 seules racines de l’unité sont 1 et -1 modulo p et p − 1 peut être
divisé par 2 car il est pair). Le critère d’Euler nous dit que a est un résidu quadratique si et seulement si a(p−1)/2 = 1
(mod p) (les a pour lesquels nous obtenons -1 sont donc les non-résidus). Chercher les racines de a revient donc à
trouver b2 = a(p−1)/2 × a = a(p+1)/2 = a (mod p), or nous savons que p ≡ 3 (mod 4), nous pouvons donc dire que
p + 1 est un multiple de 4 et prendre b = ±a(p+1)/4 !
Dans la suite, i0 sera l’index du film à récupérer (entre 1 et N ), pour l’exemple, nous prendrons i0 = 5.
Nous allons également choisir p et q, 2 nombres premiers et calculer n = p × q (ces valeurs ne seront connues que de
l’utilisateur), encore une fois, pour l’exemple nous prendrons p = 17 et q = 23 ce qui nous donne n = 391.
Dans la requête, nous allons envoyer une liste de nombres aléatoires r1 , ..., rN ainsi que le module RSA n. Dans
cette liste, chaque ri sera un résidu quadratique (un carré) sauf pour ri0 qui sera un non carré. Nous pourrions par
exemple envoyer la liste (r1 = 82 = 64, r2 = 2362 = 174, r3 = 952 = 32, r4 = 3082 = 242, r5 = 7, r6 = 2812 = 370, r7 =
1462 = 202, r8 = 3612 = 118). Comme vous pouvez le voir, ici, le seul non carré est r5 qui vaut 7.
Le serveur, lorsqu’il va recevoir ces nombres va réaliser le calcul suivant pour chaque bit j :
b b b b b b b b
sj = r11,j × r22,j × r33,j × r44,j × r55,j × r66,j × r77,j × r88,j
bi,j
Notez que tous les ri avec i ̸= i0 seront des carrés (car si bi,j = 1 nous avons ri qui est un carré et si bi,j = 1 nous
avons 1 qui est également un carré). Nous savons également que ri00 = 1 sera un carré, alors que ri10 = ri0 sera un non
carré, or un produit avec que des carrés donnera un carré alors qu’un produit contenant un seul non carré donnera
un non-carré : nous pourrons donc utiliser cela pour distinguer entre les 2 valeurs de bit ! (si le nombre sj recu est un
carré nous savons que le bit j du film i0 était 0, sinon ce dernier était 1).
Vous pouvez voir grâce à cette liste que la liste des si que nous avons sont : [ carré, carré, non-carré, carré, non-carré,
non-carré, non-carré, non-carré, carré, carré, non-carré ] ce qui nous donne les bits du 5ème film qui sont : 0, 0, 1,
0, 1, 1, 1, 0, 0, 1.
La conclusion est que la base de données ne connaissant pas p et q, elle ne peut pas distinguer entre un carré et
un non carré. Aussi tous les bits de la base sont passés en revue. Nous avons donc une privacy totale !
La conclusion est : c’est nul ! Cette conclusion n’est valide que dans le cas de l’exemple d’une base de données
contenant des films. Si nous arrivons à maximiser la valeur de N (le nombre d’enregistrements), et minimiser la valeur
B (le nombre d’octets par enregistrement de la table), nous aurons quelque chose de plutôt efficace.
Ce protocole est donc plutôt adapté aux DNS, aux dossiers médicaux, aux empreintes ADN, ...
6 Protocoles Zero-Knowledge :
6.1 Exercice 18 page 40 :
Voici une variation du protocole d’authentification fiat-shamir sur du logarithme discret :
Clés : nous choisirons p et q 2 grands entiers tels que q divise p − 1, g un entier d’ordre q modulo p. La clé secrète est
tout simplement une valeur a aléatoire entre 0 et q − 1, la clé publique sera A = g −a (mod p).
Le protocole en 4 étapes entre le prouveur et le vérifieur est le suivant :
Alice choisit k aléatoire entre 0 et q − 1 et envoie K = g k (mod p)
Bob choisit un défi r aléatoire entre 0 et q − 1 et l’envoie à Alice.
Alice calcule la réponse y = k + a × r (mod q)
Pour finir, Bob calcule g y × Ar = g k+ar × g −ar = g k et vérifie que c’est bien égal à K (mod p).
Question 2 : montrez que le protocole est cohérent et que la probabilité de triche est 1/q.
Pour montrer que ce protocole est cohérent, il nous suffit de prouver que le prouveur (Alice) peut toujours donner une
réponse au troisième message peu importe le défi qu’elle a reçu plus tôt : c’est évident, il lui suffit de calculer k + a × r
(mod q) ce qui est toujours possible peu importe la valeur de r.
Une autre question est : pourquoi ça marche ? Nous l’avons déjà montré dans la définition du protocole que lors d’une
exécution honnête, nous aurons forcément g y × Ar = g k .
Pour trouver la probabilité de triche, il va falloir que nous modélisons ce que l’attaquant a le droit et pas le droit de
faire : ce dernier se fait passer pour le prouveur, il connaı̂t donc k mais aussi la clé publique et le défi, il lui manque juste
a. Le seul moyen pour cet attaquant de tricher est de deviner la valeur de a et il a une chance sur q de faire le bon guess.
Nous pouvons maintenant définir un algorithme de signature pour le message m grâce à un protocole d’authenti-
fication :
Une constante t sera définie indiquant le nombre d’exécutions du protocole d’authentification, cela permettra de régler
le nombre de bits de sécurité (par exemple avec le protocole de Fiat-Shamir basé sur le résidu quadratique, nous
pouvons prendre t = 80 pour avoir une sécurité de 80 bits).
Les différents composants que nous allons utiliser dans la suite seront les suivants :
E = E1 ||E2 ||...||Et : les différents engagements choisis aléatoirement.
D = d1 , ..., dt = H(m||E) avec m le message et H une fonction de hachage.
R1 , ..., Rt les réponses au différents challenges calculées par le signataire.
La signature d’un message sera Sign(m) = (E, R).
Pour la vérification, il suffira de calculer D = H(m||E) et vérifier les t exécutions du protocole d’authentification.
Pour qu’une personne soit capable de forger une signature, il faudrait qu’elle arrive à calculer les bonnes réponses
sans connaı̂tre la clé privée du signataire : cela revient à casser toutes les exécutions du protocole d’authentification
zero knowledge pour les t exécutions en même temps (si nous faisions le protocole tour par tour, la sécurité serait
grandement impactée car il n’y aurait plus qu’à casser les tours indépendamment les uns des autres).
Par exemple, sur Fiat-Shamir nous aurons t = 128 tours, n = 2048 bits (pour chaque Ei et Ri ), la taille de la signature
sera donc de n × t = 2048 × 128 = 262144 bits ce qui équivaut à 65536 octets, la taille de la clé publique sera elle de
2 × 2048 = 4096 bits ce qui nous donne 512 octets pour la version Fiat-Shamir sur le résidu quadratique et 256 octets
pour la version Fiat-Shamir sur le logarithme discret.
7 Courbes elliptiques :
7.1 Introduction :
Une courbe elliptique est tout simplement définie par la relation suivante :
y 2 = x3 + a × x + b
Voici, ci-dessous 2 exemples de courbes elliptiques pour certaines valeurs de a et b :
Il existe une formule plus générale pour les courbes elliptiques qui est l’équation de Weierstras :
y 2 + a1 × xy + a3 × y = x3 + a2 × x2 + a4 × x + a6
2 autres cas particuliers peuvent se produire : si P = Q, à ce moment là nous ferons un doublement : 2P = P + P et
il faudra prendre la tangente à la courbe au point P , si Q = −P nous aurons comme résultat le point à l’infini (qui
est le neutre pour l’additions sur les courbes elliptiques) :
Nous pouvons maintenant calculer les additions dans les différents cas.
Le cas le plus simple est le cas où nous faisons P + −P ce qui nous permet d’obtenir le point à l’infini : 0.
Pour les autres cas nous chercherons les points qui vérifient à la fois y 2 = x3 + a × x + b et y = a′ × x + b′ . Nous
pouvons injecter la seconde relation dans la première pour obtenir :
(a′ × x + b′ )2 = x3 + a × x + b ⇔ x3 − a′2 × x2 + (a − 2 × a′ × b′ ) × x + b − b′2 = 0
Addition : P + Q : nous allons commencer par trouver l’équation de la droite passant par ces 2 points : le coeffi-
cient directeur de cette droite est donné par a′ = (Q.y − P.y)/(Q.x − P.x) et l’ordonnée à l’origine de cette droite
est b′ = P.y − a′ × P.x. Nous n’avons donc plus qu’à résoudre l’équation cubique qui a été donnée précédemment,
cela semble très dur à première vue, mais souvenez vous que nous avons 2 solutions à cette équation : P et Q qui
appartiennent à la fois à la droite et à la courbe elliptique. Donc :
x3 − a′2 × x2 + (a − 2 × a′ × b′ ) × x + b − b′2 = (x − P.x)(x − Q.x)(x − R.x)
⇔ x3 + k1 × x2 + k2 × x + k3 = x3 − (P.x + Q.x + R.x) × x2 + (P.x × Q.x + P.x × R.x + Q.x × R.x) × x − P.x × Q.x × R.x
1=1
k = −a′2 = −(P.x + Q.x + R.x)
1
⇔
k2 = a − 2 × a′ × b′ = P.x × Q.x + P.x × R.x + Q.x × R.x
k3 = b − b′2 = P.x × Q.x × R.x
Or nous n’avons besoin que d’une seule de ces équations pour trouver R.x, prenons donc la plus simple : a′2 =
P.x + Q.x + R.x et donc :
2
′2 Q.y − P.y
R.x = a − P.x − Q.x = − P.x − Q.x
Q.x − P.x
Pour trouver le R.y, il suffit d’appliquer la formule de la fonction affine à ce point :
R.y = a′ × R.x + b′ = a′ × R.x − a′ × P.x + P.y = a′ × (R.x − P.x) + P.y
√
Doublement
√ : 2P = P + P : nous pouvons dire que y = f (x) = x3 + a × x + b et donc f ′ (x) = (3x2 + a)/(2 ×
x3 + ax + b) = (3x2 + a)/2y qui est la formule du nombre dérivé et nous permettra de trouver le coefficient directeur
de la droite représentant la tangente. Nous savons donc que a′ = (3 × P.x2 + a)/(2 × P.y) et nous pouvons prendre
b′ = P.y − a′ × P.x.
En utilisant les mêmes techniques que précédemment, nous pouvons montrer que R.x = a′2 − 2 × P.x et R.y =
a′ × (R.x − P.x) + P.y.
Vu que nous sommes sur les entiers, nous n’aurons plus une courbe mais plutôt un ensemble de points qui vérifient
l’équation donnée au départ. Voici un exemple avec y 2 = x3 − 6x + 7 (mod 113) :
Nous allons également avoir besoin de parler de la caractéristique d’un corps : c’est le nombre de fois qu’il faut
ajouter l’élément neutre de la multiplication pour avoir celui de l’addition, il s’agit du plus petit c non nul tel que
pour tout k dans l’ensemble nous avons k × c = 0. Dans Z/pZ, nous avons que la caractéristique est égale à p. Un
autre exemple serait dans Z/(p × q)Z où la caractéristique est min(p, q).
Ensuite, le prof a parlé de la simplification de départ : y 2 + a1 × xy + a3 × y = x3 + a2 × x2 + a4 × x + a6 (mod p) :
Si Car(K) = 3 : on s’en fout.
Si Car(K) = 2 (cas GF (2q )) :
Si a1 ̸= 0, alors (x, y) → (a21 × x + a3 /a1 , a31 × y + (a21 × a4 + a23 )/a31 ) et l’équation devient de la forme
y 2 + xy = x3 + a × x2 + b (cas non super-singulier).
Si a1 = 0, alors (x, y) = (x + a2 , y) et l’équation devient de la forme y 2 + c × y = x3 + a × x + b (cas
super-singulier).
Si Car(K) ̸= 2 et Car(K) ̸= 3 : nous pouvons prendre (x, y) → ((x − 3 × a21 − 12 × a2 )/36, (y − 3 × a1 × x)/216 −
(a31 + 4 × a1 × a2 − 12 × a3 )/24). La forme simplifiée deviendra la forme usuelle : y 2 = x3 + a × x + b. En fait il
faut que la caractéristique soit différente de 2 et 3 car les constantes aux dénominateurs sont des multiples de
ces 2 nombres et donc nous pourrions diviser par 0.
En remarque finale, notez que le nombre de courbes elliptiques de la forme y 2 = x3 + a × x + b sur le corps Fq à q
éléments est q 2 car nous pouvons prendre tous les couples possibles pour les valeurs de a et b et ces dernières doivent
être des éléments de Fq .
Une première façon de trouver tous les points consiste à prendre tous les couples possibles et vérifier s’ils vérifient
l’équation, voici ce que cela donnerait pour la fonction f1 :
x\y 0 1 2 3 4
0 02 = 0 ̸= 2 = 03 + 0 + 2 : ∈
/ 1 ̸= 2 : ∈
/ 4 ̸= 2 : ∈
/ 4 ̸= 2 : ∈
/ 1 ̸= 2 : ∈
/
1 02 = 0 ̸= 4 = 13 + 1 + 2 : ∈
/ 1 ̸= 4 : ∈
/ 4=4 : ∈ 4=4 : ∈ 1 ̸= 4 : ∈
/
2 3
2 0 = 0 ̸= 2 = 2 + 2 + 2 : ∈ / 1 ̸= 2 : ∈
/ 4 ̸= 2 : ∈
/ 4 ̸= 2 : ∈
/ 1 ̸= 2 : ∈
/
3 02 = 0 ̸= 2 = 33 + 3 + 2 : ∈
/ 1 ̸= 2 : ∈
/ 4 ̸= 2 : ∈
/ 4 ̸= 2 : ∈
/ 1 ̸= 2 : ∈
/
4 02 = 0 = 0 = 43 + 4 + 2 : ∈ 1 ̸= 0 : ∈/ 4 ̸= 0 : ∈
/ 4 ̸= 0 : ∈
/ 1 ̸= 0 : ∈
/
Cette courbe possède donc 4 points : (1, 2), (1, 3), (4, 0) ainsi que le point à l’infini.
Il existe une méthode un peu plus rapide, elle pourrait être qualifiée de méthode par ”meet in the middle”, appliquons
là sur f2 . Nous allons commencer par voir les différentes valeurs que peut prendre y 2 :
y 0 1 2 3 4
y2 0 1 4 4 1
Et ensuite, nous allons également calculer toutes les différentes valeurs de x3 + a × x + b :
x 0 1 2 3 4
x3 + 1 × x + 0 0 2 0 0 3
Nous allons ensuite regarder les endroits où nous avons la même valeur : nous avons 3 valeurs de x qui donnent 0 et
une valeur de y qui donne 0 ce qui nous donne 3 points. Pour les valeurs de x où nous avons 2 et 3, elles n’apparaissent
pas dans les résultats de y 2 et donc elles ne donnent aucun point. Finalement, nous avons 4 points pour cette courbe
également : (0, 0), (2, 0), (3, 0) et encore une fois le point à l’infini.
En remarque finale, nous pouvons essayer de trouver des bornes sur le nombre de points d’une courbe. Tout d’abord
une approximation naı̈ve : le nombre minimum de points est forcément 1 car toute courbe elliptique contient le point
à l’infini, le nombre maximum de points est lui donné par q 2 (si la courbe est sur un corps à q éléments) car x et y
peuvent chacun prendre q valeurs différentes.
Le théorème de Hasse donne des bornes bien meilleures : soit E(K) une courbe elliptique sur K = Fq , alors le
nombre de points de la courbe est compris entre les bornes suivantes :
√ √
q + 1 − 2 × q <= #E(Fq ) <= q + 1 + 2 × q
La valeur t = #E(Fq ) − q − 1 sera appelée la trace de la courbe.
Pour notre exemple, ce théorème prévoit que le nombre de points minimal est 1.54 (ce qui donne une borne min à 2)
et le nombre de points maximal est 10.46 (ce qui donne une borne max à 10) : tous les exemples que nous avons fait
sont confirmés par la théorie et nous avons même une courbe qui atteint le nombre minimal de points et une courbe
qui atteint le nombre maximal.
8.2 Morphismes :
Un morphisme est une application d’une structure algébrique vers une autre structure algébrique de même type.
Il en existe plusieurs types :
Endomorphisme : application dont la structure algébrique source et celle but sont identiques. Par exemple, un
endomorphisme d’ensembles serait f : E → E, un endomorphisme de groupes pourrait être f : (G, ⋆) → (G, ⋆).
Monomorphisme : associé à la notion de fonction injective dans les ensembles.
Épimorphisme : associé à la notion de fonction surjective dans les ensembles.
Isomorphisme : associé à la notion de fonction bijective, d’ailleurs lorsque 2 structures sont isomorphes nous
pouvons considérer qu’elles sont ”identiques”.
Automorphisme : il s’agit tout simplement de la combinaison d’un endomorphisme et d’un isomorphisme.
Nous pouvons également définir des produits cartésiens de l’ensemble précédent, par exemple (Z2 ⊕ Z2 , +) :
a+b (0, 0) (0, 1) (1, 0) (1, 1)
(0, 0) (0, 0) (0, 1) (1, 0) (1, 1)
(0, 1) (0, 1) (0, 0) (1, 1) (1, 0)
(1, 0) (1, 0) (1, 1) (0, 0) (0, 1)
(1, 1) (1, 1) (1, 0) (0, 1) (0, 0)
Ce genre de groupe sera particulièrement utile pour étudier la structure des courbes elliptiques, nous en reparlerons
plus loin. D’ailleurs notez que le groupe (Z1 ⊕ Zn , +) est isomorphe au groupe (Zn , +).
Imaginons une courbe à 4 points, les seules possibilités sont donc : 1 × 4 car 1 divise 4 et 1 divise 5 − 1 = 4 ainsi que
2 × 2 qui est également possible car 2 divise 2 et 2 divise 5 − 1 = 4.
Nous allons chercher à savoir auquel de ces 2 groupes cette courbe elliptique est isomorphe. Vu que dans le premier cas
nous savons que le groupe résultant est cyclique (possède un générateur) et dans le seond cas non, nous avons juste à
cherher un générateur : si nous en trouvons un nous serons dans le cas 1 × 4, et si nous n’en trouvons pas nous serons
dans le cas 2 × 2.
La seule façon de faire pour répondre à cette question est de tester tous les points. Nous avons 2 axes pour simplifier
cette recherche et avoir moins de points à chercher :
Nous savons que le nombre de générateurs s’il y en a sera φ(4) = 2 : cela veut dire que si nous avons déjà testé
3 points et qu’aucun n’est un générateur, pas besoin de tester le quatrième.
Nous savons que l’ordre de chaque élément est un diviseur du nombre d’éléments du groupe, nous n’aurons
donc qu’à tester les valeurs de 1P , 2P et 4P pour voir si l’une d’entre elles est le neutre (le point à l’infini).
D’ailleurs, nous pouvons encore simplifier : si ni 1P ni 2P ne sont le point à l’infini, alors nous sommes forcément
en présence d’un générateur car obligatoirement 4P sera le point à l’infini.
Nous allons donc ré-étudier les courbes pour lesquelles nous avions trouvé les points.
f2 : y 2 = x3 + x : 4 points : (0, 0), (2, 0), (3, 0), 0 : vous voyez tout de suite que ce groupe ne possède pas de générateur
car le doublement de chaque nombre donne le point à l’infini. La structure n’est donc pas Z1 ⊕ Z4 mais Z2 ⊕ Z2 qui
montre les mêmes caractéristiques : le doublement de chaque élément donne le neutre.
f4 : y 2 = x3 + 3x : 10 points : (0, 0), (1, 2), (1, 3), (2, 2), (2, 3), (3, 1), (3, 4), (4, 1), (4, 4), 0 : la seule possibilité est 1 × 10,
2 × 5 n’est pas possible car 2 ne divise pas 5.
f1′ : y 2 = x3 + 4x : ici nous n’avons pas les points, il faut les re-calculer comme nous l’avions fait dans une par-
tie avant. Après ce calcul nous pouvons trouver 8 points : (0, 0), (1, 0), (2, 1), (2, 4), (3, 2), (3, 3), (4, 0), 0 :
Les 2 possibilités sont 1 × 8 et 2 × 4.
Le nombre de générateurs s’il y en a est φ(8) = 4, les multiples à tester sont 1P, 2P, 4P .
0, (0, 0), (1, 0), (4, 0) ont tous soit un ordre de 1 soit de 2, ce ne sont donc forcément pas des générateurs.
(2, 1) : 2 × (2, 1) = (0, 0) : ce n’est donc pas un générateur car 4 × (2, 1) = 0.
Il devait y avoir 4 générateurs, parmi les 8 points 5 n’en sont pas, donc ce groupe est isomorphe à (Z2 ⊕ Z4 , +).
f2′ : y 2 = x3 +4x+1 : encore une fois il faut re-calculer les points qui sont également au nombre de 8 : (0, 1), (0, 4), (1, 1),
(1, 4), (3, 0), (4, 1), (4, 4), 0 :
Les 2 possibilités sont 1 × 8 et 2 × 4.
Le nombre de générateurs s’il y en a est φ(8) = 4, les multiples à tester sont 1P, 2P, 4P .
0, (3, 0) ont soit un ordre de 1 soit de 2, ce ne sont donc forcément pas des générateurs.
(0, 1) : 2 × (0, 1) = (4, 1), 4 × (0, 1) = 2 × (4, 1) = (3, 0) : nous voyons que 1P ̸= 0, 2P ̸= 0 et 4P ̸= 0 donc
forcément 8P = 0 et nous avons un générateur.
Donc le groupe pour cette courbe elliptique est isomorphe à (Z1 ⊕ Z8 , +) et donc à (Z8 , +) et possède 4 générateurs.
Nous allons cette fois-ci faire un exemple avec les 3 courbes suivantes (toutes modulo 37) :
y 2 = x3 + 21 ∗ x + 10 : (15, 0), (13, 1), (30, 1), (31, 1), (18, 2), (19, 4), (36, 5), (10, 6), (3, 10), (17, 10), (0, 11),
(4, 11), (33, 11), (29, 12), (27, 13), (9, 15), (35, 16), (25, 18), (25, 19), (35, 21), (9, 22), (27, 24), (29, 25), (0,
26), (4, 26), (33, 26), (3, 27), (17, 27), (10, 31), (36, 32), (19, 33), (18, 35), (13, 36), (30, 36), (31, 36), 0.
y 2 = x3 + 13 ∗ x + 32 : (4, 0), (5, 0), (28, 0), (26, 1), (20, 2), (1, 3), (27, 7), (9, 8), (32, 8), (33, 8), (16, 9), (11,
10), (34, 15), (19, 16), (24, 16), (31, 16), (6, 17), (13, 17), (18, 17), (6, 20), (13, 20), (18, 20), (19, 21), (24, 21),
(31, 21), (34, 22), (11, 27), (16, 28), (9, 29), (32, 29), (33, 29), (27, 30), (1, 34), (20, 35), (26, 36), 0.
y 2 = x3 + 36 ∗ x + 27 : (16, 0), (12, 2), (29, 2), (33, 2), (5, 6), (27, 6), (0, 8), (1, 8), (36, 8), (9, 9), (24, 10), (28,
11), (2, 12), (35, 13), (34, 15), (22, 16), (7, 17), (13, 18), (13, 19), (7, 20), (22, 21), (34, 22), (35, 24), (2, 25),
(28, 26), (24, 27), (9, 28), (0, 29), (1, 29), (36, 29), (5, 31), (27, 31), (12, 35), (29, 35), (33, 35), 0.
Ces 3 courbes possèdent chacune 36 points (il semble que ce soit le nombre de points minimum pour avoir plus de 2
possibilités), nous aurons donc à chaque fois 4 possibilités :
n2 × n1 = 1 × 36 (possède φ(36) = 12 générateurs)
n2 × n1 = 2 × 18 (ne possède aucun générateur)
n2 × n1 = 3 × 12 (ne possède aucun générateur)
n2 × n1 = 6 × 6 (ne possède aucun générateur)
Vu que le nombre d’éléments pour chaque courbe est 36, l’ordre de chaque élément peut être un des diviseurs de 36 :
1, 2, 3, 4, 6, 9, 12, 18, 36.
Si l’on sait que le nombre d’éléments de la courbe, noté #E(Fq ) = p avec p un nombre premier, nous avons forcément
que n2 × n1 = 1 × p = p ce qui nous donnera forcément un groupe cyclique.
Sur les courbes elliptiques (et contrairement aux entiers modulo p) il n’y a que l’addition : nous n’ajoutons donc
√
pas de structure inutile et du coup les meilleures attaques sont en O( q) alors que pour le logarithme discret c’est
√
plutôt en 2α× n×log(n) . Voici un tableau pour comparer le nombre de bits de clé qu’il faut dans les 2 cas pour obtenir
un certain niveau de sécurité :
Sécurité Nombre de bits RSA Nombre de bits ECC
280 1024 160
2112 2048 224
128
2 3072 256
2196 7680 392
2256 15360 512
Comme vous pouvez le voir les tailles de clés sont plus petites sur les courbes elliptiques (dû au fait que la meilleure
√
attaque est en O( q)) mais le coût de calcul est plus grand : pour faire une addition sur les courbes elliptiques il faut
10 multiplications sur Fq alors que pour faire a × b sur Fq il n’y a qu’une seule multiplication à faire.
La question est d’où vient ce ”10 multiplications” : si nous nous intéressons à la formule pour faire l’addition de 2
points nous pouvons remarquer un inverse modulaire, dont nous considèrerons qu’il prendra 80 multiplications. Les
10 multiplications précédentes sont obtenues en changeant la façon de les additions de points sont réalisées.
La solution que nous avons évoquée juste avant se base sur un système de coordonnées modifié :
Affine : c’est la représentation que nous avons actuellement avec le point (x, y).
Projectives : nous associerons au point (x, y) le point (λ × x, λ × y, λ). Soit maintenant un point (x, y, z) pour
revenir en arrière il suffit de calculer (x/z, y/z) (il faut donc que z ne soit pas nul).
Jacobiennes : nous associerons au point (x, y) le point (λ2 × x, λ3 × y, λ). Soit le point (x, y, z), nous pourrons
revenir en arrière en calculant (x/z 2 , y/z 3 ).
De manière générale, nous associerons le point (x, y) au point (λc × x, λd × y, λ) et pour revenir en arrière il suffira de
calculer (x/z c , y/z d ). Ensuite, chaque couple (c, d) donne son nom a un certain système de coordonnées : pour (1, 1)
nous aurons les coordonnées projectives et pour (2, 3) nous aurons les coordonnées jacobiennes.
Pour les coordonnées projectives, il suffit de remplacer dans l’équation chaque x par X/Z 2 et chaque y par Y /Z 3 et
tout multiplier par z 6 ce qui nous donne comme nouvelle équation : Y 2 = X 3 + a × X × Z 4 + b × Z 6 .
L’intérêt est qu’il n’y a plus d’inverse modulaire, et il reste environ 10 multiplications.
Tout d’abord, nous allons montrer que si nous connaissons les 2 couples de valeurs, nous pouvons retrouver x :
c1 × P + d1 × Q = c2 × P + d2 × Q
c1 × P + d1 × x × P = c2 × P + d2 × x × P
((c1 − c2 ) − x × (d2 − d1 )) × P = 0
(c1 − c2 ) − x × (d2 − d1 ) = 0 (mod n) (rappel : n : l’ordre du groupe engendré par P )
x = (c1 − c2 )/(d2 − d1 ) (mod n)
Un autre programme pour trouver toutes les courbes elliptiques avec un certain nombre de points :
1 def trouverCourbe ( nombrePoints , n ) :
2 for a in range (0 , n ) :
3 for b in range (0 , n ) :
4 if len ( trouverPoints (a , b , n ) ) == nombrePoints :
5 print ( " y ^2 = x ^3 + " + str ( a ) + " * x + " + str ( b ) )
Voici un autre programme pour faire l’addition de 2 points et le doublement d’un point :
1 def addition ( point1 , point2 , mod ) :
2 try :
3 coefficient = ( point2 [1] - point1 [1]) * pow ( point2 [0] - point1 [0] , -1 , mod )
4 except :
5 return 0
6 x3 = ( coefficient * coefficient - point1 [0] - point2 [0]) % mod
7 y3 = ( coefficient * ( point1 [0] - x3 ) - point1 [1]) % mod
8 x3 = x3 + mod if x3 < 0 else x3
9 y3 = y3 + mod if y3 < 0 else y3
10 return ( x3 , y3 )
11
12 def doublement ( point , mod , a ) :
13 try :
14 coefficient = (3 * point [0] * point [0] + a ) * pow (2 * point [1] , -1 , mod )
15 except :
16 return 0
17 x3 = ( coefficient * coefficient - 2 * point [0]) % mod
18 y3 = ( coefficient * ( point [0] - x3 ) - point [1]) % mod
19 x3 = x3 + mod if x3 < 0 else x3
20 y3 = y3 + mod if y3 < 0 else y3
21 return ( x3 , y3 )
Et pour finir, une dernière fonction pour trouver l’ordre d’un point de la courbe :
1 def ordre ( point1 , mod , a ) :
2 if point1 == 0 :
3 return 1
4 ordre = 2
5 pointCourant = doublement ( point1 , mod , a )
6 while pointCourant != 0 :
7 pointCourant = addition ( pointCourant , point1 , mod )
8 ordre += 1
9 return ordre
L’exemple de cas facile correspond au cas où les si forment une suite hypercroissante, c’est à dire une suite dans
laquelle le terme n est strictement supérieur à la somme de tous les précédents. Un exemple de suite hypercroissante
(et même il s’agit de la plus ”petite” possible) sont les puissances de 2 : nous savons que 2k −1 = 2k−1 +2k−2 +...+21 +20 ,
2k est donc strictement supérieur à la somme des puissances de 2 avant.
L’idée pour le résoudre dans ce cas là est très simple, pour en donner l’exemple on va se placer dans le cadre des
puissances de 2. Vous savez qu’étant donné un nombre en base 10, une possibilité pour le convertir en base 2 est de
prendre les puissances de 2 de la plus grande à la plus petite, voir si le nombre est supérieur ou égal à cette dernière,
si oui mettre un 1 et faire la soustraction, sinon mettre un 0. Par exemple pour 123 : nous allons commencer par
soustraire 64 (59), puis 32 (27), puis 16 (11), puis 8 (3), puis 2 (1), puis 1 (0). Eh bien cette stratégie est équivalente
à la résolution du problème avec si = 2i , et un objet sera pris si le bit associé est à 1 !
Donc la résolution pour une suite hypercroissante consiste à trier les si par ordre croissant, on part donc de sk s’il est
plus petit que N on le prend et on enlève sk à N sinon on ne le prend pas, et on continue ainsi de suite jusqu’à s1 .
Voici un code qui permet de générer des clés, faire du chiffrement et du déchiffrement :
1 import random
2 import math
3
4 def keyGeneration ( n ) :
5 a = []
6 sommeActuelle = 0
7 for i in range (0 , n ) :
8 a . append ( random . randint ( max ( sommeActuelle + 1 , 2 ** ( n + i - 1) ) , 2 ** ( n + i ) - 1) )
9 sommeActuelle += a [ -1]
10 N = random . randint ( sommeActuelle , 2 ** (2 * n ) - 1)
11 A = 0
12 while A == 0 or math . gcd (A , N ) != 1 :
13 A = random . randint (2 , N - 2)
14
15 b = [ ( a [ i ] * A ) % N for i in range (0 , len ( a ) ) ]
16 return [ b , [ A , N , a ] ]
17
18 def encrypt ( messageBits , b ) :
19 result = 0
20 for i in range (0 , len ( messageBits ) ) :
21 if messageBits [ i ] == ’1 ’ :
22 result += b [ i ]
23 return result
24
25 def decrypt ( encryptedNumber , A , N , a ) :
26 # Find the inverse of A and getting the new number
27 Ainv = pow (A , -1 , N )
28 newNumber = ( e n cr yp te d Nu mb er * Ainv ) % N
29
30 # Getting the different bits
31 messageBits = []
32 for i in range (0 , len ( a ) ) :
33 if newNumber >= a [ len ( a ) - i - 1] :
34 newNumber -= a [ len ( a ) - i - 1]
35 messageBits = [ " 1 " ] + messageBits
36 else :
37 messageBits = [ " 0 " ] + messageBits
38 return " " . join ( messageBits )
Une première idée d’attaque sur le protocole serait de tester toutes les possibilités de N et de A et ne garder que celles
qui lorsqu’elles sont utilisées avec les bi donnent une séquence hypercroissante. Voici le code qui implémenterait cette
attaque :
1 import math
2
3 b = ...
4 powsOf2 = []
5 for i in range (0 , 2 * len ( b ) + 1) :
6 powsOf2 . append (2 ** i )
7 longueurB = len ( b )
8 maxN = powsOf2 [2 * longueurB ]
9
10 listeCles = []
11 startN = max ( maxN // 2 , max ( b ) + 1) # Start at max ( b ) because b_i < N for any i
12 for N in range ( startN , maxN ) :
13 for Ainv in range (1 , N ) :
14 if math . gcd (N , Ainv ) != 1 :
15 continue
16 ok = True
17 sommeCourante = 0
18 for i in range (0 , longueurB ) :
19 borneMin = max ( sommeCourante + 1 , powsOf2 [ longueurB + i - 1])
20 borneMax = powsOf2 [ longueurB + i ]
21 ai = ( b [ i ] * Ainv ) % N
22 if ai < borneMin or ai >= borneMax :
23 ok = False
24 break
25 sommeCourante += ai
26 if ok :
27 listeCles . append ([ pow ( Ainv , -1 , N ) , N ])
28
29 print ( " Nombre de cles possibles : " + str ( len ( listeCles ) ) )
30 print ( " Cles possibles : " + str ( listeCles ) )
Prenons donc par exemple la clé consituée de a = {13, 24, 62, 108}, A = 61, N = 226, nous avons donc b =
{115, 108, 166, 34}. Nous allons maintenant supposer que nous ne connaissons ni a, ni A, ni N et nous allons tes-
ter plusieurs valeurs de A et de N pour voir si nous obtenons une suite hypercroissante :
A = 123, N = 212 : donc A−1 = 131 et nous avons a′i = {(115 × 131) (mod 212) = 13, 156, 122, 2} qui n’est
pas hypercroissante.
A = 140, N = 201 : donc A−1 = 56 et nous avons a′i = {8, 18, 50, 95} qui est hypercroissante c’est donc une clé
possible.
A = 61, N = 226 : donc A−1 = 63 et nous avons a′i = {13, 24, 62, 108} qui est une autre clé possible.
Pour déterminer quelle clé est la bonne, une attaque à texte clair connu pourra aider à éliminer des couples.
Pour n = 4, il reste en moyenne 5 clés et pour n = 5 c’est 6. Le seul problème est le temps d’exécution exponentiel
qui dépend d’environ 24n (22n−1 valeurs de N possibles et 22n valeurs de A possibles).
Une autre attaque en temps polynomial a été décrite par Shamir en 1984, je vais en faire une courte introduction ici
et je n’irais pas en profondeur car elle demande de connaı̂tre des concepts comme l’algorithme de Lenstra, ...
Imaginons dans un premier temps que nous connaissions la valeur de N , et que nous souhaitions trouver A (nous allons
plutôt trouver B = A−1 (mod N ). L’idée va être de dire que 2n−1 <= B × b0 (mod N ) = a0 < 2n , 2n <= B × b1
(mod N ) = b1 < 2n+1 , ... : nous obtenons donc de l’information sur A grâce à toutes ces équations.
Affichons maintenant la fonction B ′ × b0 (mod N ) et affichons également la condition sur b0 :
Vous pouvez donc voir que B ′ n’est valide que dans certains intervalles et il est possible de combiner plusieurs
observations pour affiner la valeur de B ′ (c’est un peu le même principe qu’avant).
Leur idée pour enlever la valeur de N est de tout diviser par N , ce qui donne un nouveau graphe qui parcourira toutes
les valeurs de V = B ′ /N et donnera des intervalles de validité de V :
Dans la suite du document, ils semblent prendre une approche dans laquelle ils tracent les 4 fonctions associées aux 4
bi (car ils ont montré que dans notre cas, 4 valeurs sont suffisantes) et trouvent un point où les minimum de toutes
ces fonctions sont très proches.
Une idée simple (très mauvaise et qui ne change rien en temps) est de faire comme pour la méthode brute force :
prendre toutes les valeurs possibles de N , calculer tous les intervalles dans lesquels B ′ peut être et voir si l’un d’entre
eux contient un entier (qui sera une valeur de B ′ possible pour la valeur de N associée). L’efficacité sera au mieux la
même voire pire que la méthode brute force.
9.2 Les lattices (j’ai une partie plus détaillée plus bas) :
Un réseau est un sous-groupe additif de Zn de dimension n. Il est défini par une base de vecteurs éléments de Zn qui
seront placés dans une matrice à n lignes et n colonnes en ligne :
→
−
v1
B = ···
−
v→
n
Le réseau est constitué de l’ensemble des combinaisons linéaires à coefficients entiers des vecteurs de la base.
Un code binaire lui sera défini par une matrice dans F2 .
Pour les codes, c’est la distance de Hamming qui nous donne le poids égal au nombre de coordonnées non-nulles mais
cette métrique n’est utile que lorsqu’on travaille sur F2 . Sur les lattices, on utilisera plutôt la norme euclidienne (qui
est la racine carrée de la somme des carrés des coordonnées).
Sur les lattices, on a également un problème de décodage : on envoie y = x × B + e avec e une erreur dont la distance
à un vecteur de la lattice n’excède pas une certaine distance maximale (le décodé sera le vecteur du réseau le plus
proche).
Il y a aussi un problème de réduction de la base que je présente plus en détail sur la partie que j’ai réalisée.
Tous ces problèmes demandent un factuer d’approximation, si ce dernier est plus qu’une certaine limite le problème
peut être résolu en temps polynomial dans le cas contraire la complexxité sera exponentielle.
Pour le chiffrement, nous convertirons notre message en v un vecteur à l éléments tous modulo t. Il suffira ensuite de
choisir un vecteur a aléatoire à n valeurs toutes générées aléatoirement et uniformément entre −r et r.
Nous avons également une fonction f de Zt vers Zq qui a i associe i × q/t.
La première partie du chiffré est u = At × a.
La seconde partie du chiffré est c = P t × a + f (v).
La sécurité du cryptosystème repose sur l’indistinguabilité de quelque aléatoire. Si on casse McEliece, on aura cassé
un problème spécifique alors que si on casse LWE on aura cassé un problème général.
Un pairing est une construction générale qui se base sur une application bilinéaire :
e : G1 × G1 → G2 .
Elle vérifie 2 propriétés :
Bilinéarité : pour tous P, Q ∈ G1 , pour tous a, b ∈ Z∗q , on a que e(aP, bQ) = ab × e(P, Q)
Non-dégénérescence : pour tout P ∈ G1 , si P ̸= 0, alors G2 =< e(P, P ) >
Du coup, 2 points d’une courbe elliptique peuvent intéragir pour donner un point d’une autre courbe avec la propriété
de bilinéarité.
C’est une notion qui a tout d’abord été utilisée pour les attaques sur les courbes elliptiques.
Concrètement, il existe plusieurs types de couplage : couplage de Weil et de Tate à base de courbes elliptiques, ce qui
ne marche qu’avec des courbes spécifiques.
Un théorème très important : le problème du logarithme discret sur G1 n’est pas plus dur que celui sur G2 (si je
sais résoudre le problème sur G2, je sais le résoudre sur G1).
Démonstartion : soit P1 le générateur de G1 et nous connaissons y = a × P1 mais nous voulons trouver a. L’idée est
de calculer e(aP, P ) = a × e(P, P ) = a × P2 : donc si on sait résoudre sur G2 on peut retrouver a et donc on peut
résoudre sur G1 .
Un autre théorème très important : le problème DDH est facile si nous avons un couplage :
Pour le problème DDH, on va nous donner soit ab × P ou c × P et on connaı̂t aP et bP .
e(aP, bP ) = e(P, P )ab
e(P, Q) = e(P, P )ab mais seulement si Q = ab × P , il vaudra autre chose si Q = cP : du coup on peut distinguer les 2
et casser le problème DDH !
Un premier exemple de protocole est un échange de clé tripartite par Antoine Joux en 2000 :
L’idée est que A va connaı̂tre a et il aura reçu bP et cP , il va donc pouvoir calculer a × e(bP, cP ) = abc × e(P, P )
Pour additionner (soustraire) 2 matrices, il faut additionner (soutraire) leurs coefficients terme à terme,cette opération
n’est donc possible que si les 2 matrices ont les mêmes dimensions. Voici la règle :
a1,1 a1,2 · · · a1,n b1,1 b1,2 · · · b1,n a1,1 + b1,1 a1,2 + b1,2 · · · a1,n + b1,n
a2,1 a2,2 · · · a2,n b2,1 b2,2 · · · b2,n a2,1 + b2,1 a2,2 + b2,2 · · · a2,n + b2,n
A+B = . + =
.. .. .. .. .. .. .. .. .. .. ..
..
. . . . . . . . . . .
am,1 am,2 ··· am,n bm,1 bm,2 ··· bm,n am,1 + bm,1 am,2 + bm,2 ··· am,n + bm,n
Pour multiplier 2 matrices entre elles, il faudra réaliser le produit scalaire de toutes les lignes de la première par toutes
les colonnes de la seconde. L’opération n’est donc possible que si la seconde matrice a autant de lignes que la première
a de colonnes. Voici la règle :
−→ −→ − −→ −−→
a1,. · b.,1 a→
1,. · b.,2 ··· − a→
1,. · b.,n2
a1,1 a1,2 · · · a1,n1 b1,1 b1,2 · · · b1,n2
−→ −→ − −→ −−→
a2,1 a2,2 · · · a2,n1 b2,1
b2,2 · · · b2,n2 a2,. · b.,1 a→
2,. · b.,2 ··· − a→
2,. · b.,n2
A×B = . × =
.. .. .. .. .. .. .. .. .. .. ..
.. . . . . . . . . . . .
am1 ,1 am1 ,2 · · · am1 ,n1 bm2 ,1 bm2 ,2 · · · bm2 ,n2 −−−→ −→ −−−→ −→ −−−→ −−→
am ,. · b.,1 am ,. · b.,2 · · · am ,. · b.,n
2 2 2 2
Avant de passer à l’inverse d’une matrice, voyons comment calculer le déterminant de n’importe quelle matrice.
Il peut être défini par récurrence :
Le déterminant d’une matrice 1 x 1 sera le seul élément de cette matrice |a| = a
Soit A une matrice n × n, on pourra prendra n’importe quelle ligne i puis développer le déterminant sur cette
ligne en prenant tous les coefficients ai,j et en calculant le déterminant de A à laquelle on aura retiré la ligne i
et la colonne j (il est aussi possible de le faire en suivant une colonne).
Voici comment on pourrait noter la relation de récurrence :
a b c
d f a c a c
d e f = −b × +e× −h×
g i g i d f
g h i
Pour finir, l’inverse de la matrice A de dimensions n × n sera donné par (AT est la transposée de A) :
T
(−1)1+1 det(A1,1 ) (−1)1+2 det(A1,2 ) (−1)1+n det(A1,n )
···
1 1 1 (−1)2+1 det(A2,1 ) (−1)2+2 det(A2,2 ) ··· (−1)2+n det(A2,n )
A−1 = ×adj(A) = T
×com(A) = ×
.. .. .. ..
det(A) det(A) det(A)
. . . .
(−1)n+1 det(An,1 ) (−1)n+2 det(An,2 ) · · · (−1)n+n det(An,n )
Terminons par la multiplication par un vecteur : si ce dernier est représenté en ligne, la multiplication se fera avec
le vecteur à gauche, en revanche s’il est représenté en colonne la multiplication se fera avec le vecteur à droite de la
matrice.
Une matrice peut également être représentée par une liste de vecteurs lignes ou une liste de vecteurs colonnes.
Définition : un espace vectoriel est un ensemble dont les éléments se comportement comme des vecteurs, cela veut dire
que l’on peut les additionner (la condition est que le résultat de l’addition soit toujours un élément de l’EV) et les
multiplier par un scalaire (le résultat doit être un élément de l’EV). Vous pouvez les voir comme un groupe commutatif
avec une relation supplémentaire qui permet de réaliser des combinaisons linéaires de ses éléments.
Exemple 1 : l’ensemble des réels R forme un espace vectoriel.
Exemple 2 : l’ensemble R2 (toutes les paires d’éléments de R) forme un espace vectoriel.
Exemple 3 : l’ensemble E = {(x, y) ∈ R2 |x + y = 0} forme un sous-espace vectoriel de R2 :
(0, 0) est bien un élément de E.
Soient (x, y) ∈ E et (x′ , y ′ ) ∈ E, (x, y) + (x′ , y ′ ) = (x + x′ , y + y ′ ) pour lequel on a que x + x′ + y + y ′ =
x + y + x′ + y ′ = 0 + 0 = 0 ce qui montre que nous avons encore une fois un élément de l’ensemble.
Soit (x, y) ∈ E et k ∈ R, k × (x, y) = (k × x, k × y) pour lequel on a que k × x + k × y = k × (x + y) = k × 0 = 0
qui est encore un élément de l’ensemble.
Pour tester si un ensemble E est un espace vectoriel (sur les réels), il faudra toujours vérifier les 3 règles décrites.
Avant de parler de base, définissons ce qu’est une famille de vecteurs linéairement indépendants : il s’agit d’une
liste de vecteurs dont aucun ne peut être exprimé comme une combinaison linéaire de tous les autres.
Exemple 1 : B1 = {v1 , v2 } = {(1, 1), (1, 2)} est une famille de vecteurs linéairement indépendants.
Exemple 2 : B2 = {v1 , v2 } = {(1, 1), (2, 2)} n’est pas une famille de vecteurs indépendants (on dira donc qu’elle est
liée) car le vecteur v2 peut être exprimé comme une combinaison linéaire du seul vecteur v1 : v2 = 2 × v1 .
Exemple 3 : B3 = {v1 , v2 , v3 } = {(1, 3), (−6, 8), (27, −65)} n’est pas une famille de vecteurs indépendants, ce qui est
même impossible car le nombre de vecteurs est plus grand que le nombre de coordonnées des vecteurs. Ici, n’importe
quel vecteur est une combinaison linéaire des 2 autres :
−73 −13 −87 −13 −87 −73
(1, 3) = v2 + v3 , (−6, 8) = v1 + v3 , (27, −65) = v1 + v2
87 87 73 73 13 13
Exemple 4 : B4 = {v1 , v2 } = {(1, 2, 3), (4, 5, 6)} est une famille de vecteurs linéairement indépendants.
Une base d’un espace vectoriel E est une famille de vecteurs linéairement indépendants qui génèrent par combi-
naison linéaire cet espace vectoriel : il faut qu’ils soient linéairement indépendants car imaginons que nous ajoutions
un vecteur vn+1 n’étant pas linéairement indépendant aux {v1 , ..., vn } précédents, ce vn+1 est un élément de l’espace
généré par {v1 , ..., vn } et n’ajoute donc aucune information.
Prenons par exemple une base {v1 , v2 }, l’espace vectoriel généré par cette base sera {v = a × v1 + b × v2 , (a, b) ∈ R2 }.
IMPORTANT : un espace vectoriel peut avoir une infinité de bases !
Exemple 1 : une base de R2 peut être {(1, 0), (0, 1)} ou encore {(1, 123), (0, 1)}.
Exemple 2 : une base de {(x, y) ∈ R2 |x + y = 0} peut être {(1, −1)} ou tout autre élément de l’ensemble.
Exemple 3 : une base de {(x, y, z) ∈ R3 |x + y + z = 0} peut être {(−1, 1, 0), (−1, 0, 1)} ou toute autre paire d’éléments
de l’ensemble étant linéairement indépendants.
Une base d’un espace vectoriel peut être représentée sous forme de matrice où les vecteurs de la base seront mis en
colonne et la multiplication par un ensemble de valeurs se fera à droite (pour symboliser la combinaison linéaire). Voici
ce que cela donnerait pour l’exemple 4, où nous allons récupérer la forme des vecteurs vérifiant la condition :
−1 −1 −a − b
a
1 0 × = a
b
0 1 b
Nous avions dit qu’un espace vectoriel pouvait avoir une infinité de bases, une matrice de changement de base va
permettre de changer l’expression d’un élément d’une base à une autre.
Imaginons que nous voulions passer d’un point 2D exprimé dans la base {v1 = (1, 123), v2 = (0, 1)} vers un point
exprimé dans la base {e1 = (1, 0), e2 = (0, 1)}. Elle devra au moins transformer le point 1v1 − 123v2 en le point
1e1 + 0e2 et le point 0v1 + 1v2 en le point 0e1 + 1e2 , cela nous donne la matrice de changement de base suivante (il
aurait également été possible de la trouver avec l’inverse de la matrice) :
1 0 1 0 1 0
= ×
0 1 −123 1 123 1
Est-ce que cette matrice de passage existe toujours ? La réponse est oui : soient 2 bases du même EV, X dont les
vecteurs seront notés →−
xi et Y dont les vecteurs seront appelés → −
yi , les →
−
yi sont des combinaisons linéaires de →
−
xi (car ce
sont des éléments de la lattice) et cette transformation linéaire peut être représentée par une matrice.
Un autre concept intéressant est la notion de sous-lattice : une sous-lattice de L = L(B) est un sous-ensemble L′ ⊆ L
qui est généré par une certaine lattice B ′ . Voici un exemple de sous-lattice de Z2 :
2 0 1 0
L(B ′ ) = L ⊆L = L(B) = Z2
0 1 0 1
La lattice de gauche ne génère que des paires d’entiers dont le premier est un nombre pair, alors que celle de droite
génère toutes les paires d’entiers possibles. Pour un espace vectoriel cela n’aurait pas été vrai et les 2 bases auraient
généré le même espace vectoriel pour le simple fait qu’il est possible d’utiliser des coefficients réels en plus des entiers.
Prenons l’exemple de la lattice suivante définie par la base B = {(5, 3, 3), (4, 5, 6)}, qui envoie des éléments de Z2 vers
Z3 et donc génère obligatoirement une sous-lattice de Z3 :
5 4
L(B) = L 3 5 ⊂ Z3
3 6
√
Le minimum est Λ1 (L(B)) = ||1→ −
e1 − 1→
−
e2 || = ||(1, −2, −3)|| = 14.√
Le second minimum est Λ2 (L(B)) = ||2→ −
e1 − 1→ −
e2 || = ||(6, 1, 0)|| = 37
Bien sûr, il n’y a pas de troisième minimum vu que cette lattice est générée par une base de 2 vecteurs (il sera donc
impossible de trouver un troisième vecteur indépendant aux 2 premiers qui ont été pris).
Ces 2 vecteurs étant indépendants et des éléments de L(B), ils nous permettent d’obtenir une autre base pour cette
lattice qui sera appelée la base la plus courte (”Shortest Basis”) :
1 6
L(B ′ ) = L −2 1
−3 0
Par contre attention, une liste de vecteurs contenant tous les minimums n’est pas forcément une base de la lattice
associée. Soit L la lattice telle qu’un vecteur (x1 , x2 , x3 , x4 ) ∈ L si la somme des 4 composantes donne un nombre pair.
Les 2 matrices ci-dessous sont constituées de minimums, or, la matrice de gauche est une base et celle de droite non :
1 1 1 1 a
a+b+c+d 1 1 0 0
−1 1 0 0 × b , (a, b, c, d) ∈ Z4 = −a + b , B2 = −1 1 0 0
L(B1 ) =
0 0 1 0 c
c 0 0 1 −1
0 0 0 1 d d 0 0 1 1
Il est facile de voir que la B1 génère des vecteurs de L car a+b+c+d−a+b+c+d = 2×(b+c+d). Prenons maintenant
un vecteur (x, y, z, w) ∈ L, nous pouvons prendre c = z, d = w, a = (x − y − z − w)/2 = x − (x + y + z + w)/2 qui sera
entier, b = (x + y − z − w)/2 = x + y − (x + y + z + w)/2 qui sera également un entier. Du coup B1 est une base de L.
Il est également facile de voir que B2 génère des vecteurs de L car a + b − a + b + c + d − c + d = 2 × (b + d). Mais, il
est impossible de trouver une combinaison linéaire des vecteurs de la base donnant (1, 2, 3, 4) ∈ L : du coup B2 n’est
pas une base de L.
Il est possible de montrer que si X et Y sont 2 bases de la même lattice si et seulement s’il existe une matrice
C unimodulaire telle que Y = XC.
Sens 1 : L(X) = L(Y ) → ∃C | det(C) = ±1 ∧ Y = XC :
C existe, son inverse C −1 existe et que les 2 matrices doivent être à coefficients entiers car Y et X sont elles-
mêmes à coefficients entiers. On a que det(C) × det(C −1 ) = 1, or les 2 déterminants sont des entiers vu que les
matrices sont à coefficients entiers, donc soit det(C) = det(C −1 ) = 1, soit det(C) = det(C −1 ) = −1.
Sens 2 : ∃C | det(C) = ±1 ∧ Y = XC → L(X) = L(Y ) :
Montrons que L(Y ) ⊆ L(X) : soit y dans L(Y ), il existe donc x dans Zn tel que y = Y × x, et donc y est un
élément de L(X) car il existe x′ = C × x dans Zn tel que y = X × x′ .
Montrons que L(X) ⊆ L(Y ) : soit y dans L(X), il existe donc x dans Zn tel que y = X × x, et donc y est un
élément de L(Y ) car il existe x′ = C −1 × x dans Zn tel que y = Y × x′ .
Nous avons donc fini de prouver que L(X) = L(Y ) ⇔ ∃C | det(C) = ±1 ∧ Y = XC.
Nous pouvons maintenant montrer très simplement quelque chose d’encore plus important. Soient donc X et Y , 2 bases
de la même lattice (c’est à dire telles que L(X) = L(Y )), nous savons donc qu’il existe une matrice unimodulaire C telle
que Y = XC. Si nous nous intéressons au déterminant, cela veut dire que |det(Y )| = |det(X) × det(C)| = |det(X)|.
La conclusion est très simple : L(X) = L(Y ) → |det(X)| = |det(Y )| : la lattice est uniquement définie par son
déterminant (mais l’inverse n’est pas forcément vrai car il est possible que la matrice C n’existe pas alors que
|det(X)| = |det(Y )|).
Aussi, grâce à ce que nous avons dit précédemment, vous remarquez que multiplier une base d’une lattice par une
matrice unimodulaire donne une autre base de la même lattice : on peut donc créer une infinité de bases pour la même
lattice ! Voici un exemple avec 10 étapes :
1 0 0 1 0 0 0 0 1 −1 0 0 1 0 0
A0 = 0 1 0 , A1 = 0 0 1 , A2 = 0 1 0 , A3 = 0 1 0 , A4 = 13 1 0
0 0 1 0 1 0 1 0 0 0 0 1 0 0 1
1 −78 0 1 0 0 1 0 0 1 93 0 0 1 0
A5 = 0 1 0 , A6 = 0 1 0 , A7 = 0 1 0 , A8 = 0 1 0 , A9 = 1 0 0
0 0 1 −93 0 1 0 0 1 0 0 1 0 0 1
Y9 1 0 0 −8649 −93 1
B2 = B1 × Ai = 0 3 1 × A0 × A1 × A2 × A3 × A4 × A5 × A6 × A7 × A8 × A9 = 151 10 0
i=0 0 0 −5 −980 −65 0
Grâce à ce que nous avons vu avant, nous savons que B2 est également une base de la même lattice que celle générée
par B1 (car le produit des Ai forme une matrice unimodulaire), mais si je ne vous donne que B2 il vous sera très
difficile de revenir vers la base B1 qui est plutôt simple (sans connaı̂tre cette dernière bien sûr).
L’avantage de la base B1 est que ses vecteurs sont quasiment orthogonaux (il est donc facile de résoudre le CVP avec
comme nous le verrons après) alors que pour B2 l’angle entre le premier et le dernier vecteur de la base est 6.
Cela peut être résolu en utilisant l’algorithme LLL dont la complexité dépendra de la taille des nombres dans la
”grande” base : d’où la volonté d’avoir de grands nombres.
Voici maintenant les projections orthogonales et parallèles, puis l’orthogonale arrondie à l’entier :
L’opération de projection orthogonale arrondie à l’entier est extrêmement intéressante car elle peut se voir comme une
division de 2 vecteurs avec un quotient qui sera un entier et un vecteur pour le reste.
Voyons maintenant comment trouver une formule générale pour la projection orthogonale :
Pour rappel, l’algorithme d’Euclide permettant de trouver le PGCD fonctionne de la manière suivante :
1 Entr é e : a et b tels que a > b
2 r = a
3 r’ = b
4 Tant que r ’ != 0 :
5 Trouver q : r // r ’
6 Trouver r ’ ’ : r - qr ’ # On aurait aussi pu faire r mod r ’
7 r = r’
8 r’ = r’’
9 Retourner r
Nous sommes sûrs que la base produite après chaque étape reste une base de la même lattice car nous n’effectuons
que des opérations élémentaires sur les colonnes : addition d’une colonne à une autre et échange de 2 colonnes.
On sait de plus que le nouveau Y a une norme inférieure au précédent car la projection orthogonale forme un triangle
dont l’hypothénuse sera x et les 2 autres côtés seront q × y et x − q × y. Le seul cas particulier qui va se produire sera
quand la base sera minimale : q sera égal à 0 et donc nous aurons une inversion des 2 vecteurs de la base ce qui fera
s’arrêter la boucle.
Souvenez vous que chacun des éléments p de la lattice est défini par :
p1 a1
→
−p = ... = → −
v1 · · · −v→
.. n
× . , (a1 , ..., an ) ∈ Z
n
pk an
Il est donc très facile de retrouver la combinaison linéaire de vecteurs de la base associée à un point, il suffit de
multiplier le point à droite par l’inverse de la base.
→
−
Du coup, un algorithme simple pour réaliser le décodage du point t quand les vecteurs de la base sont quasi-
ment orthogonaux (donc quand elle a été réduite) consiste à tout d’abord trouver a1 , ..., an des réels qui forment une
solution du système suivant :
t1 a1
.. →
− −
→ .
. = v1 · · · vn × ..
tk an
Ensuite, le vecteur le plus proche p sera celui obtenu en prenant l’arrondi de chaque ai et en multipliant par la base :
p1 round(a1 )
.. →
− −
→ ..
. = v1 · · · vn ×
.
pk round(an )
En revanche, moins les vecteurs de la base sont orthogonaux entre eux, moins le décodage est efficace.
Prenons par exemple la lattice définie ci-dessous par les 2 bases suivantes : B1 = {→ −
v1 , →
−
v2 } = {(−1, −3), (3, −1)}
−
→ −
→
(à gauche) et B2 = {u1 , u2 } = {(4, 2), (7, 1)} (à droite). Le point (0, 0) est représenté en rouge et le point p = (4, 3.5)
(qui n’est pas dans la lattice) est en bleu :
Pour finir, un point intéressant est d’étudier le décodage pour tous les points (x, y) ∈ R2 : nous allons définir une
couleur pour chaque point de la lattice et un (x, y) sera mis de la même couleur que ce point si le décodage donne
comme résultat ce point de la lattice.
Voici ce que cette étude donnerait avec les 2 bases que nous avons vues précédemment (vous pouvez voir la qualité du
décodage dégradée avec la seconde base) :
11.7.2 Décodage :
Les problèmes de cette catégorie peuvent être décrits de la façon suivante (d(t, L) dénote la distance au vecteur de la
lattice le plus proche) :
Closest Vector Problem : étant donnée une base B d’une lattice L, un point t ∈ Zn et un facteur d’approximation
γ, trouver y ∈ L tel que ||t − y|| < γ × d(t, L).
Decision Closest Vector Problem (DCVP) : étant donnée une base B d’une lattice L, un point t ∈ Zn et un
rayon r, dire s’il existe y ∈ L tel que ||t − y|| <= r (y peut rester inconnu).
Bounded Distance Decoding (BDD) : étant donnée une base B d’une lattice L, un point t ∈ Zn et un paramètre
de distance α tel que d(t, L) < α × Λ1 (L), trouver y ∈ L tel que ||y − t|| < α × Λ1 (L).
Learning With Errors (LWE) : étant donné q, χ et des échantillons indépendants, trouver s. Il y a aussi la version
décisionelle où il faut distinguer sir les échantillons sont purement random (pas de solution) ou construits grâce
à la règle.
Pour résoudre le CVP, nous utiliserons l’algorithme de Babai qui peut être décrit de 2 façons :
On applique la méthode que nous avons vue précédemment en calculant l’inverse de la base, puis en réalisant la
multiplication et finalement en prenant le vecteur correspondant à l’arrondi de tous les ai obtenus. La complexité
de cette méthode est totalement dépendante à la complexité de l’inversion qui eset O(n3 ).
On prend le target t qui nous est donné, on le ”divise” (via projection orthogonale) par chacun des vecteurs de
la base et on retire l’arrondi du coefficient multiplié par le vecteur de la base associé. Ici, la complexité sera en
O(n2 ).
Le second algorithme peut être décrit de la façon suivante :
1 Appliquer LLL sur la base B
2 resteCourant = t
3 Pour i allant de 1 à n :
4 coefficient = round (( resteCourant . B [ i ]) / ( B [ i ] . B [ i ]) )
5 resteCourant -= coefficient * B [ i ]
6 Retourner t - resteCourant
L’idée est que l’on compare l’hypervolume d’une base de vecteurs parfaitement orthogonaux (le calcul du déterminant)
à l’hypervolume formé par les longueurs des vecteurs de la base courante et on en prend la racine n-ième.
Si nous reprenons l’exemple de la partie sur le CVP, nous pouvons obtenir les résultats suivants :
1/2
10
B1 = {(−1, −3), (3, −1)} : √ √ =1
10 × 10
1/2
10
B2 = {(4, 2), (7, 1)} : √ √ ≈ 0.562
20 × 50
Vous vous souvenez que la première base est parfaitement orthogonale (d’où le ratio de 1) alors que la seconde l’est
beaucoup moins : on le voit, le ratio est plus proche de 0.
Voici un premier exemple dans lequel le ratio de Hadamard de B devait être plus grand que 0.95 :
4 5 −3 −3 −56540 −5512462 15099 −688559 −74525215 ···
−3 −5 −1 −2 1492343 145499114 −397745 18174225 ′
−48332776 · · ·
B= −5 4 −3 4 U = 13466499
B =
1312944565 −3589182 163999280 21000939 · · ·
−3 5 4 −4 13787091 1344201237 −3674789 167903536 6348967 ···
L’angle entre les différents vecteurs de la base est :
b1 b2 b3 b4 b′1 b′2 b′3 b′4
b1 x 90.0° 82.4° 74.2° b′1 x 82.2° 0.00° 0.00°
b2 90.0° x 88.0° 81.9° b′2 82.2° x 82.2° 82.2°
b3 82.4° 88.0° x 64.6° b′3 0.00° 82.2° x 0.00°
b4 74.2° 81.9° 64.6° x b′4 0.00° 82.2° 0.00° x
Et pour finir, voici le calcul des ratios de Hadamard : H(B) = 0.951, H(B ′ ) = 0.000486.
Voici un seond exemple dans lequel le ratio de Hadamard de B devait être plus grand que 0.995 :
4 −1 4 2 807661 −4062130 80472 −80472 −55104698 ···
−3 −2 −3 4 111496 −560769 11109 −11109 ′ 23463766 · · ·
B= U =
−11784987 59272520 −1174208 1174203 B = −6577526
4 −3 1 −1 · · ·
5 1 1 5 −2311305 11624694 −230289 230288 −19191711 ···
L’angle entre les différents vecteurs de la base est :
b1 b2 b3 b4 b′1 b′2 b′3 b′4
b1 x 84.5° 87.3° 89.0° b′1 x 0.00° 0.00° 0.00°
b2 84.5° x 90.0° 85.6° b′2 0.00° x 0.00° 0.00°
b3 87.3° 90.0° x 90.0° b′3 0.00° 0.00° x 0.00°
b4 89.0° 85.6° 90.0° x b′4 0.00° 0.00° 0.00° x
Et pour finir, voici le calcul des ratios de Hadamard : H(B) = 0.9978, H(B ′ ) = 1.926 × 10−7 .
11.8.3 Chiffrement :
L’opération de chiffrement sera très simple : on commencera par mettre le message sous forme de vecteur (une idée
peut être de mettre les bits du message comme vecteur). Ensuite, nous ajouterons une erreur aléatoire qui ne devra
pas être trop grande sinon le décodage ne marchera pas, une idée est de la choisir aléatoirement suivant les mêmes
limites que B (et même moins) puis voir si le décodage marche (pour ne pas rendre la tâche trop facile à l’attaquant
et en même temps permettre le décodage).
Le chiffré peut donc s’exprimer en c = B ′ × m + e.
Nous pouvons ensuite ajouter l’erreur, je propose 2 exemples (la première est assez petite et permet le décodage alors
que la seconde est trop grande et le fera échouer) :
1 1631575302 0 1631575301
2 −694730123 −2 −694730127
e1 =
−2 , c1 = 194751501 , e2 = −1 , c2 = 194751500
2 568240308 1 568240309
11.8.4 Déchiffrement :
La procédure pour le déchiffrement est un peu plus compliquée :
1. On commence par calculer B −1 × c, puis on arrondit les coefficients du vecteur résultat et on multiplie B par
ces nouveaux coefficients pour obtenir le vecteur le plus proche (algorithme de Babai) : la sortie sera appelée v.
2. On calcule (B × U )−1 × v pour retrouver la combinaison linéaire ayant donné le chiffré et donc le message.
68434596.4940855 68434595.9772520
En arrondissant les coefficients et en re-multipliant par B nous obtenons :
−23913773 1631575301 −23913773 1631575300
−3301249 −694730125 −3301248 −694730127
v1 = B × 348937442 = 194751501 , v2 = B × 348937442 = 194751498
3
86413.5048828125
6727.883819580078
m2 = B ′−1 × v2 = −535537.73046875
−7562.8701171875
Et nous avons donc récupéré le message pour le premier et une mauvaise valeur pour le second (qui d’ailleurs à cause
d’erreurs d’arrondi en python ne donne pas exactement v2 lorsqu’on le re-multiplie par B ′ ).
La multiplication elle est plus complexe, sans réduction par X N − 1 elle se définirait de la manière suivante :
NX−1 NX−1
a(x) × b(x) = (a0 b0 mod m) + ((a0 b1 + a1 b0 ) mod m) × X + · · · = ai × bj × X i+j
i=0 j=0
Il ne faudra pas oublier d’appliquer le modulo devant chaque coefficient du résultat.
Vu que l’on fait la réduction par X N − 1, soit aN le coefficient devant X N on va ajouter −aN × X N + aN à notre
polynôme (ce qui aura pour effet de rajouter aN au coefficient a0 ). La nouvelle formule devient :
N
X −1 N
X −1
a(x) × b(x) = ai × bj × X (i+j) mod N
i=0 j=0
Encore une fois il ne faudra pas oublier de faire le modulo devant chaque coefficient.
Par exemple :
a(x) × b(x) = (3X 3 + 7X 2 + 4X + 1) × (4X 3 + 2X 2 + 9X + 3)
a(x)×b(x) = 12X 6 +6X 5 +27X 4 +9X 3 +28X 5 +14X 4 +63X 3 +21X 2 +16X 4 +8X 3 +36X 2 +12X +4X 3 +2X 2 +9X +3
a(x) × b(x) = 12X 2 + 6X + 27 + 9X 3 + 28X + 14 + 63X 3 + 21X 2 + 16 + 8X 3 + 36X 2 + 12X + 4X 3 + 2X 2 + 9X + 3
a(x) × b(x) = 84X 3 + 71X 2 + 55X + 60
a(x) × b(x) = 4X 3 + X 2 + 5X (mod 10)
Avant de passer à l’inversion de polynôme, il nous faut voir comment réaliser la division Euclidienne de polynômes.
En voici un exemple sur a(x) = 3X 6 + 12X 5 + 7X 4 + X 3 + 5X 2 + 10X + 7 et b(x) = 4X 3 + X 2 + 5X modulo m = 13 :
3X 6 + 12X 5 + 7X 4 + X3 + 5X 2 + 10X + 7 4X 3 + X2 + 5X
6 5 4 3 2
- 16X - 4X - 20X 4X + 2X + 6X + 6
5 4 3 2
8X + 0X + X + 5X + 10X + 7
- 8X 5 - 2X 4 - 10X 3
11X 4 + 4X 3 + 5X 2 + 10X + 7
- 11X 4 - 6X 3 - 4X 2
11X 3 + 1X 2 + 10X + 7
3 2
- 11X - 6X - 4X
2
8X + 6X + 7
Pour calculer l’inverse d’un polynôme, on utilisera l’algorithme d’Euclide étendu dont le principe est le suivant :
1 r = s * P + t * p (P : polyIrreductible , p : polynome )
2 r2 = s2 * P + t2 * p
3 Trouvons r = r2 * q + r3 <= > r3 = r - r2 * q
4 Donc : r3 = s * P + t * p - s2 * q * P - t2 * q * p
5 Donc : r3 = ( s - s2 * q ) * P + ( t - t2 * q ) * p
q r Égalité
11
X +2 r =1×P +0×a
2X 10 + X 9 + X 6 + 2X 4 + X 2 + X + 2 r =0×P +1×a
9 7 6 5 4 3 2
2X + 2 X + X + X + 2X + 2X + X + 2X + 1 r = 1 × P + (X + 1) × a
8 6 4 3 2
2X + 1 X + 2X + X + X + 2X + 2X + 1 r = (X + 2) × P + X 2 × a
X 2X 7 + X 6 + X 5 + X 4 + 2X 3 + 2X + 1 r = (2X 2 + X + 1) × P + (2X 3 + X + 1) × a
2X + 2 X 6 + 2X 5 + X 4 + X 2 + 2X + 2 r = 2X 3 × P + (2X 4 + 2X 3 + 2X 2 + 2X + 1) × a
2X 2X 5 + X 4 + 2X 2 + X + 1 r = · · · × P + (2X 5 + 2X 4 + X 3 + 2X 2 + 2X + 1) × a
4 3 2
2X X + 2X + 2X + 2 r = · · · × P + (2X 6 + 2X 5 + X 3 + X 2 + 1) × a
2X 2X 3 + 2X 2 + 1 r = · · · × P + (2X 7 + 2X 6 + 2X 5 + 2X 3 + 2X 2 + 1) × a
2X + 2 X2 + X r = · · · × P + (2X 8 + X 7 + X 5 + 2X 4 + 2X 3 + X + 2) × a
2X 1 1 = · · · + (2X 9 + X 8 + 2X 7 + X 5 + 2X 4 + 2X 3 + 2X + 1)a
Voyons maintenant pourquoi il faut parfois diviser par le terme constant à la fin, nous allons prendre le polynôme
a(X) = 3X 6 + 4X 5 + 10X 4 + 8X 3 + X 2 + 10X + 9 avec P (X) = X 7 − 1 et m = 11 :
q r Égalité
7
X + 10 r =1×P +0×a
6 5 4 3 2
3X + 4X + 10X + 8X + X + 10X + 9 r =0×P +1×a
5 4 3 2
4X + 2 7X + 3X + 2X + 2X + 10X + 3 r = 1 × P + (7X + 9) × a
2X + 6 10X 4 + 3X 3 + 2X 2 + 10X + 2 r = (9X + 5) × P + (8X 2 + 6X + 2) × a
4X + 9 10X 2 + 7 r = (8X 2 + 9X) × P + (X 3 + 3X 2 + 2) × a
X 2 + 8X + 5 9X r = · · · × P + (10X 5 + 4X 3 + 2X 2 + X + 3) × a
6X 7 7 = · · · × P + (6X 6 + 9X 4 + 8X 2 + 4X + 2) × a
Et terminons maintenant par le dernier cas possible un modulo qui n’est pas premier : m = 16, l’inversion ne
machera souvent pas et il faudra donc utiliser une autre méthode que nous décrirons plus loin. Prenons a(X) =
5X 6 + 6X 5 + 15X 4 + 3X 3 + 2X 2 + 9X + 1 et P (X) = X 7 − 1 :
q r Égalité
7
X + 15 r =1×P +0×a
6 5 4 3 2
5X + 6X + 15X + 3X + 2X + 9X + 1 r =0×P +1×a
5 4 3 2
13X + 10 X + 3X + 8X + 7X + 9X + 5 r = 1 × P + (3X + 6) × a
4 3 2
5X + 7 2X + 8X + 4X + X + 14 r = (11X + 9) × P + (X 2 + 13X + 7) × a
Il est impossible de continuer plus loin car il est impossible de trouver l’inverse de 2 modulo 16 (pour pouvoir enlever
le X 5 ), donc on pourrait conclure qu’il n’y a pas d’inverse mais cela serait faux.
L’idée pour trouver l’inverse sera d’utiliser le ”lifting” de solutions : il suffit de trouver la solution au problème
modulo p par exemple et il est ensuite possible de la calculer modulo p2 .
L’idée va maintenant être de l’appliquer à l’inversion de polynome : soit p un nombre, nous sommes arrivés à trouver
a(x) × b1 (x) = 1 (mod p) c’est à dire l’inverse de a(x) modulo p (en utilisant l’algorithme d’Euclide étendu ou une
élévation précédente).
Nous avons les 3 relations suivantes :
a(x) × b1 (x) = 1 + k × p (mod p2 ) pour un certain k.
2 × a(x) × b1 (x) = 2 + 2 × k × p (mod p2 ) pour le même k.
(a(x) × b(x))2 = (1 + k × p) = 1 + 2 × k × p (mod p2 ) pour le même k.
Nous pouvons donc prendre a(x) × b2 (x) = 2 × a(x) × b1 (x) − (a(x) × b1 (x))2 = 1 (mod p2 ) ce qui nous donne donc
b2 (x) = 2 × b1 (x) − a(x) × b1 (x)2 = b1 (x) × (2 − a(x) × b1 (x)) comme solution à a(x) × b2 (x) = 1 (mod p2 ) : il est
donc possible de construire une solution modulo p2 à partir d’une solution modulo p.
Pour notre exemple précédent a(X) = 5X 6 + 6X 5 + 15X 4 + 3X 3 + 2X 2 + 9X + 1, modulo 16, voici la méthode :
b1 (x) = a−1 (x) (mod 2) = X 6 + X + 1
b2 (x) = 2 × b1 (x) − a(x) × b1 (x)2 (mod 4) = X 6 + 2X 5 + 2X 4 + 2X 3 + 2X 2 + X + 3
b3 (x) = 2 × b2 (x) − a(x) × b2 (x)2 (mod 16) = X 6 + 14X 5 + 10X 4 + 6X 3 + 14X 2 + 13X + 15
Et nous avons donc notre inverse : b3 (x) = a−1 (x) (mod 16).
Une autre question se pose si nous voulons l’inverse modulo 32 par exemple : l’idée va être de le trouver modulo
64, puis de prendre tous les coefficients modulo 32.
Supposons que nous avons b(x) = a−1 (x) (mod pn ) et que nous voulions b′ (x) = a−1 (x) (mod pm ) avec m < n, nous
avons donc que a(x) × b(x) = 1 + k × pn = 1 + (k × pn−m ) × pm = 1 (mod pm ) donc l’inverse modulo 32 est le même
que l’inverse modulo 64, il suffit de prendre chacun des coefficients modulo 32.
11.9.2 Le cryptosystème :
Tout d’abord, il y aura 6 paramètres importants :
N : le degré maximal (non atteint) de tous les polynômes, la réduction se fera via X N − 1
p : une première valeur de modulo petite.
q : une seconde valeur de modulo, première avec p et beaucoup plus grande.
df , dg et d : seront expliqués plus loin.
Pour la génération de la clé, il faudra commencer par générer 2 polynômes aléatoires dont les coefficients seront soit
−1, soit 0, soit 1. f aura df coefficients à 1 et df − 1 coefficients à -1, g aura dg coefficients à 1 et dg coefficients à -1.
Ces 2 polynômes seront appelés f et g et il faudra que f soit inversible modulo p et modulo q. f formera la clé privée.
Une fois cela fait, il faut calculer h = p × f −1 × g (mod q) qui formera la clé publique.
11.9.3 Un exemple :
Nous allons reprendre l’exemple de Wikipédia qui utilise les paramètres suivants :
N, p, q, df , dg , d = 11, 3, 32, 3, 3, 3.
Pour le déchiffrement, nous allons commencer par calculer a = f × c (mod q), ici :
a = 25X 10 + 29X 9 + 5X 8 + 7X 7 + 6X 6 + 7X 5 + 10X 4 + 21X 3 + 22X 2 + 25X + 3 (mod 32)
Pour la formule nous avons a = p × g × r + m × f (mod q).
Il faut ensuite re-centrer a, ce qui nous donne :
a = −7X 10 − 3X 9 + 5X 8 + 7X 7 + 6X 6 + 7X 5 + 10X 4 − 11X 3 − 10X 2 − 7X + 3 (mod 32)
Pour finir, vous pouvez appliquer un modulo p = 3 :
a = 2X 10 + 2X 8 + X 7 + X 5 + X 4 + X 3 + 2X 2 + 2X
Puis multiplier par fp et vous aurez le message :
m = a × fp (mod 3) = −X 7 − X 5 + X 4 + X 3 + X 2 − 1
Le taux de déchiffrement avec les paramètres donnés et en changeant juste le message est 99.91%.
Une première attaque que l’on peut faire avec des lattices va consister à retrouver la clé privée à partir de la clé
publique et des paramètres. La lattice associée à l’instance NTRU sera définie par L = {(u, v) ∈ P, u × h = v (mod q)}
ce qui correspond à l’ensemble des couples de polynômes (u, v) tels que u × h = v (mod q).
Trouver une base est très simple, prenons u = 0 nous avons k × q à droite (si nous retirons le modulo), prenons u = 1
nous avons v = h, une base de cette lattice peut donc être :
0 1
B=
q h
Sauf que les différentes variables sont des polynômes, il est donc possible de tout ré-écrire avec leurs coefficients :
f0 0 ··· 0 1 ··· 0 x0
.. .. . . . .. .. .. ..
. .
. .. . . . .
fN −1 0 · · · 0 0 ··· 1 xN −1
g0 = q · · · 0
×
h0 · · · hN −1
f0
. . . . . . . .
.. .. . . .. .. .. .. ..
gN −1 0 · · · q hN −1 · · · h0 fN −1
Du coup nous savons que le couple (f, g) est dans L et c’est également probablement l’un des plus petits vecteurs de
cette lattice. Il est donc possible de casser NTRU en résolvant le problème SVP sur la lattice précédente.
Il est possible de faire une analyse similaire sur la reconstruction d’un texte en clair à partir d’un texte chiffré :
0 0 ··· 0 1 ··· 0 x0 −r0
.. .. . . . .. .. .. .. ..
. .
. .. . . . . .
0 0 · · · 0 0 ··· 1 xN −1 −rN −1
= × +
c0 q · · · 0 p × h0 · · · p × hN −1
r0 m0
. . . . . . . . .
.. .. . . .. .. .. .. .. ..
cN −1 0 · · · q p × hN −1 · · · p × h0 rN −1 mN −1
c est donc un point de la lattice définie par une base quasi-identique à avant auquel nous avons rajouté une petite er-
reur (représentée par le vecteur contenant −r et m). Donc, si on arrive à résoudre le CVP, on peut déchiffrer sans la clé !
En conclusion c’est uniquement parce que casser NTRU se base sur la résolution de problèmes sur les lattices qu’on
dit que c’est un cryptosystème basé sur les lattices.
Voici un autre programme pour trouver les points ayant les plus petites normes (donc les minimums seront contenus
dans la liste mais cette dernière contiendra également des valeurs qui ne sont pas des minimums) :
1 import math
2
3 # Function to compute the norm of a vector
4 def norm ( vector ) :
5 sumVal = 0
6 for i in range (0 , len ( vector ) ) :
7 sumVal += vector [ i ] * vector [ i ]
8 return math . sqrt ( sumVal )
9
10 def minimumsRec ( baseVectors , currentLinearComb , depth , maxDepth , limit , res ) :
11 if depth == maxDepth :
12 # We will get the norm of the current linear comb
13 normVal = norm ( c u r r e n t L i n e a r C o m b )
14
15 # Let ’s now put it in the res array
Et un autre programme en Python qui commence par une base d’une certaine lattice, puis lui applique k opérations
sur les colonnes pour obtenir une autre base de la même lattice :
1 import random
2
3 # Le programme suppose que toutes les matrices sont carrees
4 n = 3
5 base = [
6 [ 1, 0, 0 ],
7 [ 0, 3, 1 ],
8 [ 0 , 0 , -5 ]
9 ]
10
11 def multMatrices (A , B ) :
12 result = [ [ 0 for j in range (0 , n ) ] for i in range (0 , n ) ]
13 for i in range (0 , n ) :
14 for j in range (0 , n ) :
15 prodScal = 0
16 for k in range (0 , n ) :
17 prodScal += A [ i ][ k ] * B [ k ][ j ]
18 result [ i ][ j ] = prodScal
19 return result
20
21 def invertMatrix ( l ) :
22 result = [ [ (1 if i == j else 0) for j in range (0 , n ) ] for i in range (0 , n ) ]
23 result [ l ][ l ] = -1
24 return result
25
26 def addMatrix ( l1 , c , l2 ) :
27 result = [ [ (1 if i == j else 0) for j in range (0 , n ) ] for i in range (0 , n ) ]
28 result [ l2 ][ l1 ] = c
29 return result
30
31 def swapMatrix ( l1 , l2 ) :
32 result = [ [ (1 if i == j else 0) for j in range (0 , n ) ] for i in range (0 , n ) ]
33 result [ l1 ][ l1 ] = 0
34 result [ l2 ][ l2 ] = 0
35 result [ l1 ][ l2 ] = 1
36 result [ l2 ][ l1 ] = 1
37 return result
38
39 def r a n d o m I n v e r t M a t r i x () :
40 ligne = random . randint (0 , n - 1)
41 return invertMatrix ( ligne )
42
43 def r an do m Ad dM at r ix ( r ) :
Et pour finir, voici l’algorithme pour réduire une base composée de 2 vecteurs :
1 import math
2
3 def nearestInt ( x ) :
4 if x <= x // 1 + 0.5 :
5 return x // 1
6 else :
7 return ( x // 1) + 1
8
9 def dot ( v1 , v2 ) :
10 result = 0
11 for i in range (0 , len ( v1 ) ) :
12 result += v1 [ i ] * v2 [ i ]
13 return result
14
15 def norm ( v ) :
16 return math . sqrt ( dot (v , v ) )
17
18 def reduce ( v1 , v2 ) :
19 if norm ( v1 ) < norm ( v2 ) :
20 return reduce ( v2 , v1 )
21
22 x , y = v1 , v2
23 while norm ( x ) > norm ( y ) :
24 q = nearestInt ( dot (y , x ) / dot (y , y ) )
25 newY = []
26 for i in range (0 , len ( y ) ) :
27 newY . append ( x [ i ] - q * y [ i ])
28 x , y = y , newY
29 return y , x
11.10.2 GGH :
Voici un programme qui génère une clé pour le cryptosystème GGH :
1 import math
2 import random
3 import numpy as np
4
5 def r a n d o m I n v e r t M a t r i x ( size ) :
6 l = random . randint (0 , size - 1)
7 result = [ [ (1 if i == j else 0) for j in range (0 , size ) ] for i in range (0 , size ) ]
8 result [ l ][ l ] = -1
9 return result
10
11 def r an do m Ad dM at r ix (r , size ) :
91 break
92 if good == False :
93 break
94 if good :
95 break
96 U = U . tolist ()
97
98 # pubB est le produit privB * U
99 pubB = np . matmul ( privB , U ) . tolist ()
100
101 # On calcule encore une fois le ratio de hadamard
102 if hadamardRatio ( pubB ) <= 0.01 : # Une autre limite comme ca
103 break
104
105 return (( privB , U ) , pubB )
106
107 (( privB , U ) , pubB ) = generateKey (4 , 5 , 10000)
108 print ( hadamardRatio ( privB ) )
109 print ( " Private B : " + str ( privB ) )
110 print ( " Private U : " + str ( U ) )
111 print ( " Public B : " + str ( pubB ) )
112 print ( hadamardRatio ( pubB ) )
11.10.3 NTRU :
Voici un premier programme pour la gestion des polynômes :
1 import math
2 import random
3
4 # Un polynome est represente par un tableau
5 # Le 1 er element du tableau est le coefficient devant X ^0 , le suivant X ^1 , ...
6 # Exemple : 3 X ^3 - 4 X ^2 + 1 : [ 1 , 0 , -4 , 3 ]
7
8 # La fonction pour afficher un polynome
9 def a ff ic h eP ol yn o me ( polynome ) :
10 for i in range (0 , len ( polynome ) ) :
11 print ( str ( polynome [ i ]) , end = " " )
12 if i == 0 :
13 print ( " " , end = " " )
14 elif i == 1 :
15 print ( " X " , end = " " )
16 elif i >= 2 :
17 print ( " X ^ " + str ( i ) , end = " " )
18 if i != len ( polynome ) - 1 :
19 print ( " + " , end = " " )
20 print ()
21
22 # La fonction pour enlever les 0 a la fin d ’ un polynome
23 def f o r m a t G o o d P o l y n o m e ( polynome ) :
24 # On commence donc par compter le nombre de zeros a la fin
25 nomb reZerosF in = 0
26 for i in range ( len ( polynome ) - 1 , -1 , -1) :
27 if polynome [ i ] != 0 :
28 break
29 nombr eZerosF in += 1
30 # On prend ensuite la partie sans ces zeros
31 res = polynome [: len ( polynome ) - nombreZe rosFin ]
32 # Si le resultat ne contient aucune valeur on ajoute 0
33 if len ( res ) == 0 :
34 res . append (0)
35 # Retournons le resultat
36 return res
37
38 def a d d i t i o n n e r P o l y n o m e s ( polynome1 , polynome2 , N , modulo ) :
39 # On veut que le polynome de plus haut degre soit toujours le premier parametre
40 if len ( polynome1 ) < len ( polynome2 ) :
41 return a d d i t i o n n e r P o l y n o m e s ( polynome2 , polynome1 , N , modulo )
42 # Calcul du resultat ( on ajoute les coefficients de meme degre )
43 result = [ polynome1 [ i ] for i in range (0 , len ( polynome1 ) ) ]
44 for i in range (0 , len ( polynome2 ) ) :
45 result [ i ] = ( result [ i ] + polynome2 [ i ]) % modulo
46 # On retourne le resultat
47 return f o r m a t G o o d P o l y n o m e ( result )
48
49 def oppose ( polynome , N , modulo ) :
50 return [ ( modulo - polynome [ i ]) % modulo for i in range (0 , len ( polynome ) ) ]
51
52 def m u l t i p l i e r P o l y n o m e s ( polynome1 , polynome2 , N , modulo ) :
53 # On initialise le resultat avec des 0
54 result = [ 0 ] * ( len ( polynome1 ) + len ( polynome2 ) - 1)
55 # Calcul du resultat : le coefficient de X ^{ i + j } est la somme des coefficients de X ^ i * X ^ j
56 # On fait en meme temps la reduction modulo X ^ N - 1 ( c ’ est a ca que sert ( i + j ) % N ) : pour
enlever un X ^ N on fait -X ^ N + 1
57 for i in range (0 , len ( polynome1 ) ) :
58 for j in range (0 , len ( polynome2 ) ) :
59 result [( i + j ) % N ] += polynome1 [ i ] * polynome2 [ j ]
60 result [( i + j ) % N ] %= modulo
61 # S ’ occupe de renvoyer le polynome sans les 0 devant les termes de plus haut degre
62 return f o r m a t G o o d P o l y n o m e ( result )
63
64 def d i v i s i o n E u c l i d i e n n e ( polynome1 , polynome2 , modulo ) :
65 quotient = []
66 copi ePolynom e1 = [ polynome1 [ i ] for i in range (0 , len ( polynome1 ) ) ]
67
68 for i in range (0 , len ( polynome1 ) - len ( polynome2 ) + 1) :
69 # On recupere l ’ index en partant de la fin et on passe si besoin
6 # Calcul du resultat
7 result = m u l t i p l i e r P o l y n o m e s (r , h , N , baseQ ** puissQ )
8 for i in range (0 , len ( result ) ) :
9 result [ i ] = ( result [ i ] * ( baseP ** puissP ) ) % ( baseQ ** puissQ )
10 result = a d d i t i o n n e r P o l y n o m e s ( result , m , N , baseQ ** puissQ )
11 return f o r m a t G o o d P o l y n o m e ( result )
12
13 # La fonction pour dechiffrer un message avec NTRU
14 def decryptNTRU (N , baseP , puissP , baseQ , puissQ , f , fp , c ) :
15 q = baseQ ** puissQ
16
17 # Calcul de a
18 a = m u l t i p l i e r P o l y n o m e s (f , c , N , q )
19
20 # Centrage des coefficients de a
21 for i in range (0 , len ( a ) ) :
22 if a [ i ] > q // 2 :
23 a[i] = a[i] - q
24 # Modulo p
25 a = [ a [ i ] % ( baseP ** puissP ) for i in range (0 , len ( a ) ) ]
26
27 # Retrouvons le message
28 return m u l t i p l i e r P o l y n o m e s ( fp , a , N , baseP ** puissP )
29
30 # La fonction pour mesurer l ’ efficacite du decodage
31 def m e a s u r e E f f i c i e n c y (N , baseP , puissP , baseQ , puissQ , f , fp , h , testCount ) :
32 successCount = 0
33 for i in range (0 , testCount ) :
34 m = [ random . randint (0 , 2) for i in range (0 , N ) ]
35 m = [ -1 if m [ i ] == 2 else m [ i ] for i in range (0 , len ( m ) ) ]
36 m = formatGoodPolynome (m)
37
38 c = encryptNTRU (N , baseP , puissP , baseQ , puissQ , d , h , m )
39
40 mPrime = decryptNTRU (N , baseP , puissP , baseQ , puissQ , f , fp , c )
41 mPrime = [ -1 if mPrime [ i ] == 2 else mPrime [ i ] for i in range (0 , len ( mPrime ) ) ]
42
43 if m == mPrime :
44 successCount += 1
45
46 return successCount / testCount
47
48 m = g e n e r a t e R a n d o m P o l y n o m i a l (N , N // 3 , N // 3)
49 c = encryptNTRU (N , baseP , puissP , baseQ , puissQ , d , h , m )
50 mPrime = decryptNTRU (N , baseP , puissP , baseQ , puissQ , f , fp , c )
51 mPrime = [ -1 if mPrime [ i ] == 2 else mPrime [ i ] for i in range (0 , len ( mPrime ) ) ]
52
53 print ( " m : " , end = " " )
54 a ff ic he P ol yn om e ( m )
55 print ( " c : " , end = " " )
56 a ff ic he P ol yn om e ( c )
57 print ( " m ’ : " , end = " " )
58 a ff ic he P ol yn om e ( mPrime )
59 print ()
60
61 print ( " Pourcentage bon decodage : " + str ( m e a s u r e E f f i c i e n c y (N , baseP , puissP , baseQ , puissQ , f , fp ,
h , 10000) * 100) + " % " )
12 L’interpolation lagrangienne :
12.1 Le but :
C’est une méthode très utile et très puissante qui permet de trouver un polynôme de degré k − 1 qui passe k points
que nous pourrons choisir. Ces points seront appelées ”points de contrôle” et seront notés (x1 , y1 ), ..., (xk , yk ), comme
vous vous en doutez ce seront les points par lesquels notre polynôme devra passer.
Une droite passe par 2 points : (x1 , y1 ), (x2 , y2 ). Tout ce qu’il nous faut c’est trouver le coefficient directeur de cette
droite ainsi que son ordonnée à l’origine.
Le coefficient directeur est très facile à trouver, le voici :
y1 − y2
a=
x1 − x2
Pour l’ordonnée à l’origine nous savons que le point (x1 , y1 ) doit appartenir à la droite, il doit donc également être
une solution de l’équation y = ax + b, nous pourrons donc prendre b = y − ax.
Voici donc l’équation de la droite passant par les 2 points donnés :
y1 − y2 y1 − y2
y= x + y1 − x1 ×
x1 − x2 x1 − x2
Notez que si x1 = x2 , la fonction n’existe pas.
Pour 3 points, cela se complique un peu plus : il faudra trouver la fonction de degré 2 passant par les points
(x1 , y1 ), (x2 , y2 ), (x3 , y3 ). Nous allons donc chercher à trouver a, b, c dans ax2 + bx + c tels que les 3 points donnés
soient solutions de cette équation.
Cela peut se résoudre avec un système :
2
ax1 + bx1 + c = y1
2
x1 x1 1 a y1
ax22 + bx2 + c = y2 ⇔ x22 x2 1 × b = y2
x23 x3 1 c y3
2
ax3 + bx3 + c = y3
Avec cette équation, vous pouvez remarquer le lien très fort qu’il y a entre l’interpolation lagrangienne et les matrices
de Vandermonde. L’inverse d’une matrice de Vandermonde constituera une solution à l’interpolation lagrangienne et
avoir une solution à l’interpolation lagrangienne permettra d’inverser une matrice de Vandermonde !
Cette méthode pourrait être appliquée à n’importe quel nombre de points mais le problème est que l’inverse d’une
matrice ne peut être calculé qu’en un temps proportionnel à n3 , il nous faudra donc une solution plus efficace. De
plus, le faire à la main serait assez long.
La manière la plus simple d’arriver à valider la première condition pour le polynôme f1 est la suivante : f1 (x) =
(x − x2 ) × ... × (x − xk ) : ce dernier vaudra 0 dès que nous prendrons x = x2 , x = x3 et ainsi de suite.
Pour obtenir la seconde condition, il faut tout d’abord remarquer que tous nos facteurs auront une valeur que nous
ne connaissons pas lorsque le calcul de f1 (x1 ) sera réalisé. Ce qu’il serait intéressant de faire est qu’ils deviennent
tous 1 quand nous voulons calculer f1 (x1 ) : nous allons diviser le facteur (x − xj ) par (x1 − xj ), de cette façon, nous
obtiendrons le comportement voulu.
Finalement, l’expression de fi est la suivante :
(x − x1 ) (x − xi−1 ) (x − xi+1 ) (x − xk )
fi (x) = × ··· × × × ··· ×
(xi − x1 ) (xi − xi−1 ) (xi − xi+1 ) (xi − xk )
Tous les fi forment une base de l’ensemble des polynômes qui passent par les points (x1 , y1 ), ..., (xk , yk ).
Pour finir une remarque très importante : il faut que tous les xi soient différents pour que l’interpolation puisse être
réalisée (dans le cas contraire, il serait impossible de trouver une fonction).
Le premier sera avec 2 points (nous chercherons donc un polynôme de degré 1). Les points que nous prendrons
seront (2, y1 ), (5, y2 ). Commençons donc par le calcul des polynômes de la base :
f1 (x) = (x − x2 )/(x1 − x2 ) = (x − 5)/ − 3 = −1/3x + 5/3
f2 (x) = (x − x1 )/(x2 − x1 ) = (x − 2)/3 = 1/3x − 2/3
En conclusion tous les polynômes qui passent par les points (2, y1 ), (5, y2 ) peuvent s’écrire sous la forme d’une combi-
naison linéaire entre les 2 polynômes de la base trouvée : f = y1 × f1 + y2 × f2 .
Imaginons que nous ayons y1 = 2 et y2 = 5 (l’équation à trouver est évidente ici, c’est y = x), la fonction à prendre
sera 2 × f1 (x) + 5 × f2 (x) = −2/3x + 10/3 + 5/3x − 10/3 = x.
Notez que si nous n’avions pas donné de valeur précise à x1 et x2 , la formule générale de la fonction passant par
(x1 , y1 ), (x2 , y2 ) serait dans ce cas :
x − x2 x − x1
f (x) = y1 × + y2 ×
x1 − x2 x2 − x1
Enchaı̂nons avec un exemple un peu plus intéressant sur 4 points (nous chercherons un polynôme de degré 3). Les 4
points que nous prendrons seront les suivants : (4, 0), (6, 5), (8, −8), (10, 18).
Voici le détail du calcul du premier polynôme de la base :
x − 6 x − 8 x − 10 1 1 47
f1 (x) = × × = − × x3 + × x2 − × x + 10
4−6 4−8 4 − 10 48 2 12
Et voici maintenant la base au complet :
1
× x3 + 21 × x2 − 12 47
f1 (x) = − 48 × x + 10
f (x) = 1 × x3 − 11 × x2 + 19 × x − 20
2 16 8 2
1 3 5 2 31
f 3 (x) = − 16 × x + 4 × x − 4 × x + 15
1 3 3 2 13
f4 (x) = 48 × x − 8 × x + 6 × x − 4
Pour finir, le polynôme souhaité est donné par f (x) = 0 × f1 (x) + 5 × f2 (x) − 8 × f3 (x) + 18 × f4 (x) dont le résultat
du calcul est le suivant :
19 189 297
f (x) = × x3 − × x2 + × x − 292
16 8 2
Question b : quelles sont les tailles de clé minimales qu’on doit prendre pour les algorithmes RSA ou El-Gamal ?
Quel est l’intérêt des systèmes basés sur les courbes elliptiques par rapport aux précédents ?
Question c : pour une fonction de hachage quelle taille de haché doit-on prendre au minimum et pourquoi ? Donner
des exemples de noms de fonctions de hachage.
Question d : expliquer pourquoi si on utilise du chiffrement à flot, réutiliser le même flot quasi-aléatoire sur différents
message est une mauvaise idée.
Question f : peut-on faire de l’échange de clé de manière générique à partir d’un algorithme de chiffrement à clé
publique. Si oui, décrire comment.
13.1.2 Réponses :
Question a : le chiffrement à flot est plus adapté à une transmission série car il va chiffrer bit par bit alors que le
chiffrement par blocs va demander d’avoir un certaine taille avant de pouvoir chiffrer. Les algorithmes de chiffrement
à flot sont du coup en général plus rapides que ceux par blocs. Le chiffrement par blocs permet la réutilisation de clé
pour chiffrer plusieurs messages alors que les conditions sur la clé sont beaucoup plus dures avec les chiffrements par
flot.
Exemples d’algorithmes de chiffrement par bloc : DES, AES, blowfish.
Exemples d’algorithmes de chiffrement à flot : RC4, A5/1.
Question b : actuellement, la taille de clé minimale pour ces 2 algorithmes est 1024 bits, même s’il faudrait passer à
2048 bits (pour avoir 112 bits de sécurité). L’intérêt de prendre les courbes elliptiques est que les tailles de clés sont
plus petites (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de 2 points est
10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc qu’à partir
d’une certaine taille de clé.
Question c : pour avoir n bits de sécurité avec une fonction de hachage, il faudra prendre un haché √ de 2n bits
à cause du paradoxe des anniversaires qui montre qu’il y a 50% de chances d’obtenir une collision après 22n = 2n
éléments vus. Comme fonction de hachage, nous pouvons citer MD5 ainsi que la famille SHA : SHA 1, 2 et 3.
Question d : le chiffrement à flot fonctionne en xorant un flot de clé avec le message : c = m⊕k, si la même clé est uti-
lisée pour un autre message m′ , alors un attaquant qui voit passer c et c′ pourra calculer c⊕c′ = m⊕k⊕m′ ⊕k = m⊕m′ .
Imaginons ensuite que l’attaquant arrive à connaı̂tre un des clairs et le chiffré associé, il pourra déchiffrer n’importe
quel message.
Question f : oui et c’est très facile, imaginons que Alice et Bob veulent échanger une clé symétrique :
1. Alice choisit une clé K.
2. Alice envoie la clé K chiffrée avec la clé publique de Bob.
3. Bob reçoit ce message et le déchiffre avec sa clé privée pour récupérer K
Une fois le protocole terminé, les 2 parties ont une clé commune K qu’aucun attaquant n’aura pu récupérer si le
chiffrement asymétrique utilisé est sûr.
Question b : calculer pour un module RSA n = 35 et un exposant public e = 5 l’exposant secret d associé à e.
Calculer le chiffré de 10 puis vérifier son déchiffrement.
Question c : on considère Alice qui utilise un schéma de chiffrement RSA (N, e) avec des paramètres de sécurité
classiques, pour un clair m elle calcule le chiffré de manière normale : c = me (mod N ). Comme elle trouve que faire
des calculs avec des gros nombres c’est long et compliqué, elle fait savoir à tout le monde qu’en ce qui la concerne elle
se ramènerait à chiffrer uniquement des messages m tels que m < 1000. Est-ce que cette façon de procéder change
la sécurité ? Est-ce que Eve qui voit passer des messages chiffrés d’Alice peut déchiffrer les chiffrés d’Alice ? Si oui,
comment ?
13.2.2 Réponses :
Question a :
n=p×q
φ(n) = (p − 1) × (q − 1) = n − p − q + 1
Nous connaissons donc :
p×q =n
p + q = n + 1 − φ(n) Mais, nous savons que (x − x1 )(x − x2 ) = x2 − (x1 + x2 ) × x + x1 × x2
Du coup, nous pouvons former le polynôme : x2 + (φ(n) − n − 1) × x + n et trouver ses racines qui seront p et q.
Question b :
La clé privée est l’inverse de e modulo φ(n). Ici, nous allons chercher l’inverse de 5 modulo φ(35) = 4 × 6 = 24 :
5−1 = 5 car 5 × 5 = 1 (mod 24).
Pour chiffrer, nous allons calculer me (mod n) = 105 (mod 35) = 100 × 100 × 10 = −5 × −5 × 10 = 250 = 5 (mod 35)
Pour déchiffrer, calculons md (mod n) = 55 (mod 35) = 25 × 25 × 5 = 500 = 150 = 10 (mod 35) : le déchiffrement
marche !
Question c :
Oui, cette façon de procéder diminue grandement la sécurité car il est maintenant possible de faire un brute force pour
trouver le texte en clair.
Eve commencerait par calculer une table des chiffrés de tous les messages entre 0 et 999 (car elle connaı̂t la clé publique
et peut donc chiffrer n’importe quel message de son choix). Ensuite, dès qu’elle verra passer le chiffré c, elle le cherchera
dans sa table et pourra récupérer le message associé.
13.3.2 Réponses :
On connaı̂t :
C = 10001110010101
M = ????101010????
K = ????010011???? : obtenue en faisant le XOR de ce que nous connaissons.
Pour finir, il ne reste plus qu’à xorer le chiffré et la clé pour récupérer le texte en clair :
C = 10001110010101
K = 01110100111010
M = 11111010101111
Question 1 : montrer que le protocole fonctionne et que c’est bien la même clé commune qui est calculée. Pour-
quoi ce protocole est potentiellement plus intéressant qu’un diffie-hellman classique pour un téléphone mobile par
exemple ?
Question 2 : montrer que si un attaquant connaı̂t une clé de session d’un tour précédent (il connaı̂t une clé commune
KM B ) pour lesquels il a enregistré des messages, alors il peut se faire passer pour B (indication : l’attaquant peut
rejouer des messages de la session précédente).
Question 3 : montrer qu’en fait un attaquant peut se faire passer pour B connaissant simplement les clés publiques
XB et XM . Qu’en concluez vous pour le protocole ?
13.4.2 Réponses :
Question 1 : nous allons tout simplement simplifier les expressions :
−1
N B N B N B N B
g xM +NM × XM = g xM +NM × g −xM = g xM +NM −xM = g NM = g NM ×NB
−1
NM NM NM NM
g xB +NB × XB = g xB +NB × g −xB = g xB +NB −xB = g NB = g NM ×NB
Ce protocole est plus intéressant qu’un diffie-hellman classique pour un téléphone mobile car le téléphone aura une
exponentiation modulaire à faire : il envoie juste NM + xM au lieu de g puissance ça. Du coup, cela demande moins
de ressources pour le téléphone.
Question 2 :
Connaı̂tre une clé de tour, cela veut dire que l’on connaı̂t KM B = g NM ×NB .
Vu que nous voulons nous faire passer pour la base, une première idée pourrait être d’arriver à dériver la même clé
que le téléphone.
L’idée sera de renvoyer g xB +NB comme premier message (nous ne connaissons ni xB ni NB ).
′
Ensuite, le téléphone va nous envoyer NM + xM
′
NB ×NM
La clé calculée par le téléphone sera : g .
′ ′
Nous savons que g NB ×NM /KM B = g NB ×(NM −NM ) . Nous pouvons calculer NM ′
− NM en faisant NM ′
+ x M − NM − x M
−1
(la différence des 2 message), pour g NB il suffit de calculer g xB +NB × XB . Finalement la clé sera donnée par :
′
(g NB )NM +xM −NM −xM × KM B .
Question 3 :
L’attaquant va envoyer n’importe quel g xB +NB = XB × g NB : la clé dérivée par le téléphone sera g NB ×NM . Pour que
−1 NB ′ ′ ′
l’attaquant la calcule, il peut s’y prendre de la manière suivante : (g NB )NM +xM × (XM ) = g NB ×NM +xM ×NB ×
′ ′ ′
g −xM ×NB = g NB ×NM .
Ce protocole n’est donc absolument pas sécurisé.
Question c : quelles sont sur le papier les différentes structures de groupes possibles ?
Question e : existe-t-il un générateur pour le groupe (un point P tel que 0P, P, 2P, ... engendre le groupe) ? Si
oui, combien de générateurs existe-t-il ? En donner un le cas échéant.
13.5.2 Réponses :
Question a : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à
du RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition
de 2 points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera
donc qu’à partir d’une certaine taille de clé. Pour le schéma, refaire celui au début de la partie sur les courbes elliptiques.
Question b :
y 0 1 2 3 4 x 0 1 2 3 4
y2 0 1 4 4 1 x3 + 4x + 4 4 4 0 3 4
Cette courbe possède donc 8 points : (0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (4, 2), (4, 3), 0.
Question d :
Tout d’abord, si la structure de cette courbe elliptique est isomorphe à Z/1Z ⊕ Z/8Z qui est lui-même isomorphe
à Z/8Z, alors nous aurons φ(8) = 4 générateurs (si nous avons testé 5 points et que nous n’avons pas trouvé de
générateurs ce sera l’autre possibilité).
Il n’y qu’à tester 1P , 2P et 4P car l’ordre d’un point est un diviseur du nombre de points : ici 8.
(0, 2) :
- 2 × (0, 2) : coefficient : 4/(2 × 2) = 1 : (x3 , y3 ) = (1, 1 × −1 − 2) = (1, 2)
- 4 × (0, 2) = 2 × (1, 2) : coefficient : 2/4 = 1/2 = 3 : (x3 , y3 ) = (32 − 2 × 1, 3 × (1 − x3 ) − 2) = (2, 0)
Vu que 1P ̸= 0, 2P ̸= 0 et 4P ̸= 0, nous avons que (0, 2) est un générateur.
La structure de cette courbe elliptique est donc isomorphe à Z/1Z ⊕ Z/8Z.
Question e :
Oui, il y a un générateur, il y en a même φ(8) = 4.
P = (0, 2) est un exemple de générateur.
Question b : êtes-vous d’accord avec Bob et Alice sur la sécurité du protocole ? Justifiez.
13.6.2 Réponses :
Question a : lorsqu’elle reçoit c = r ⊕ k, elle va calculer k ⊕ c, récupérer le résultat et si ce dernier vaut r l’authenti-
fication aura réussi.
Question b : non, une personne qui voit passer les messages peut récupérer la clé : elle récupère r dans le pre-
mier message, puis elle peut obtenir k en interceptant le second message et en calculant k = r ⊕ (r ⊕ k).
Question b : expliquer pourquoi si on utilise du chiffrement à flot, réutiliser le même flot quasi-aléatoire sur différents
message est une mauvaise idée.
Question c : est-ce que la factorisation est un problème difficile à résoudre ? Comparer ce problème à la résolution
du problème du log discret sur un anneau de type Z/nZ ou sur des courbes elliptiques.
Question d : quelle est la complexité de la meilleure attaque connue sur le problème du logarithme discret sur
les courbes elliptiques sur un corps avec de l’ordre de 2n éléments en fonction de n et ce pour le cas d’un ordinateur
classique et aussi dans le cas d’un ordinateur quantique suffisamment puissant.
Question e : on utilise souvent la compression de données pour le stockage d’informations. Supposons qu’on veuille
compresser des données avec du chiffrement. Est-ce qu’il vaut mieux chiffrer et puis compresser ou le contraire.
Question f : qu’est ce que le schéma de partage de clés de Shamir ? donner un exemple d’utilisation de ce schéma.
14.1.2 Réponses :
Question a : L’avantage est la rapidité du chiffrement à clé secrète comparé au chiffrement à clé publique, on gagne
environ un facteur 1000 en temps avec du chiffrement à clé secrète. Quelques exemples d’algorithmes à clé secrète sont
AES et DES, pour les algorithmes à clé publique nous avons par exemple RSA, El-Gamal, Rabin, ...
Question b : le chiffrement à flot fonctionne en xorant un flot de clé avec le message : c = m⊕k, si la même clé est uti-
lisée pour un autre message m′ , alors un attaquant qui voit passer c et c′ pourra calculer c⊕c′ = m⊕k⊕m′ ⊕k = m⊕m′ .
Imaginons ensuite que l’attaquant arrive à connaı̂tre un des clairs et le chiffré associé, il pourra déchiffrer n’importe
quel message.
Question c : oui c’est un problème difficile (il n’existe pas d’algorithme polynomial pour le résoudre sur un or-
dinateur ”conventionel” (non-quantique)). La complexité de la factorisation est L[1/3, (64/9)1/3 ] en utilisant le crible
algébrique. Pour la complexité du logarithme discret, elle est identique car c’est également la méthode du crible √
algébrique qui est utilisée pour le résoudre. En revanche, sur les courbes elliptiques, la meilleure attaque est en O( n)
(avec n le nombre de points de la courbe).
Question d : vu que le corps à 2n éléments, nous pouvons dire que la courbe a environ 2n points (d’après le théorème
de Hasse), et la meilleure attaque connue consiste à trouver 2 couples (c, d) et (c′ , d′ ) tels que cG + dQ = c′ G + d′ Q
(G étant le générateur et Q le point pour lequel on veut résoudre
√ le logarithme). Grâce au paradoxe des anniversaires,
nous savons que cette collision se produit en moyenne en 2n = 2n/2 couples√vus. Pour l’ordinateur quantique, le
meilleur algorithme connu est l’algorithme BHT qui trouver une collision en O( 3 2n = 2n/3 ).
Question e : chiffrer puis compresser ne fonctionnera pas car l’entropie des données après chiffrement sera très
élevée, or, une fonction de compression pourra le mieux compresser quand l’entropie est basse (qu’il y a des zones
prévisibles qui se répètent). Donc, il vaut mieux d’abord compresser et après chiffrer.
Question f : comme son nom l’indique c’est un schéma de partage de clés, donc chaque partie aura un ”morceau”
de la clé et il faudra que toutes les parties réunissent ces morceaux (via de l’interpolation lagrangienne dans le cas de
Shamir) pour pouvoir récupérer la clé et l’utiliser. Un exemple d’application réelle est dans une cérémonie des clés où
toutes les personnes doivent mettre leur carte dans le HSM (Hardware Security Module) pour l’initialiser : génération
des clés les plus importantes.
Question b : on suppose maintenant que lors de ses vacances (d’une durée fixe) un responsable souhaite déléguer
sa signature électronique à son adjoint (un peu comme une procuration). Comment peut-il s’y prendre ? Proposer un
cadre réaliste et proposer une solution. Bien sûr, l’adjoint doit pouvoir signer à la place du responsable mais sans que
le responsable donne sa clé secrète.
14.2.2 Réponses :
Question a : la solution la plus simple consiste à envoyer le document à tous les signataires, récupérer toutes leurs
signatures et les concaténer pour avoir la signature finale.
Le processus de signature serait le suivant : s = s1 ||s2 ||...||sk (avec k le nombre de parties) et si = Sign(ski , m).
Le processus de vérification étant donné le message et la signature serait le suivant : retourner 1 si V erif (pki , m, s) = 1
pour tout i ∈ [1, k].
La longueur de la clé sera k fois celle utilisée pour la signature : imaginons du RSA 1024 bits, les clés publiques et
privées auraient une taille de 1024 × k bits.
La longueur de la signature est k fois la longueur d’une seule signature.
Il n’y a pas d’importance dans l’ordre des signataires.
L’un de signataires triche : on peut dire que tricher correspond à signer à la place de quelqu’un d’autre, ici c’est
impossible à moins de connaı̂tre la clé secrète ou d’arriver à casser la signature sous-jacente.
Question b : nous allons nous placer dans le cas de la signature RSA : pour signer avec RSA, on calcule s = md
(mod n). Pour la vérification on va faire se (mod n) et on va voir si c’est égal au message m.
L’idée pour déléguer sa clé sera d’envoyer d + x × φ(n) pour une valeur de x aléatoire à l’employé : la signature donnera
la même chose car mφ(n) = 1 (mod n) et l’employé ne connaissant ni x ni φ(n) il ne pourra pas récupérer d. Pour la
vérification, on peut laisser se (mod n) (la même clé publique).
Question a : On suppose tout d’abord que Alice et Bob ont en commun la clé K = 102201, on suppose qu’Alice veut
envoyer le message M = 222222 chiffré par la clé K. Que vaut le chiffré de M par K ?
Question b : On suppose maintenant que Eve intercepte un chiffré C = 011101 (mais ne connait pas la clé secrète
utilisée), est-ce que le clair peut valoir M = 102 ?
Question c : Quels sont tous les clairs possibles qui peuvent donner le chiffré C = 011101 ?
Question d : A partir des questions précédentes, montrer qu’un tel schéma n’est pas bon, en ce sens qu’il y a
de l’information qui fuit et que ce schéma n’est pas parfaitement sûr. On pourra montrer que tous les chiffrés c1 , c2
(où c1 est un bit) n’ont pas la même probabilités d’exister.
Question e : Proposer un autre schéma à base de modulo qui serait parfaitement sûr.
14.3.2 Correction :
Question a : nous avons K = 102201 et M = 222222
Commençons par mettre K et M en binaire :
K : 01 00 10 10 00 01
M : 10 10 10 10 10 10
Nous pouvons maintenant faire le xor entre la clé et le message :
C : 11 10 00 00 10 11
Comme vous pouvez le voir nous avons des 11 dans le chiffré qui ne pourront pas être convertirs en éléments de {0, 1, 2}
mais cela n’est pas grave car rien ne nous dit dans le sujet que le chiffré doit être re-converti dans la notation originale.
Question b : mettons nos 2 paramètres sur 2 lignes pour voir comment faire :
C : 01 11 01
M : 01 00 10
Comme vous pouvez le voir, il est impossible que le clair soit la valeur donnée car il faudrait que le second chiffre soit
11 = 3 pour que le XOR fonctionne et donne bien C ce qui est impossible.
Question d : nous allons tout simplement faire comme le prof le dit et lister pour chaque caractère toutes les
possibilités de message et clé qui donnent un certain chiffré :
Pour avoir 00 dans le chiffré : 3 couples (00, 00), (01, 01), (10, 10)
Pour avoir 01 dans le chiffré : 2 couples (01, 00), (00, 01)
Pour avoir 10 dans le chiffré : 2 couples (10, 00), (00, 10)
Pour avoir 11 dans le chiffré : 2 couples (10, 01), (01, 10)
Vous pouvez donc voir qu’il est plus probable d’obtenir 00 ce qui constitue donc une fuite d’informations.
Question e : un schéma qui est parfaitement sûr consiste tout simplement faire M +K (mod 3) pour chaque caractère
du messsage et de la clé.
Si nous reprenons le premier exemple :
K = 102201
M = 222222
Nous avons finalement comme chiffré C = 021120 (le premier 0 est obtenu en faisant 1 + 2 modulo 3).
Re-listons tous les couples possibles :
Pour avoir 0 dans le chiffré : 3 couples (0, 0), (1, 2), (2, 1) marchent.
Pour avoir 1 dans le chiffré : 3 couples (1, 0), (0, 1), (2, 2) marchent.
Pour avoir 2 dans le chiffré : 3 couples (2, 0), (0, 2), (1, 1) marchent.
Nous venons donc de confirmer qu’il s’agit bien d’un schéma de chiffrement sécurisé.
14.4 Exercice 3 - Calcul de la signature RSA avec le théorème des restes chinois :
14.4.1 Sujet :
On considère un module RSA : n = p × q et d l’exposant privé. Soit un message m à signer, on cherche à calculer Smd
(mod n). On note dp = d (mod p − 1), dq = d (mod q − 1) et iq = q −1 (mod p). Soient également Sp = mdp (mod p)
et Sq = mdq (mod q).
Question a : rappeler le théorème des restes chinois, montrer que S (mod p) = Sp et S (mod q) = Sq , expli-
quer alors pourquoion peut retrouver S à partir de Sp et Sq .
Question c : expliquer l’intérêt (en terme de cout calculatoire) de calculer S par cette méthode plutôt que di-
rectement en calculant md (mod n).
14.4.2 Réponses :
Question a :
Le théorème des restes chinois permet de résoudre des systèmes d’équations modulaires : étant donnés k le nombre
d’équations, ni les modules et ai les restes nous pouvons retrouver la valeur de x (mod n1 × ... × nk ) (si tous les ni
Question b :
(Sq + q × (iq × (Sp − Sq ) (mod p))) (mod q) = Sq + 0 = Sq
(Sq + q × (iq × (Sp − Sq ) (mod p))) (mod p) = Sq + Sp − Sq = Sp
Question c :
Le coût d’une exponentiation modulaire si toutes les valeurs sont sur n bits est O(n3 ) : vu que l’exposant d est full-size
ce sera le coût de la signature.
Si elle est réalisée avec la seconde méthode, nous aurons 2 exponentiations modulaires sur des nombres de n/2 bits ce
qui nous donnera une complexité de (n/2)3 × 2 = n3 /4 : 4 fois plus rapide que précédemment (car les autres opérations
sont négligeables par rapport à l’exponentiation full-size).
Question a : donner une description étape par étape de ce que le receveur doit faire en recevant y pour retrou-
ver le message.
Question b : préciser en les justifiant si les propriétés suivantes sont vérifiées pour chacun des protocoles : confiden-
tialité, intégité, non répudiation.
14.5.2 Réponses :
Question a :
Pour le protocole A, on va d’abord commencer par déchiffrer y : dk1 (y) = x || H(k2 || x), à partir de cela on peut
ensuite retrouver x et vérifier son intégrité en calculant H(k2 || x) et en comparant avec la valeur recue.
Pour le protocole B, on va encore une fois commencer par déchiffrer y : dk1 (y) = x || sigkpr (H(x)) ce qui nous permet
une nouvelle fois de récupérer x et nous pouvons ensuite vérifier la signature mais cela ne permet pas de tester l’intégrité.
Question b :
Définition de non-répudiation : il s’agit de l’impossibilité de pouvoir nier avoir reçu / émis un message.
Protocole A :
Confidentialité : oui, car x est chiffré et n’apparaı̂t jamais en clair sur le réseau.
Intégrité : oui, la fonction de hachage va permettre de faire cette vérification et une collision semble difficile à
trouver ne connaissant pas k2 .
Non-répudiation : non, car vu que les 2 parties connaissent les clés k1 et k2 , on ne sait pas quelle partie aurait
pu envoyer le message et du coup les 2 peuvent nier avoir envoyé / reçu.
Protocole B :
Confidentialité : oui, car encore une fois, x est chiffré et n’apparaı̂t pas en clair sur le réseau.
Intégrité : non, il serait possible qu’un attaquant trouve une collision sur le message avec la fonction de hachage.
Non-répudiation : oui, car seul l’envoyer connaı̂t la clé privée kpr et il ne peut donc pas nier son envoi.
14.6 Exercice 5 - Courbes elliptiques :
14.6.1 Sujet :
Question a : quel est l’intérêt des courbes elliptiques en cryptographie ? Rappeler le schéma de fonctionnement de
l’addition et du doublement pour le groupe des opints de la courbe.
Question e : donner un générateur du groupe (un point P tel que 0P, P, 2P, ... engendre le groupe) ? En déduire la
structure de groupe de la courbe.
14.6.2 Réponses :
Question a : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à du
RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de 2
points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc
qu’à partir d’une certaine taille de clé. Pour rappeler le schéma de fonctionnement, reprenez les 2 schémas que nous
avons fait au début.
Question b :
y 0 1 2 3 4 x 0 1 2 3 4
y2 0 1 4 4 1 x3 + x + 2 2 4 2 2 0
Cette courbe possède donc 4 points : (1, 2), (1, 3), (4, 0), 0.
Question c :
Vu qu’il y a 4 points dans la courbe, nous aurons forcément que 4P = 0 pour tous les points.
2 × (1, 2) = (4, 0) : coeff = (3 × 1 + 1)/(2 × 2) = 1 : x3 = 1 − 2 = 4, y3 = 1 × (1 − 4) − 2 = 0.
2 × (1, 3) = (4, 0) : coeff = (3 × 1 + 1)/(2 × 3) = 2/3 = 4 : x3 = 42 − 2 = 4, y3 = 4 × (1 − 4) − 3 = 0.
2 × (4, 0) = 0 car y1 = 0
2×0=0
Question d :
Il y a 2 générateurs dans ce groupe : (1, 2) et (1, 3).
La structure du groupe est donc isomorphe à Z/1Z ⊕ Z/4Z qui est lui-même isomorphe à Z/4Z.
Question b : montrer que le protocole fonctionne (en ce sens que si on connaı̂t le secret, on répond convenable-
ment quoiqu’il arrive).
Question c : donner un exemple où en anticipant un défi, un tricheur peut se faire passer pour Alice avec une
probabilité de 1/q. En déduire que la probabilité de tricher est supérieure à 1/q (on admet par la suite que cette
probabilité est exactement 1/q).
Question d : quel est l’intérêt de de protocole par rapport au protocole de Fiat-Shamir (en terme de nombre de
passes).
14.7.2 Réponses :
Question a : voici le schéma :
Question b :
Il est possible de répondre à tout message vu qu’on envoie simplement (k + a × r) (mod q).
En connaissant la clé, si on envoie g k et y = (k + a × r) : Bob va calculer y × Ar = g y × g −a×r = g k+a×r−a×r = g k = K.
Question c :
Cela veut dire que l’attaquant connaı̂t la valeur du défi r (qui est une constante) mais il ne connaı̂t pas a.
L’attaquant peut commencer par envoyer K = Ar = g −a×r .
Ensuite, il va recevoir le défi r dont il a anticipé une valeur.
L’attaquant va ensuite envoyer y = 0 et du coup Bob va calculer g 0 × Ar = g −a×r qui est bien égal au K envoyé.
Vu qu’il y a q valeurs de r possibles, la probabilité de triche de l’attaquant est 1/q mais on ne peut pas exclure le
fait qu’il lui sera peut être possible de combiner les résultats pour plusieurs valeurs de r ce qui ferait augmenter sa
probabilité de triche.
Question d :
Dans le protocole de Shamir, la probabilité de triche est 1/2, du coup pour avoir une sécurité de n bits, il faut faire n
exécutions du protocole.
Dans le protocole au-dessus, la probabilité de triche est 1/q et q peut être choisi assez grand (par exemple avec un
premier de 1024 bits, on pourrait tout à fait avoir q sur 256 - 512 bits). Du coup avec de telles tailles, la sécurité
voulue peut être obtenue avec un tour de protocole.
Il faut tout de même noter que des exponentiations modulaires sont utilisées dans le second protocole et donc qu’il est
beaucoup plus long que celui de Shamir (pour un tour).
Question e :
La propriété de zero-knowledge est que ces échanges ne doivent rien dévoiler sur la clé : ici du point de vue d’un
adversaire r est aléatoire, la valeur de a est donc masquée totalement.
14.8.2 Réponses :
Il faut tout d’abord modéliser le problème sous forme de système d’équations modulaires :
(
x ≡ 0 (mod 25)
x ≡ −3 (mod 31)
Une fois cela fait, il suffit d’appliquer le théorème des restes chinois pour trouver la solution :
( (
x ≡ 0 (mod 25) 31x ≡ 0 (mod 775)
⇔
x ≡ −3 (mod 31) 25x ≡ −75 (mod 775)
Nous pouvons ensuite additionner les 2 équations ce qui nous donne : 56x = −75 (mod 775).
Question a : rappeler les propriétés importantes des fonctions de hachage. Proposer un protocole simple utilisant
simplement une fonction de hachage permettant de jouer à pile ou face par téléphone.
Question b : pour éviter la possibilité qu’une des deux personnes puisse tricher, de quelles propriétés de la fonc-
tion de hachage a-t-on besoin ? Fonction à sens unique et/ou fonction sans collision ? Justifiez la réponse.
Question c : proposer maintenant un protocole qui utilise seulement le logaritmhe discret. Quels sont les avan-
tages et désavantages d’un tel protocole par rapport à celui d’avant ?
14.9.2 Réponses :
Question a : une fonction de hachage doit avoir 3 propriétés importantes :
Compression
Fonction à sens unique : étant donné y = f (x), il est difficile de retrouver x.
Fonction sans collision : il est difficile de trouver x ̸= x′ tels que H(x) = H(x′ ).
Voici le protocole que l’on pourrait réaliser pour les 2 parties :
Question b :
Bob triche : s’il arrive à connaı̂tre le choix de Alice, il va répondre l’opposé de ce choix. On veut donc que Bob
ne puisse pas retrouver l’entrée de la fonction de hachage à partir du hash (sinon il pourra retrouver le choix
de Alice), du coup on a besoin de la propriété de fonction à sens unique.
Alice triche : elle se rend compte que le résultat n’est pas ce qu’elle veut (pour notre exemple ”face”), elle va
donc essayer de trouver une valeur de r que nous appellerons r′ telle que H(”face”||r′ ) = H(”pile”||r). Cela
revient à trouver une collision : nous voulons donc la propriété de fonction sans collision.
Question c :
Nous ne pouvons pas prendre vpile = 0 et vf ace = 1 sinon Alice pourra très facilement tricher : imaginons que le
résultat sorti soit face, elle va vouloir dire qu’elle avait donné face et pourra envoyer pour ce faire r − 1. Mais je vois
pas trop comment résoudre le problème.
Pour finir, ce protocole n’a que des désavantages par rapport à celui d’avant : il est plus long à cause des exponentia-
tions modulaires, plus difficile à implémenter, ...
Question b : quelles sont les tailles de clé minimales qu’on doit prendre pour les algorithmes RSA ou El-Gamal ?
Quel est l’intérêt des systèmes basés sur les courbes elliptiques par rapport aux précédents ?
Question c : pour une fonction de hachage quelle taille de haché doit-on prendre au minimum et pourquoi ? Donner
des exemples de noms de fonctions de hachage.
Question d : les documents qui sont signés chez un notaire doivent être conservés 99 ans, décrivez de manière
sommaire une manière pour arriver à garder la validité d’une signature pour une période de 99 ans (sans prendre une
seule clé très importante). Quels sont les problèmes auxquels vous pensez pour votre proposition ?
Question e : montrer qu’une fonction de hachage résistante aux collisions n’est pas nécessairement résistante à
la pré-image.
15.1.2 Réponses :
Question a : le chiffrement à flot est plus adapté à une transmission série car il va chiffrer bit par bit alors que le
chiffrement par blocs va demander d’avoir un certaine taille avant de pouvoir chiffrer. Les algorithmes de chiffrement
à flot sont du coup en général plus rapides que ceux par blocs. Le chiffrement par blocs permet la réutilisation de clé
pour chiffrer plusieurs messages alors que les conditions sur la clé sont beaucoup plus dures avec les chiffrements par
flot.
Exemples d’algorithmes de chiffrement par bloc : DES, AES, blowfish.
Exemples d’algorithmes de chiffrement à flot : RC4, A5/1.
Question b : actuellement, la taille de clé minimale pour ces 2 algorithmes est 1024 bits, même s’il faudrait passer à
2048 bits (pour avoir 112 bits de sécurité). L’intérêt de prendre les courbes elliptiques est que les tailles de clés sont
plus petites (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de 2 points est
10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc qu’à partir
d’une certaine taille de clé.
Question c : pour avoir n bits de sécurité avec une fonction de hachage, il faudra prendre un haché √ de 2n bits
à cause du paradoxe des anniversaires qui montre qu’il y a 50% de chances d’obtenir une collision après 22n = 2n
éléments vus. Comme fonction de hachage, nous pouvons citer MD5 ainsi que la famille SHA : SHA 1, 2 et 3.
Question d : une idée serait de signer le document de manière régulière avec une clé différente à chaque fois, cela
demande tout de même de savoir à quelle fréquence changer la signature et aussi plus on avance dans le temps plus il
faudra refaire la signature souvent pour éviter les attaques.
Question e : nous pouvons prendre la fonction de hachage H(x) = x qui prendra des entrées de 512 bits et donnera
512 bits en sortie : elle est résistante aux collisions car il n’y a aucune collision en revanche elle n’est pas du tout
résistante à la pré-image car c’est une fonction linéaire.
Question b : montrer que le protocole fonctionne (en ce sens que si on connaı̂t le secret, on répond convenable-
ment quoiqu’il arrive).
Question c : donner un exemple où en anticipant un défi, un tricheur peut se faire passer pour Alice avec une
probabilité de 1/q. En déduire que la probabilité de tricher est supérieure à 1/q (on admet par la suite que cette
probabilité est exactement 1/q).
Question d : quel est l’intérêt de de protocole par rapport au protocole de Fiat-Shamir (en terme de nombre de
passes).
15.2.2 Réponses :
Question a : voici le schéma :
Question b :
Il est possible de répondre à tout message vu qu’on envoie simplement (k + a × r) (mod q).
En connaissant la clé, si on envoie g k et y = (k + a × r) : Bob va calculer y × Ar = g y × g −a×r = g k+a×r−a×r = g k = K.
Question c :
Cela veut dire que l’attaquant connaı̂t la valeur du défi r (qui est une constante) mais il ne connaı̂t pas a.
L’attaquant peut commencer par envoyer K = Ar = g −a×r .
Ensuite, il va recevoir le défi r dont il a anticipé une valeur.
L’attaquant va ensuite envoyer y = 0 et du coup Bob va calculer g 0 × Ar = g −a×r qui est bien égal au K envoyé.
Vu qu’il y a q valeurs de r possibles, la probabilité de triche de l’attaquant est 1/q mais on ne peut pas exclure le
fait qu’il lui sera peut être possible de combiner les résultats pour plusieurs valeurs de r ce qui ferait augmenter sa
probabilité de triche.
Question d :
Dans le protocole de Shamir, la probabilité de triche est 1/2, du coup pour avoir une sécurité de n bits, il faut faire n
exécutions du protocole.
Dans le protocole au-dessus, la probabilité de triche est 1/q et q peut être choisi assez grand (par exemple avec un
premier de 1024 bits, on pourrait tout à fait avoir q sur 256 - 512 bits). Du coup avec de telles tailles, la sécurité
voulue peut être obtenue avec un tour de protocole.
Il faut tout de même noter que des exponentiations modulaires sont utilisées dans le second protocole et donc qu’il est
beaucoup plus long que celui de Shamir (pour un tour).
Question e :
La propriété de zero-knowledge est que ces échanges ne doivent rien dévoiler sur la clé : ici du point de vue d’un
adversaire r est aléatoire, la valeur de a est donc masquée totalement.
Question a : On suppose tout d’abord que Alice et Bob ont en commun la clé K = 102201, on suppose qu’Alice veut
envoyer le message M = 222222 chiffré par la clé K. Que vaut le chiffré de M par K ?
Question b : On suppose maintenant que Eve intercepte un chiffré C = 011101 (mais ne connait pas la clé secrète
utilisée), est-ce que le clair peut valoir M = 102 ?
Question c : Quels sont tous les clairs possibles qui peuvent donner le chiffré C = 011101 ?
Question d : A partir des questions précédentes, montrer qu’un tel schéma n’est pas bon, en ce sens qu’il y a
de l’information qui fuit et que ce schéma n’est pas parfaitement sûr. On pourra montrer que tous les chiffrés c1 , c2
(où c1 est un bit) n’ont pas la même probabilités d’exister.
Question e : Proposer un autre schéma à base de modulo qui serait parfaitement sûr.
15.3.2 Correction :
Question a : nous avons K = 102201 et M = 222222
Commençons par mettre K et M en binaire :
K : 01 00 10 10 00 01
M : 10 10 10 10 10 10
Nous pouvons maintenant faire le xor entre la clé et le message :
C : 11 10 00 00 10 11
Comme vous pouvez le voir nous avons des 11 dans le chiffré qui ne pourront pas être convertirs en éléments de {0, 1, 2}
mais cela n’est pas grave car rien ne nous dit dans le sujet que le chiffré doit être re-converti dans la notation originale.
Question b : mettons nos 2 paramètres sur 2 lignes pour voir comment faire :
C : 01 11 01
M : 01 00 10
Comme vous pouvez le voir, il est impossible que le clair soit la valeur donnée car il faudrait que le second chiffre soit
11 = 3 pour que le XOR fonctionne et donne bien C ce qui est impossible.
Question d : nous allons tout simplement faire comme le prof le dit et lister pour chaque caractère toutes les
possibilités de message et clé qui donnent un certain chiffré :
Pour avoir 00 dans le chiffré : 3 couples (00, 00), (01, 01), (10, 10)
Pour avoir 01 dans le chiffré : 2 couples (01, 00), (00, 01)
Pour avoir 10 dans le chiffré : 2 couples (10, 00), (00, 10)
Pour avoir 11 dans le chiffré : 2 couples (10, 01), (01, 10)
Vous pouvez donc voir qu’il est plus probable d’obtenir 00 ce qui constitue donc une fuite d’informations.
Question e : un schéma qui est parfaitement sûr consiste tout simplement faire M +K (mod 3) pour chaque caractère
du messsage et de la clé.
Question a : rappeler les propriétés importantes des fonctions de hachage. Proposer un protocole simple utilisant
simplement une fonction de hachage permettant de jouer à pile ou face par téléphone.
Question b : pour éviter la possibilité qu’une des deux personnes puisse tricher, de quelles propriétés de la fonc-
tion de hachage a-t-on besoin ? Fonction à sens unique et/ou fonction sans collision ? Justifiez la réponse.
Question c : proposer maintenant un protocole qui utilise seulement le logaritmhe discret. Quels sont les avan-
tages et désavantages d’un tel protocole par rapport à celui d’avant ?
15.4.2 Réponses :
Question a : une fonction de hachage doit avoir 3 propriétés importantes :
Compression
Fonction à sens unique : étant donné y = f (x), il est difficile de retrouver x.
Fonction sans collision : il est difficile de trouver x ̸= x′ tels que H(x) = H(x′ ).
Voici le protocole que l’on pourrait réaliser pour les 2 parties :
Question b :
Bob triche : s’il arrive à connaı̂tre le choix de Alice, il va répondre l’opposé de ce choix. On veut donc que Bob
ne puisse pas retrouver l’entrée de la fonction de hachage à partir du hash (sinon il pourra retrouver le choix
de Alice), du coup on a besoin de la propriété de fonction à sens unique.
Alice triche : elle se rend compte que le résultat n’est pas ce qu’elle veut (pour notre exemple ”face”), elle va
donc essayer de trouver une valeur de r que nous appellerons r′ telle que H(”face”||r′ ) = H(”pile”||r). Cela
revient à trouver une collision : nous voulons donc la propriété de fonction sans collision.
Question c :
Nous ne pouvons pas prendre vpile = 0 et vf ace = 1 sinon Alice pourra très facilement tricher : imaginons que le
résultat sorti soit face, elle va vouloir dire qu’elle avait donné face et pourra envoyer pour ce faire r − 1. Mais je vois
pas trop comment résoudre le problème.
Pour finir, ce protocole n’a que des désavantages par rapport à celui d’avant : il est plus long à cause des exponentia-
tions modulaires, plus difficile à implémenter, ...
Question b : décrire une attaque dans le cas où le même aléa est utilisé pour signer 2 messages différents. Mon-
trer alors qu’on peut faire un cassage total et retrouver la clé secrète.
15.5.2 Correction :
Question a :
Génération des paramètres : on choisit un nombre premier p sur n bits, on choisit un générateur g d’un sous-groupe
d’ordre q de (Z/pZ)∗. La clé secrète est un nombre aléatoire x choisi entre 1 et p − 2 et la clé publique sera g x (mod p).
Signature d’un message : on va choisit k aléatoire entre 2 et p − 2, il faut que pgcd(k, p − 1) = 1, on pourra ensuite
calculer r = g k (mod p) ainsi que s = (H(m) − x × r) × k −1 (mod p − 1). Si jamais s = 0, refaire la signature avec un
k différent. La signature est le couple (r, s).
Vérification d’une signature : on va totu simplement vérifier que g H(m) = y r × rs (mod p).
Ca marche car H(m) = xr + sk (mod p − 1).
Question b :
Message 1 : r = g k (mod p) et s1 = (H(m1 ) − x × r) × k −1 (mod p − 1)
Message 2 : r = g k (mod p) et s2 = (H(m2 ) − x × r) × k −1 (mod p − 1)
L’attaque est simple, on va faire s1 −s2 = (H(m1 )−x×r−H(m2 )+x×r)×k −1 = (H(m1 )−H(m2 ))×k −1 (mod p−1) et
du coup on pourra récupérer la clé secrète en faisant k −1 = (s1 −s2 )×(H(m1 )−H(m2 ))−1 puis en prenant son inverse.
15.6.2 Correction :
Il faut tout d’abord se souvenir que pour un LFSR, nous avons C = M ⊕ K. K est tout simplement la suite de bits s
générée par le LFSR. Nous avons donc :
c = 10001110010101
m = ????101010????
Si nous faisons un XOR entre ces 2 valeurs, nous obtenons :
s = ????010011????
L’étape suivante va consister à trouver les ai qui vont permettre le calcul de tous les termes de la suite des si . Il
nous est dit que la complexité linéaire est d’au plus 3, commençons donc par 3 valeurs de ai .
Nous allons nous baser sur les bits 5 à 7 : 010.
Grâce à la relation du LFSR nous pouvons créer le système suivant :
Bit 8 : a2 × s5 + a1 × s6 + a0 × s7 = s8 ⇔ a2 × 0 + a1 × 1 + a0 × 0 = 0
Bit 9 : a2 × s6 + a1 × s7 + a0 × s8 = s9 ⇔ a2 × 0 + a1 × 0 + a0 × 1 = 1
Bit 10 : a2 × s7 + a1 × s8 + a0 × s9 = s10 ⇔ a2 × 1 + a1 × 0 + a0 × 0 = 1
Nous pouvons déduire de ces équations que a2 = 1, a1 = 0, a0 = 1.
Question a : pour toutes les méthodes le challenge (M, C, C ′ ) peut être cassé en approximativement 2n (en temps en
ignorant les facteurs logarithmes), expliquez comment vous casseriez le challenge pour haque méthode. Quelle méthode
est la plus facile à casser ?
Question b : supposons que la longueur de clé n est suffisamment large pour que les attaques de la partie a soit
infaisable, quelle est la méthode la plus efficace à utiliser ?
15.7.2 Correction :
Question a :
Le schéma le plus facile à casser est le premier : vu que le chiffrement est réalisé avec la clé k1 ⊕ k2 , c’est comme si on
chiffrait avec une seule clé k3 . Du coup, on peut faire une recherche exhaustive de la clé k3 ce qui se fera en temps 2n
vu qu’elle est de taille n.
Pour le premier schéma, le principe est le même que le double-DES : nous allons faire une attaque par Meet-In-The-
Middle. L’idée va être de diviser la chaı̂ne en M → r → C (pour le premier on utilisera Ek2 et pour le second Ek1 ).
L’attaque consiste ensuite à faire une table de toutes les valeurs de r possibles avec le message M et toutes les clés k2′
possibles (cette table devra être maintenue triée via un arbre binaire par exemple). Ensuite, on va faire un déchiffré
de C avec tous les k2′ possibles et pour chaque valeur r′ obtenue on ira la rechercher dans l’autre table. Obtenir une
correspondance entre la première table et une valeur de la seconde partie nous donne un couple possible (k1 , k2 ).
Pour le dernier schéma, l’idée sera similaire à celle d’avant. Nous allons faire une table des déchiffrés de Ek1 (r) xorées
avec M pour toutes les valeurs de k1 possibles, il y aura le r ⊕ M valide à un endroit de cette table, et il faudra
la garder triée (pour que la recherche se fasse en log(n)). Une fois cela fait, nous allons pour chaque clé k2 faire un
déchiffrement de Ek2 (r ⊕ M ) et rechercher la valeur obtenue dans la table : chaque couple trouvé nous indiquera une
valeur de (k1 , k2 ) possible.
Question b :
Au niveau du temps, la solution la plus rapide sera le second algorithme de chiffrement car il ne demande qu’un seul
chiffrement.
Question a : montrez que H est une fonction résisante aux collisions en supposant que le problème du logarithme dis-
cret dans G est difficile : montrez qu’un attaquant capable de trouver une collision pour H pour des valeurs aléatoires
g1 , ..., gn ∈ G peut être utilisé pour calculer le logarithme discret dans G. Indication : étant donné une paire g, h ∈ G,
votre but est de trouver un α tel que g α = h, choisissez g1 , ..., gn ∈ G de telle sorte qu’une collision sur le H résultant
révélera α.
Question b : soit M un message dans I n , supposons qu’Alice calcule le hash de M (H(M )), maintenant Alice
change une coordonnée de M pour obtenir un nouveau message M’. Montrez qu’Alice peut rapidement calculer H(M ′ )
depuis H(M ) en temps qui est dépendant sur la taille de M. Vous avez juste à montrer que après avoir fait un petit
change au message, il n’y a pas besoin de re-hasher le message entier. Les fonctions de hachage résistantes à ce type
de collisions supportent le ”incremental hashing”.
15.8.2 Correction :
Question a :
′
Trouver une collision pour H revient à trouver x et x′ tels que H(x) = g x1 × ... × g xn = gx′1 × ... × g xn = H(x′ ).
Pour faire cette collision, l’attaquant aura dû trouver de manière efficace x1 + ... + xn = x′1 + ... + x′n (mod q). Mais
la seule façon pour l’attaquant de trouver x1 + ... + xn de manière efficace est de résoudre le problème du logarithme
discret sur le haché H(x) : donc s’il arrive à casser la fonction de hachage, il arrivera à résoudre le problème du
logarithme discret.
Question b :
′
La solution est très simple, soit x′i la partie modifiée, on va tout simplement calculer H(x′ ) = (H(x)/g xi ) × g xi . La
′
division va enlever le facteur g xi et la multiplication va le remplacer par g xi .
Question b : quel est l’intérêt des courbes elliptiques par rapport à un algo de type RSA ? Quelle est la taille
de clé souhaitable pour RSA, AES ou les protocoles basés sur les courbes elliptiques ?
Question d : est-ce qu’en général le chiffrement permet de faire de la signature ? de l’échange de clés ? de l’au-
thentification ? Si oui comment ?
Question e : quelle est la différence entre une fonction de hachage et une signature ?
Question f : expliquer le type de procédure à mettre en place pour qu’une signature signée aujourd’hui soit en-
core valide dans 99 ans ?
16.1.2 Réponses :
Question a : le chiffrement à flot est plus adapté à une transmission série car il va chiffrer bit par bit alors que le
chiffrement par blocs va demander d’avoir un certaine taille avant de pouvoir chiffrer. Les algorithmes de chiffrement
à flot sont du coup en général plus rapides que ceux par blocs. Le chiffrement par blocs permet la réutilisation de clé
pour chiffrer plusieurs messages alors que les conditions sur la clé sont beaucoup plus dures avec les chiffrements par
flot.
Exemples d’algorithmes de chiffrement par bloc : DES (64 bits), AES (128, 192 ou 256 bits), blowfish.
Exemples d’algorithmes de chiffrement à flot : RC4 (entre 40 et 256 bits), A5/1.
Question b : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à
du RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de
2 points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc
qu’à partir d’une certaine taille de clé. Pour le schéma, refaire celui au début de la partie sur les courbes elliptiques.
Pour RSA, la taille de clé minimale est 1024 bits, pour avoir 112 bits de sécurité il en faut plutôt 2048. Pour AES, on
peut choisir l’une des 3 tailles. Pour les courbes elliptiques, si on veut 128 bits de sécurité il faut une clé de taille 256 bits.
Question c : un certificat est un fichier qui contient des informations sur une personne / entité ainsi qu’une clé
publique et il est validé par une tierce partie (l’autorité de certification). Il peut être utilisé pour faire de l’authentifi-
cation serveur / client, ...
Question d :
Signature : cela marche seulement dans le cas de RSA (car le chiffrement et le déchiffrement sont ”les mêmes”) mais
en général non car on ne peut pas forcément chiffrer avec la clef privée.
Échange de clés : oui, Alice va choisir une clé K, elle va la chiffrer avec la clé publique de Bob qui pourra ensuite
déchiffrer avec sa clé privée pour récupérer K.
Authentification : oui, imaginons que Alice veut s’authentifier auprès de Bob, Bob va envoyer le chiffré avec la clé
publique d’Alice d’une valeur aléatoire, puis Alice sera la seule à pouvoir déchiffrer avec sa clef privée.
Question e : une fonction de hachage va permettre de vérifier l’intégrité d’un message / programme, une signa-
ture va permettre d’identifier une personne en particulier. La fonction de hachage peut être utilisée par tout le monde
sur n’importe quel message avec le même résultat, on ne pourra pas identifier la personne ayant calculé le hash.
Question f : une idée serait de signer le document de manière régulière avec une clé différente à chaque fois, cela
demande tout de même de savoir à quelle fréquence changer la signature et aussi plus on avance dans le temps plus
il faudra refaire la signature souvent pour éviter les attaques. Une autre solution est de choisir une clé de taille très
grande de façon à rester sécurisé contre l’augmentation en puissance des ordinateurs.
Question b : montrer que le protocole fonctionne (en ce sens que si on connaı̂t le secret, on répond convenable-
ment quoiqu’il arrive).
Question c : donner un exemple où en anticipant un défi, un tricheur peut se faire passer pour Alice avec une
probabilité de 1/q. En déduire que la probabilité de tricher est supérieure à 1/q (on admet par la suite que cette
probabilité est exactement 1/q).
Question d : quel est l’intérêt de de protocole par rapport au protocole de Fiat-Shamir (en terme de nombre de
passes).
16.2.2 Réponses :
Question a : voici le schéma :
Question b :
Il est possible de répondre à tout message vu qu’on envoie simplement (k + a × r) (mod q).
En connaissant la clé, si on envoie g k et y = (k + a × r) : Bob va calculer y × Ar = g y × g −a×r = g k+a×r−a×r = g k = K.
Question c :
Cela veut dire que l’attaquant connaı̂t la valeur du défi r (qui est une constante) mais il ne connaı̂t pas a.
L’attaquant peut commencer par envoyer K = Ar = g −a×r .
Ensuite, il va recevoir le défi r dont il a anticipé une valeur.
L’attaquant va ensuite envoyer y = 0 et du coup Bob va calculer g 0 × Ar = g −a×r qui est bien égal au K envoyé.
Vu qu’il y a q valeurs de r possibles, la probabilité de triche de l’attaquant est 1/q mais on ne peut pas exclure le
fait qu’il lui sera peut être possible de combiner les résultats pour plusieurs valeurs de r ce qui ferait augmenter sa
probabilité de triche.
Question d :
Dans le protocole de Shamir, la probabilité de triche est 1/2, du coup pour avoir une sécurité de n bits, il faut faire n
exécutions du protocole.
Dans le protocole au-dessus, la probabilité de triche est 1/q et q peut être choisi assez grand (par exemple avec un
premier de 1024 bits, on pourrait tout à fait avoir q sur 256 - 512 bits). Du coup avec de telles tailles, la sécurité
voulue peut être obtenue avec un tour de protocole.
Il faut tout de même noter que des exponentiations modulaires sont utilisées dans le second protocole et donc qu’il est
beaucoup plus long que celui de Shamir (pour un tour).
Question e :
La propriété de zero-knowledge est que ces échanges ne doivent rien dévoiler sur la clé : ici du point de vue d’un
adversaire r est aléatoire, la valeur de a est donc masquée totalement.
Question a : rappeler les propriétés importantes des fonctions de hachage. Proposer un protocole simple utilisant
simplement une fonction de hachage permettant de jouer à pile ou face par téléphone.
Question b : pour éviter la possibilité qu’une des deux personnes puisse tricher, de quelles propriétés de la fonc-
tion de hachage a-t-on besoin ? Fonction à sens unique et/ou fonction sans collision ? Justifiez la réponse.
Question c : proposer maintenant un protocole qui utilise seulement le logaritmhe discret. Quels sont les avan-
tages et désavantages d’un tel protocole par rapport à celui d’avant ?
16.3.2 Réponses :
Question a : une fonction de hachage doit avoir 3 propriétés importantes :
Compression
Fonction à sens unique : étant donné y = f (x), il est difficile de retrouver x.
Fonction sans collision : il est difficile de trouver x ̸= x′ tels que H(x) = H(x′ ).
Voici le protocole que l’on pourrait réaliser pour les 2 parties :
Question b :
Bob triche : s’il arrive à connaı̂tre le choix de Alice, il va répondre l’opposé de ce choix. On veut donc que Bob
ne puisse pas retrouver l’entrée de la fonction de hachage à partir du hash (sinon il pourra retrouver le choix
de Alice), du coup on a besoin de la propriété de fonction à sens unique.
Alice triche : elle se rend compte que le résultat n’est pas ce qu’elle veut (pour notre exemple ”face”), elle va
donc essayer de trouver une valeur de r que nous appellerons r′ telle que H(”face”||r′ ) = H(”pile”||r). Cela
revient à trouver une collision : nous voulons donc la propriété de fonction sans collision.
Question c :
Nous ne pouvons pas prendre vpile = 0 et vf ace = 1 sinon Alice pourra très facilement tricher : imaginons que le
résultat sorti soit face, elle va vouloir dire qu’elle avait donné face et pourra envoyer pour ce faire r − 1. Mais je vois
16.4.2 Réponses :
Question a : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à du
RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de 2
points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc
qu’à partir d’une certaine taille de clé. Pour rappeler le schéma de fonctionnement, reprenez les 2 schémas que nous
avons fait au début.
Question b :
y 0 1 2 3 4 x 0 1 2 3 4
y2 0 1 4 4 1 x3 + x + 2 2 2 3 1 2
Cette courbe possède donc 3 points : (3, 1), (3, 4), 0.
Question c :
D’après le théorème de la courbe elliptique, la seule structure possible pour ce groupe est Z/1Z ⊕ Z/3Z qui possède 2
générateurs.
Question d :
Les 2 seuls générateurs possibles sont (3, 1) et (3, 4.
Nous pouvons calculer 1P , 2P dans chaque cas pour le vérifier :
(3, 1) :
0P = 0
1P = (3, 1)
2P = (3, 1) + (3, 1) = (3, 4) : coeff = 1/2 = 3, x3 = 32 − 2 × 3 = 3, y3 = 3 × (3 − 3) − 1 = 4
(3, 4) :
0P = 0
1P = (3, 4)
2P = (3, 4) + (3, 4) = (3, 1) : coeff = 1/2 = 3, x3 = 32 − 2 × 3 = 3, y3 = 3 × (3 − 3) − 4 = 1
L’idée derrière ce protocole est que le message ne passe jamais en clair (bien évidemment) et également que seul S
peut enlever le x qu’il a rajouté et seul R peut enlever le y qu’il a rajouté.
Question a : pourquoi a-t-on M zx = M (mod P ) ? Soyez complet dans vos explications !
Question b : que se passe-t-il précisément du point de vue mathématique lorsque S élève M xy à la puissance z ?
Question c : quelles sont précisément les opérations mises en oeuvre par R pour enlever y et pourquoi lui permettent-
elels de retrouver M ?
Question d : expliquez en vous servant par exemple du théorème de Bezout, pourquoi x et y doivent être pre-
miers avec P − 1.
Question e : en définitive, à quel schéma à clés publiques vu en cours le procédé décrit par J. H ; Ellis se ramène-t-il ?
Justifiez votre réponse ?
Question f : S et R ont choisir de travailler avec P = 101. Les valeurs utilisées par S sont 3 et 67, celles utilisées par
R sont 13 et 77. Au total, combien de multiplications seront effectuées au cours de l’échange, si les exponentiations se
font par la méthode rapide ?
16.5.2 Correction :
Question a : M zx (mod P ) = M k×(P −1)+1 (mod P ) = (M P −1 )k × M (mod P ) = 1 × M (mod P ) = M (mod P ).
Question c : R commence par trouver w tel que wy = 1 (mod P − 1) puis calcule M yw = M (mod P ).
Question d : supposons que x n’est pas premier avec P −1, la relation de Bézout nous dit qu’il sera possible de trouver
z et a tels que xz + a × (P − 1) = pgcd(x, P − 1), nous voyons donc qu’il sera impossible de trouver un inverse modu-
laire de x car ce dernier n’est pas premier avec P −1 : pgcd(x, P −1) ̸= 1. Le même raisonnement peut être appliqué à y.
Question e : ce schéma est très similaire à l’échange de clé diffie-hellman car les 2 parties génèrent une valeur
aléatoire, font une exponentiation modulaire puis arrivnet à dériver le même message en faisant des opérations sur les
exposants.
Question f : dans une exponentiation rapide, nous aurons 1 multiplication si le bit est à 0 et 2 multiplications
si le bit est à 1. Nous allons donc écrire les différents nombres en binaire et calculer le nombre de multiplications :
M x = M 3 : 3 = 11, 2 multiplications (on retire le premier 1)
M xy = (M x )13 : 13 = 1101, 5 multiplications.
M xyz = (M xy )67 : 67 = 1000011, 8 multiplications.
M wy = (M y )77 : 77 = 1001101, 9 multiplications.
Question b : êtes-vous d’accord avec Bob et Alice sur la sécurité du protocole ? Justifiez.
16.6.2 Réponses :
Question a : lorsqu’elle reçoit c = r ⊕ k, elle va calculer k ⊕ c, récupérer le résultat et si ce dernier vaut r l’authenti-
fication aura réussi.
Question b : non, une personne qui voit passer les messages peut récupérer la clé : elle récupère r dans le pre-
mier message, puis elle peut obtenir k en interceptant le second message et en calculant k = r ⊕ (r ⊕ k).
Question a : calculer pour n = 256 et k = 80 les tailles des clés publiques et privées. Comparer avec les tailles
de clés pour RSA et DSA.
Question b : expliquer comment de manière plus générale on pourrait signer des messages de taille quelconque
en utilisant la méthode précédente.
Question c : justifier que pour une seule signature, la sécurité du schéma repose sur la sécurité de la fonction
de hachage f .
Question e : montrer qu’avec une attaque à messages choisis, en 2 signatures pour 2 messages choisis on peut
récupérer la clé privée. Justifier du coup la notion d’usage unique pour ce protocole.
Question f : en fait ce protocole peut être couplé avec un algorithme (de Merkle) uniquement à base de fonc-
tion de hachage qui permet de signer un nombre quelconque de fois mais signé à l’avance. Quel est l’intérêt de ce
protocole par rapport à ceux de théorie des nombres cités plus haut.
16.7.2 Réponses :
Question a :
Taille de clé privée : nous avons 2k valeurs chacune de taille k, la taille de la clé privée est donc 2k 2 = 12800 dnas
notre cas.
Taille de la clé publique : nous avons 2k valeurs chacune de taille n, la taille de la clé publique sera donc 2kn = 40960
dans notre cas.
Les tailles de clés pour cet algorithme d’authentification sont beaucoup plus grandes que pour RSA et DSA où on est
plus de l’ordre 1024 / 2048 bits.
Question b : il suffit de faier passer le message M à signer dans une fonction de hachage pour récupérer un m
de taille fixe qui pourra ensuite être utilisé dans le protocole de signature.
Question c : si un attaquant arrive à renverser la fonction de hachage, il pourra récupérer la clé secrète yi,j à
partir de la clé publique zi,j . Une fois ceettte clé secrète obtenue, on pourra signer ce que l’no veut.
Question d : prendre k petit est une très mauvaise idée car la taille de la clé privée sera également petite : pour k = 1
on aura 2 bits, pour k = 2 ça fera 8 et pour k = 3 nous en aurons 18, ce qui permettrait une attaque par brute force facile.
Question e : il suffit d’envoyer en premier un message tout à 0 pour récupérer tous les yi,0 et puis un second
message tout à 1 pour récupérer tous les yi,1 et ensuite on pourra créer la signature de n’importe quel message en
utilisant soit yi,0 soit yi,1 en fonction du bit. Il doit être à usage unique car dès lors que 2 messages avec au moins 2
bits de différence sont envoyés on peut créer des signatures pour d’autres messages.
Question f : on peut peut être dire que c’est plus rapide de faire le protocole à base de fonctions de hachage
au lieu de celui à base de théorie des nombres.
Question c : définir en généralisant la définition du b) la notion de signature basée sur l’identité et d’authentifi-
cation basée sur l’identité.
Question d : alors que trouver des schémas de chiffrement basés sur l’identité est un problème difficile, montrer
qu’il est très facile de construire de manière générique (par exemple, à partir d’un schéma quelconque de signature)
des protocoles de signature et d’authentification basés sur l’identité.
16.8.2 Réponses :
Question a : un couplage est une application e : G1 × G1 → G2 avec les 2 propriétés suivantes :
Bilinéarité : ∀P, Q ∈ G1 , ∀a, b ∈ Z∗q , e(aP, bQ) = ab × e(P, Q).
Non-dégénérescence : ∀P ∈ G1 , P ̸= 0 → G2 =< e(P, P ) >
Ils ont tout d’abord été utilisés pour faire des attaques sur les courbes elliptiques (car avec ces couplages, si on sait
résoudre le problème du logarithme discret sur G2, on sait le résoudre sur G1).
Il est possible de l’utiliser pour faire un échange de clé tri-partite (A reçoit bP de B et cP de C et peut calculer abc × P
avec a × e(bP, cP )).
Une autre possibilité est le chiffrement basé sur l’identité.
Question b : un schéma de chiffrement basé sur l’identité est un algorithme de chiffrement asymétrique dans le-
quel la clé publique d’une personne sera un élément de son identité (prénom, nom, numéro de sécurité sociale, ...).
C’est une notion introduite en 1984 par Shamir mais les premiers protocoles n’ont vu le jour qu’en 2001 par Boneh et
Franklin en utilisant des pairings.
Cela repose sur une tierce partie : un PKG (Private Key Generator). Pour chiffrer un message, une personne utilisera
l’identité du destinataire ainsi que la clé publique du PKG. Pour déchiffrer, le destinataire va demander la clé privée
correspondant à son identité au PKG et l’utiliser pour récupérer le message.
Question c : (je suis pas sûr, il me semble qu’on l’a pas fait en cours)
Pour une signature basée sur l’identité, il faut qu’un utilisateur soit capable de vérifier une signature juste en utilisant
l’identité de la personne ayant signé l’élément. Pour signer, une personne utilisera son identité ainsi que la clé privée
qui lui est donnée par le PKG.
Pour de l’authentification basée sur l’identité, l’idée serait d’envoyer un engagement ”normal”, puis on recevrait un
challenge généré sur la base de notre identité, et nous pourrons ensuite nous authentifier en donnant une réponse grâce
Question d : (encore une fois, il me semble qu’on l’a pas fait en cours)
- Setup du PKG : on va d’abord générer pkm et skm à partir du même algorithme de génération de clés que pour la
signature, ce seront les clés du PKG. Ensuite, la clé skid sera le tuple (sk, pk, cert) avec cert = Sign(skm , pk||id), il
n’y aura rien dans pkid .
- Création de la signature : s = (Sign(sk, M ), pk, cert) avec (sk, pk, cert) récupérés depuis skid .
- Vérification de la signature : on récupère (pk, cert, s′ ) depuis la signature, puis on fait V erif (pk, M, s′ ) et V erif (pkm , pk||id, cert)
(on a juste eu besoin de récupérer pkm et l’identité).
Le principe général est le suivant : lorsqu’un utilisateur veut signer, on lui génère un couple de clés et on incorpore
dans la clé privée le certificat prouvant la validité de pk. Ce certificat est ensuite ajouté à la signature pour que tout
le monde puisse vérifier la clé à utiliser.
16.9.2 Réponses :
Il faut tout d’abord modéliser le problème sous forme de système d’équations modulaires :
(
x ≡ 0 (mod 25)
x ≡ −3 (mod 31)
Une fois cela fait, il suffit d’appliquer le théorème des restes chinois pour trouver la solution :
( (
x ≡ 0 (mod 25) 31x ≡ 0 (mod 775)
⇔
x ≡ −3 (mod 31) 25x ≡ −75 (mod 775)
Nous pouvons ensuite additionner les 2 équations ce qui nous donne : 56x = −75 (mod 775).
Question c : qu’est-ce qu’un tiers de confiance, donner des exemples de telles entités.
Question d : est-ce que le chiffrement permet de faire de la signature ? de l’échange de clés ? de l’authentifica-
tion ? Si oui, comment ?
Question e : à quoi sert un schéma de Retrait d’Information Privé (PIR en anglais) ? Donner des exemples d’appli-
cations.
Question f : donner des applications spécifiques des algorithmes de couplage sur les courbes elliptiques.
17.1.2 Réponses :
Question a : un certificat est un document numérique qui va contenir des informations sur une entité ainsi que la clé
publique de cette dernière. Cette clé publique sera signée par une autorité de degré supérieur.
Question b : une chaı̂ne de certificats contient le certificat de l’entité, puis le certificat utilisé pour signer le cer-
tificat de l’entité, puis le certificat utilisé pour signer ce certificat et ainsi de suite. Pour moi, on l’utilise pour vérifier
toute la chaı̂ne de confiance.
Question c : un tiers de confiance est comme son nom l’indique une entité tierce dont on va supposer qu’elle se
comporte de manière honête. Dans le cadre de la certification, un tiers de confiance entre un client et un serveur serait
l’autorité de certification qui est trusted par le client et qui lui permettra d’accepter le certificat du serveur.
Question d :
Signature : cela marche seulement dans le cas de RSA (car le chiffrement et le déchiffrement sont ”les mêmes”) mais
en général non car on ne peut pas forcément chiffrer avec la clef privée.
Échange de clés : oui, Alice va choisir une clé K, elle va la chiffrer avec la clé publique de Bob qui pourra ensuite
déchiffrer avec sa clé privée pour récupérer K.
Authentification : oui, imaginons que Alice veut s’authentifier auprès de Bob, Bob va envoyer le chiffré avec la clé
publique d’Alice d’une valeur aléatoire, puis Alice sera la seule à pouvoir déchiffrer avec sa clef privée.
Question e : l’idée est que l’on veut laisser un utilisateur récupérer des informations d’une base de données sans
que la base de données sache quelle information nous avons retirée. Un exemple de protocole pour le résoudre est celui
d’Ostrovsky et Kushilevitz mais pour être efficace il faut avoir beaucoup de données de petite taille. C’est donc utile
dans le cadre des DNS, des données médicales, ...
Question f : ils ont tout d’abord été utilisés pour faire des attaques sur les courbes elliptiques (car avec ces couplages,
si on sait résoudre le problème du logarithme discret sur G2, on sait le résoudre sur G1).
Il est possible de l’utiliser pour faire un échange de clé tri-partite (A reçoit bP de B et cP de C et peut calculer abc × P
avec a × e(bP, cP )).
Une autre possibilité est le chiffrement basé sur l’identité.
Question b : montrer que le protocole fonctionne (en ce sens que si on connaı̂t le secret, on répond convenable-
ment quoiqu’il arrive).
Question c : donner un exemple où en anticipant un défi, un tricheur peut se faire passer pour Alice avec une
probabilité de 1/q. En déduire que la probabilité de tricher est supérieure à 1/q (on admet par la suite que cette
probabilité est exactement 1/q).
Question d : quel est l’intérêt de de protocole par rapport au protocole de Fiat-Shamir (en terme de nombre de
passes).
17.2.2 Réponses :
Question a : voici le schéma :
Question b :
Il est possible de répondre à tout message vu qu’on envoie simplement (k + a × r) (mod q).
En connaissant la clé, si on envoie g k et y = (k + a × r) : Bob va calculer y × Ar = g y × g −a×r = g k+a×r−a×r = g k = K.
Question c :
Cela veut dire que l’attaquant connaı̂t la valeur du défi r (qui est une constante) mais il ne connaı̂t pas a.
L’attaquant peut commencer par envoyer K = Ar = g −a×r .
Ensuite, il va recevoir le défi r dont il a anticipé une valeur.
L’attaquant va ensuite envoyer y = 0 et du coup Bob va calculer g 0 × Ar = g −a×r qui est bien égal au K envoyé.
Vu qu’il y a q valeurs de r possibles, la probabilité de triche de l’attaquant est 1/q mais on ne peut pas exclure le
fait qu’il lui sera peut être possible de combiner les résultats pour plusieurs valeurs de r ce qui ferait augmenter sa
probabilité de triche.
Question d :
Dans le protocole de Shamir, la probabilité de triche est 1/2, du coup pour avoir une sécurité de n bits, il faut faire n
exécutions du protocole.
Dans le protocole au-dessus, la probabilité de triche est 1/q et q peut être choisi assez grand (par exemple avec un
premier de 1024 bits, on pourrait tout à fait avoir q sur 256 - 512 bits). Du coup avec de telles tailles, la sécurité
voulue peut être obtenue avec un tour de protocole.
Il faut tout de même noter que des exponentiations modulaires sont utilisées dans le second protocole et donc qu’il est
beaucoup plus long que celui de Shamir (pour un tour).
Question e :
La propriété de zero-knowledge est que ces échanges ne doivent rien dévoiler sur la clé : ici du point de vue d’un
adversaire r est aléatoire, la valeur de a est donc masquée totalement.
Question a : quelle est la différence entre le partage de secret et l’échange de clé ? Donner un exemple d’appli-
cation du partage de secret.
Question c : on suppose qu’un état major (composé de 2 généraux, 4 colonels et 16 capitaines) a la possibilité
de faire tirer un missile ultra-destructeur, le code du missile est un secret partagé, qui ne peut être activé que dans
certains cas :
1. Les généraux le souhaitent.
2. Les deux colonels le souhaitent et un seul général.
3. Les 16 capitaines le souhaitent.
4. 1 général et les 8 capitaines le souhaitent.
1) Proposer une solution en utilisant le schéma de partage de secret de Shamir qui permet de résoudre ce problème.
2) Dans votre solution, combien faudrait-il de colonels avec 12 capitaines pour retrouver le secret ?
3) Avec ce type d’approche, on aura toujours le cas ou un grand nombre de capitaine pourra toujours trouver le secret,
comment pourrait-on faire pour que quoiqu’il arrive, il y ait au moins un général qui collabore pour retrouver le secret ?
17.3.2 Réponses :
Question a : pour un échange de clé, on veut pouvoir créer une clé qui sera connue de 2 personnes sans connaı̂tre
un secret auparavant. Pour le partage de secret chaque personne aura des bouts de secret et ce dernier ne pourra être
re-constitué que si un certain nombre de bouts de secrets sont récupérés.
Un exemple d’application réelle est dans une cérémonie des clés où toutes les personnes doivent mettre leur carte dans
le HSM (Hardware Security Module) pour l’initialiser : génération des clés les plus importantes.
Question b : dans le schéma de partage de secret de Shamir, k sera le nombre de bouts de secret à rejoindre pour
obtenir le secret et n le nombre de bouts de secret total. L’idée est donc de créer un polynôme P de degré k − 1 dont
les coefficients seront aléatoires, puis de prendre n points aléatoires sur ce polynôme (on prendra un x aléatoire, on cal-
culera P (x) et le bout de secret sera la paire (x, f (x))). Le secret commun sera le coefficient constant du polynôme P [0].
Question c :
1) Une solution simple consiste à prendre 8 bouts de secrets par général, 4 bouts de secret par colonel et 1 bout de
secret par capitaine. Il faudra dans chacun des cas 16 bouts de secret pour reconstituer le secret, on choisira donc un
polynôme aléatoire de degré k = 15 puis on devra donner 48 bouts de secret au total.
2) Dans cette solution, il faudra juste un seul colonel avec les 12 capitaines pour retrouver le secret. Le colonel va
ajouter ses 4 secrets aux 12 des capitaines, ce qui en fait 16 et ce qui est suffisant pour obtenir le secret.
3) On pourrait peut être faire un partage de secret en plusieurs étapes : on donnerait 1 bout de secret à chaque
capitaine et si les 16 capitaines se mettent d’accord, ils peuvent retrouver un bout de secret d’une importance plus
grande. Ensuite, chaque capitaine aura un bout de secret et il faudra 2 de ces bouts de secret d’importance plus grande
pour retrouver le secret final.
Question e : donner un générateur du groupe (un point P tel que 0P, P, 2P, ... engendre le groupe) ? En déduire la
17.4.2 Réponses :
Question a : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à du
RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de 2
points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc
qu’à partir d’une certaine taille de clé. Pour rappeler le schéma de fonctionnement, reprenez les 2 schémas que nous
avons fait au début.
Question b :
y 0 1 2 3 4 x 0 1 2 3 4
y2 0 1 4 4 1 x3 + x + 2 2 4 2 2 0
Cette courbe possède donc 4 points : (1, 2), (1, 3), (4, 0), 0.
Question c :
Vu qu’il y a 4 points dans la courbe, nous aurons forcément que 4P = 0 pour tous les points.
2 × (1, 2) = (4, 0) : coeff = (3 × 1 + 1)/(2 × 2) = 1 : x3 = 1 − 2 = 4, y3 = 1 × (1 − 4) − 2 = 0.
2 × (1, 3) = (4, 0) : coeff = (3 × 1 + 1)/(2 × 3) = 2/3 = 4 : x3 = 42 − 2 = 4, y3 = 4 × (1 − 4) − 3 = 0.
2 × (4, 0) = 0 car y1 = 0
2×0=0
Question d :
Il y a 2 générateurs dans ce groupe : (1, 2) et (1, 3).
La structure du groupe est donc isomorphe à Z/1Z ⊕ Z/4Z qui est lui-même isomorphe à Z/4Z.
Question a : donner une attaque en O(2n/2 ) pour la fonction de hachage h qui permet de construire deux mes-
sages avec deux significations choisies différentes mais avec le même haché.
Question b : montrer comment l’attaque du a. peut être utilise pour abuser un vérificateur de signature (exemple :
”faites un virement de 10000 euros” au lieu de ”faites un virement de 100 euros”).
17.5.2 Réponses :
Questionpa : l’idée va être de se baser sur l’algorithme de détection du rho de Pollard dont la taille du cycle est en
moyenne π × N/8 avec N le nombre d’éléments de l’ensemble. Du coup pour notre fonction de hachage la complexité
sera de O(2n/2 ).
L’idée sera de partir de la signification choisie, de calculer son hash, de calculer une nouvelle signification similaire à
la première à partir de ce hash (pour une image, on pourrait partir de l’image de base et ajouter les bits du hash aux
bits de poids faible des pixels) et ainsi de suite.
Ensuite, il faudra trouver le point de départ du cycle et nous aurons 2 antécédents qui seront des images différentes
mais qui donneront le même hash :
Question b : nous savons que la signature demande tout d’abord de calculer le hash du message et ensuite d’appli-
quer l’algorithme de signature. L’idée sera de prendre un message pour lequel nous avons la signature associée puis
générer un autre message avec une signification similaire qui aura le même hash (nous avons vu comment faire cela à
la question précédente) et ce dernier pourra donc être présenté avec la même signature que le premier !
Question c : pour résister à cette attaque, il faut choisir n de sorte à ce que la taille du cycle soit trop grande
en terme de temps de calcul. Pour avoir une sécurité de k bits, il faudrait prendre une fonction de hachage dont la
taille du hash serait n = 2k.
Question 1 : montrer que le protocole fonctionne et que c’est bien la même clé commune qui est calculée. Pour-
quoi ce protocole est potentiellement plus intéressant qu’un diffie-hellman classique pour un téléphone mobile par
exemple ?
Question 2 : montrer que si un attaquant connaı̂t une clé de session d’un tour précédent (il connaı̂t une clé commune
KM B ) pour lesquels il a enregistré des messages, alors il peut se faire passer pour B (indication : l’attaquant peut
rejouer des messages de la session précédente).
Question 3 : montrer qu’en fait un attaquant peut se faire passer pour B connaissant simplement les clés publiques
XB et XM . Qu’en concluez vous pour le protocole ?
17.6.2 Réponses :
Question 1 : nous allons tout simplement simplifier les expressions :
−1
NB NB N B N B
g xM +NM × XM = g xM +NM × g −xM = g xM +NM −xM = g NM = g NM ×NB
−1
NM N M N M N M
g xB +NB × XB = g xB +NB × g −xB = g xB +NB −xB = g NB = g NM ×NB
Ce protocole est plus intéressant qu’un diffie-hellman classique pour un téléphone mobile car le téléphone aura une
exponentiation modulaire à faire : il envoie juste NM + xM au lieu de g puissance ça. Du coup, cela demande moins
de ressources pour le téléphone.
Question 2 :
Connaı̂tre une clé de tour, cela veut dire que l’on connaı̂t KM B = g NM ×NB .
Vu que nous voulons nous faire passer pour la base, une première idée pourrait être d’arriver à dériver la même clé
que le téléphone.
L’idée sera de renvoyer g xB +NB comme premier message (nous ne connaissons ni xB ni NB ).
′
Ensuite, le téléphone va nous envoyer NM + xM
′
NB ×NM
La clé calculée par le téléphone sera : g .
′ ′
Nous savons que g NB ×NM /KM B = g NB ×(NM −NM ) . Nous pouvons calculer NM ′
− NM en faisant NM′
+ xM − NM − xM
NB xB +NB −1
(la différence des 2 message), pour g il suffit de calculer g × XB . Finalement la clé sera donnée par :
′
(g NB )NM +xM −NM −xM × KM B .
Question 3 :
L’attaquant va envoyer n’importe quel g xB +NB = XB × g NB : la clé dérivée par le téléphone sera g NB ×NM . Pour que
−1 NB ′ ′ ′
l’attaquant la calcule, il peut s’y prendre de la manière suivante : (g NB )NM +xM × (XM ) = g NB ×NM +xM ×NB ×
′ ′ ′
−xM ×NB NB ×NM
g =g .
Ce protocole n’est donc absolument pas sécurisé.
Question b : êtes-vous d’accord avec Bob et Alice sur la sécurité du protocole ? Justifiez ?
17.7.2 Correction :
Question a : soit c = r ⊕ k, Alice va tout simplement calculer c ⊕ k et voir si c’est égal à r : si oui elle sait que c’est
bien Bob.
Question b : absolument pas, un attaquant qui voit passer le premier message contenant seulement r et le se-
cond message contenant r ⊕ k peut très bien calculer r ⊕ (r ⊕ k) = k et donc obtenir la clé secrète (ce qui est un peu
con).
Question a : donner une description étape par étape de ce que le receveur doit faire en recevant y pour retrou-
ver le message.
Question b : préciser en les justifiant si les propriétés suivantes sont vérifiées pour chacun des protocoles : confiden-
tialité, intégité, non répudiation.
17.8.2 Réponses :
Question a :
Pour le protocole A, on va d’abord commencer par déchiffrer y : dk1 (y) = x || H(k2 || x), à partir de cela on peut
ensuite retrouver x et vérifier son intégrité en calculant H(k2 || x) et en comparant avec la valeur recue.
Pour le protocole B, on va encore une fois commencer par déchiffrer y : dk1 (y) = x || sigkpr (H(x)) ce qui nous permet
une nouvelle fois de récupérer x et nous pouvons ensuite vérifier la signature mais cela ne permet pas de tester l’intégrité.
Question b :
Définition de non-répudiation : il s’agit de l’impossibilité de pouvoir nier avoir reçu / émis un message.
Protocole A :
Confidentialité : oui, car x est chiffré et n’apparaı̂t jamais en clair sur le réseau.
Intégrité : oui, la fonction de hachage va permettre de faire cette vérification et une collision semble difficile à
trouver ne connaissant pas k2 .
Non-répudiation : non, car vu que les 2 parties connaissent les clés k1 et k2 , on ne sait pas quelle partie aurait
pu envoyer le message et du coup les 2 peuvent nier avoir envoyé / reçu.
Protocole B :
Confidentialité : oui, car encore une fois, x est chiffré et n’apparaı̂t pas en clair sur le réseau.
Intégrité : non, il serait possible qu’un attaquant trouve une collision sur le message avec la fonction de hachage.
Non-répudiation : oui, car seul l’envoyer connaı̂t la clé privée kpr et il ne peut donc pas nier son envoi.
Question b : expliquer pourquoi si on utilise du chiffrement à flot, réutiliser le même flot quasi-aléatoire sur différents
message est une mauvaise idée.
Question c : est-ce que la factorisation est un problème difficile à résoudre ? Comparer ce problème à la résolution
du problème du log discret sur un anneau de type Z/nZ ou sur des courbes elliptiques.
Question d : quelle est la complexité de la meilleure attaque connue sur le problème du logarithme discret sur
les courbes elliptiques sur un corps avec de l’ordre de 2n éléments en fonction de n et ce pour le cas d’un ordinateur
classique et aussi dans le cas d’un ordinateur quantique suffisamment puissant.
Question f : on utilise souvent la compression de données pour le stockage d’informations. Supposons qu’on veuille
compresser des données avec du chiffrement. Est-ce qu’il vaut mieux chiffrer et puis compresser ou le contraire.
18.1.2 Correction :
Question a : L’avantage est la rapidité du chiffrement à clé secrète comparé au chiffrement à clé publique, on gagne
environ un facteur 1000 en temps avec du chiffrement à clé secrète. Quelques exemples d’algorithmes à clé secrète sont
AES et DES, pour les algorithmes à clé publique nous avons par exemple RSA, El-Gamal, Rabin, ...
Question b : le chiffrement à flot fonctionne en xorant un flot de clé avec le message : c = m⊕k, si la même clé est uti-
lisée pour un autre message m′ , alors un attaquant qui voit passer c et c′ pourra calculer c⊕c′ = m⊕k⊕m′ ⊕k = m⊕m′ .
Imaginons ensuite que l’attaquant arrive à connaı̂tre un des clairs et le chiffré associé, il pourra déchiffrer n’importe
quel message.
Question c : oui c’est un problème difficile (il n’existe pas d’algorithme polynomial pour le résoudre sur un or-
dinateur ”conventionel” (non-quantique)). La complexité de la factorisation est L[1/3, (64/9)1/3 ] en utilisant le crible
algébrique. Pour la complexité du logarithme discret, elle est identique car c’est également la méthode du crible √
algébrique qui est utilisée pour le résoudre. En revanche, sur les courbes elliptiques, la meilleure attaque est en O( n)
(avec n le nombre de points de la courbe).
Question d : vu que le corps à 2n éléments, nous pouvons dire que la courbe a environ 2n points (d’après le théorème
de Hasse), et la meilleure attaque connue consiste à trouver 2 couples (c, d) et (c′ , d′ ) tels que cG + dQ = c′ G + d′ Q
(G étant le générateur et Q le point pour lequel on veut résoudre
√ le logarithme). Grâce au paradoxe des anniversaires,
nous savons que cette collision se produit en moyenne en 2n = 2n/2 couples√vus. Pour l’ordinateur quantique, le
meilleur algorithme connu est l’algorithme BHT qui trouver une collision en O( 3 2n = 2n/3 ).
Question e : signer permet de garantir l’identité de la personne qui a réalisé la signature alors qu’un hash peut
être calculé par n’importe quelle personne.
Question f : chiffrer puis compresser ne fonctionnera pas car l’entropie des données après chiffrement sera très
élevée, or, une fonction de compression pourra le mieux compresser quand l’entropie est basse (qu’il y a des zones
prévisibles qui se répètent). Donc, il vaut mieux d’abord compresser et après chiffrer.
Question b : on suppose maintenant que lors de ses vacances (d’une durée fixe) un responsable souhaite déléguer
sa signature électronique à son adjoint (un peu comme une procuration). Comment peut-il s’y prendre ? Proposer un
cadre réaliste et proposer une solution. Bien sûr, l’adjoint doit pouvoir signer à la place du responsable mais sans que
18.2.2 Réponses :
Question a : la solution la plus simple consiste à envoyer le document à tous les signataires, récupérer toutes leurs
signatures et les concaténer pour avoir la signature finale.
Le processus de signature serait le suivant : s = s1 ||s2 ||...||sk (avec k le nombre de parties) et si = Sign(ski , m).
Le processus de vérification étant donné le message et la signature serait le suivant : retourner 1 si V erif (pki , m, s) = 1
pour tout i ∈ [1, k].
La longueur de la clé sera k fois celle utilisée pour la signature : imaginons du RSA 1024 bits, les clés publiques et
privées auraient une taille de 1024 × k bits.
La longueur de la signature est k fois la longueur d’une seule signature.
Il n’y a pas d’importance dans l’ordre des signataires.
L’un de signataires triche : on peut dire que tricher correspond à signer à la place de quelqu’un d’autre, ici c’est
impossible à moins de connaı̂tre la clé secrète ou d’arriver à casser la signature sous-jacente.
Question b : nous allons nous placer dans le cas de la signature RSA : pour signer avec RSA, on calcule s = md
(mod n). Pour la vérification on va faire se (mod n) et on va voir si c’est égal au message m.
L’idée pour déléguer sa clé sera d’envoyer d + x × φ(n) pour une valeur de x aléatoire à l’employé : la signature donnera
la même chose car mφ(n) = 1 (mod n) et l’employé ne connaissant ni x ni φ(n) il ne pourra pas récupérer d. Pour la
vérification, on peut laisser se (mod n) (la même clé publique).
Question a : On suppose tout d’abord que Alice et Bob ont en commun la clé K = 102201, on suppose qu’Alice veut
envoyer le message M = 222222 chiffré par la clé K. Que vaut le chiffré de M par K ?
Question b : On suppose maintenant que Eve intercepte un chiffré C = 011101 (mais ne connait pas la clé secrète
utilisée), est-ce que le clair peut valoir M = 102 ?
Question c : Quels sont tous les clairs possibles qui peuvent donner le chiffré C = 011101 ?
Question d : A partir des questions précédentes, montrer qu’un tel schéma n’est pas bon, en ce sens qu’il y a
de l’information qui fuit et que ce schéma n’est pas parfaitement sûr. On pourra montrer que tous les chiffrés c1 , c2
(où c1 est un bit) n’ont pas la même probabilités d’exister.
Question e : Proposer un autre schéma à base de modulo qui serait parfaitement sûr.
18.3.2 Correction :
Question a : nous avons K = 102201 et M = 222222
Commençons par mettre K et M en binaire :
K : 01 00 10 10 00 01
M : 10 10 10 10 10 10
Nous pouvons maintenant faire le xor entre la clé et le message :
C : 11 10 00 00 10 11
Comme vous pouvez le voir nous avons des 11 dans le chiffré qui ne pourront pas être convertirs en éléments de {0, 1, 2}
mais cela n’est pas grave car rien ne nous dit dans le sujet que le chiffré doit être re-converti dans la notation originale.
Question b : mettons nos 2 paramètres sur 2 lignes pour voir comment faire :
C : 01 11 01
M : 01 00 10
Comme vous pouvez le voir, il est impossible que le clair soit la valeur donnée car il faudrait que le second chiffre soit
11 = 3 pour que le XOR fonctionne et donne bien C ce qui est impossible.
C[2] = 01 : 2 possibilités (M [2], K[2]) = (00, 01) et (M [2], K[2]) = (01, 00)
Comme vous pouvez le voir, nous avons donc 2 × 2 × 2 = 8 possibilités de couples (M, K) qui pourraient donner ce
chiffré :
M = 00 10 00, K = 01 01 01
M = 01 10 00, K = 00 01 01
M = 00 01 00, K = 01 10 01
M = 01 01 00, K = 00 10 01
M = 00 10 01, K = 01 01 00
M = 01 10 01, K = 00 01 00
M = 00 01 01, K = 01 10 00
M = 01 01 01, K = 00 10 00
Question d : nous allons tout simplement faire comme le prof le dit et lister pour chaque caractère toutes les
possibilités de message et clé qui donnent un certain chiffré :
Pour avoir 00 dans le chiffré : 3 couples (00, 00), (01, 01), (10, 10)
Pour avoir 01 dans le chiffré : 2 couples (01, 00), (00, 01)
Pour avoir 10 dans le chiffré : 2 couples (10, 00), (00, 10)
Pour avoir 11 dans le chiffré : 2 couples (10, 01), (01, 10)
Vous pouvez donc voir qu’il est plus probable d’obtenir 00 ce qui constitue donc une fuite d’informations.
Question e : un schéma qui est parfaitement sûr consiste tout simplement faire M +K (mod 3) pour chaque caractère
du messsage et de la clé.
Si nous reprenons le premier exemple :
K = 102201
M = 222222
Nous avons finalement comme chiffré C = 021120 (le premier 0 est obtenu en faisant 1 + 2 modulo 3).
Re-listons tous les couples possibles :
Pour avoir 0 dans le chiffré : 3 couples (0, 0), (1, 2), (2, 1) marchent.
Pour avoir 1 dans le chiffré : 3 couples (1, 0), (0, 1), (2, 2) marchent.
Pour avoir 2 dans le chiffré : 3 couples (2, 0), (0, 2), (1, 1) marchent.
Nous venons donc de confirmer qu’il s’agit bien d’un schéma de chiffrement sécurisé.
18.4 Exercice 3 - Calcul de la signature RSA avec le théorème des restes chinois :
18.4.1 Sujet :
On considère un module RSA : n = p × q et d l’exposant privé. Soit un message m à signer, on cherche à calculer Smd
(mod n). On note dp = d (mod p − 1), dq = d (mod q − 1) et iq = q −1 (mod p). Soient également Sp = mdp (mod p)
et Sq = mdq (mod q).
Question a : rappeler le théorème des restes chinois, montrer que S (mod p) = Sp et S (mod q) = Sq , expli-
quer alors pourquoion peut retrouver S à partir de Sp et Sq .
Question c : expliquer l’intérêt (en terme de cout calculatoire) de calculer S par cette méthode plutôt que di-
rectement en calculant md (mod n).
18.4.2 Réponses :
Question a :
Le théorème des restes chinois permet de résoudre des systèmes d’équations modulaires : étant donnés k le nombre
d’équations, ni les modules et ai les restes nous pouvons retrouver la valeur de x (mod n1 × ... × nk ) (si tous les ni
sont premiers entre eux) en calculant (via la méthode de Gauss) :
Question b :
(Sq + q × (iq × (Sp − Sq ) (mod p))) (mod q) = Sq + 0 = Sq
(Sq + q × (iq × (Sp − Sq ) (mod p))) (mod p) = Sq + Sp − Sq = Sp
Question c :
Le coût d’une exponentiation modulaire si toutes les valeurs sont sur n bits est O(n3 ) : vu que l’exposant d est full-size
ce sera le coût de la signature.
Si elle est réalisée avec la seconde méthode, nous aurons 2 exponentiations modulaires sur des nombres de n/2 bits ce
qui nous donnera une complexité de (n/2)3 × 2 = n3 /4 : 4 fois plus rapide que précédemment (car les autres opérations
sont négligeables par rapport à l’exponentiation full-size).
Question a : donner une description étape par étape de ce que le receveur doit faire en recevant y pour retrou-
ver le message.
Question b : préciser en les justifiant si les propriétés suivantes sont vérifiées pour chacun des protocoles : confiden-
tialité, intégité, non répudiation.
18.5.2 Réponses :
Question a :
Pour le protocole A, on va d’abord commencer par déchiffrer y : dk1 (y) = x || H(k2 || x), à partir de cela on peut
ensuite retrouver x et vérifier son intégrité en calculant H(k2 || x) et en comparant avec la valeur recue.
Pour le protocole B, on va encore une fois commencer par déchiffrer y : dk1 (y) = x || sigkpr (H(x)) ce qui nous permet
une nouvelle fois de récupérer x et nous pouvons ensuite vérifier la signature mais cela ne permet pas de tester l’intégrité.
Question b :
Définition de non-répudiation : il s’agit de l’impossibilité de pouvoir nier avoir reçu / émis un message.
Protocole A :
Confidentialité : oui, car x est chiffré et n’apparaı̂t jamais en clair sur le réseau.
Intégrité : oui, la fonction de hachage va permettre de faire cette vérification et une collision semble difficile à
trouver ne connaissant pas k2 .
Non-répudiation : non, car vu que les 2 parties connaissent les clés k1 et k2 , on ne sait pas quelle partie aurait
pu envoyer le message et du coup les 2 peuvent nier avoir envoyé / reçu.
Protocole B :
Confidentialité : oui, car encore une fois, x est chiffré et n’apparaı̂t pas en clair sur le réseau.
Intégrité : non, il serait possible qu’un attaquant trouve une collision sur le message avec la fonction de hachage.
Non-répudiation : oui, car seul l’envoyer connaı̂t la clé privée kpr et il ne peut donc pas nier son envoi.
Question a : calculer pour n = 256 et k = 80 les tailles des clés publiques et privées. Comparer aux tailles des
clés pour RSA ou DSA.
Question b : expliquer comment de manière plus générale on pourrait signer des messages de taille quelconque
Question c : justifier que pour 1 seule signature, la sécurité du schéma repose sur la sécurité de la fonction de
hachage f .
Question e : montrer qu’en prenant une attaque à message choisi en deux signatures pour 2 messages choisis on
peut récupérer toute la clé publique. Justifier du coup la notion d’usage unique pour ce protocole.
Question f : en fait, ce protocole peut être couplé avec un algorithme (de Merkle) uniquement à base de fonc-
tion de hachage qui permet de signer un nombre quelconque de fois mais fixé à l’avance. Quel est l’intérêt de ce type
de protocole par rapport aux protocoles classiques de la théorie des nombres cités plus haut.
18.6.2 Réponses :
Question a :
Pour la clé publique, nous avons 2k valeurs yi,j chacune sur k bits, du coup cela représente 2k 2 bits ce qui pour
l’exemple donné fait 2 × 802 = 12800 bits (ce qui nous donne 1600 octets).
Pour la clé privée, nous aurons 2k valeurs zi,j mais cette fois-ci de taille n bits, du coup la clé publique aura une taille
de 2k × n bits ce qui pour notre exemple donne 2 × 80 × 256 = 40960 bits (ce qui donne 5120 octets).
Ces tailles de clés sont beaucoup plus grandes qu’avec RSA et DSA où les clés auront une taille égale à 2048 bits.
Question b :
Pour signer des messages de taille arbitraire, il suffit de faire passer ces derniers par une fonction de hachage dont la
sortie fait k bits et ensuite de réaliser la signature sur ce hash.
Question c :
Imaginons qu’aucune signature n’ait été faite, le seul moyen de tricher est d’arriver à renverser la fonction de hachage
pour obtenir les yi,j correspondants aux zi,j de façon à pouvoir réaliser la signature (tous les yi,j n’ont pas besoin
d’être découverts, juste ceux correspondant aux bits de notre message).
Question d :
Si on prend k petit, la taille de la clé privée sera également petite. Pour k = 1 elle sera de 2 bits, pour k = 2 de 8 bits,
pour k = 3 de 18 bits et ainsi de suite. Cette petite taille de clé permet de réaliser une attaque par brute force c’est
pourquoi prendre k petit détruit la sécurité du protocole.
Question e : l’exemple le plus simple à imaginer est si on demande la signature du message contenant k bits à
0 puis la signature du message contenant k bits à 1. La première signature contiendra tous les yi,0 et la seconde
contiendra tous les yi,1 , nous aurons donc toute la clé privée et nous pourrons signer ce que nous voulons ! En réalité,
dès qu’on demandera la signature d’un second message qui a au moins 2 bits différents par rapport au premier, nous
pourrons forger des signatures. En l’utilisant une seule fois en revanche il n’y a pas de problème car il est impossible
de forger une signature (vu que nous ne connaissons que les yi correspondants aux bits du message).
Question f : le gros avantage de cet algorithme est qu’il ne fait intervenir aucun calcul complexe et il est donc
extrêmement rapide.
Question c : définir en généralisant la définition du b) la notion de signature basée sur l’identité et d’authentifi-
cation basée sur l’identité.
Question d : alors que trouver des schémas de chiffrement basés sur l’identité est un problème difficile, montrer
qu’il est très facile de construire de manière générique (par exemple, à partir d’un schéma quelconque de signature)
des protocoles de signature et d’authentification basés sur l’identité.
18.7.2 Réponses :
Question a : un couplage est une application e : G1 × G1 → G2 avec les 2 propriétés suivantes :
Bilinéarité : ∀P, Q ∈ G1 , ∀a, b ∈ Z∗q , e(aP, bQ) = ab × e(P, Q).
Non-dégénérescence : ∀P ∈ G1 , P ̸= 0 → G2 =< e(P, P ) >
Ils ont tout d’abord été utilisés pour faire des attaques sur les courbes elliptiques (car avec ces couplages, si on sait
résoudre le problème du logarithme discret sur G2, on sait le résoudre sur G1).
Il est possible de l’utiliser pour faire un échange de clé tri-partite (A reçoit bP de B et cP de C et peut calculer abc × P
avec a × e(bP, cP )).
Une autre possibilité est le chiffrement basé sur l’identité.
Question b : un schéma de chiffrement basé sur l’identité est un algorithme de chiffrement asymétrique dans le-
quel la clé publique d’une personne sera un élément de son identité (prénom, nom, numéro de sécurité sociale, ...).
C’est une notion introduite en 1984 par Shamir mais les premiers protocoles n’ont vu le jour qu’en 2001 par Boneh et
Franklin en utilisant des pairings.
Cela repose sur une tierce partie : un PKG (Private Key Generator). Pour chiffrer un message, une personne utilisera
l’identité du destinataire ainsi que la clé publique du PKG. Pour déchiffrer, le destinataire va demander la clé privée
correspondant à son identité au PKG et l’utiliser pour récupérer le message.
Question c : (je suis pas sûr, il me semble qu’on l’a pas fait en cours)
Pour une signature basée sur l’identité, il faut qu’un utilisateur soit capable de vérifier une signature juste en utilisant
l’identité de la personne ayant signé l’élément. Pour signer, une personne utilisera son identité ainsi que la clé privée
qui lui est donnée par le PKG.
Pour de l’authentification basée sur l’identité, l’idée serait d’envoyer un engagement ”normal”, puis on recevrait un
challenge généré sur la base de notre identité, et nous pourrons ensuite nous authentifier en donnant une réponse grâce
à la clé privée donnée par le PKG.
Question d : (encore une fois, il me semble qu’on l’a pas fait en cours)
- Setup du PKG : on va d’abord générer pkm et skm à partir du même algorithme de génération de clés que pour la
signature, ce seront les clés du PKG. Ensuite, la clé skid sera le tuple (sk, pk, cert) avec cert = Sign(skm , pk||id), il
n’y aura rien dans pkid .
- Création de la signature : s = (Sign(sk, M ), pk, cert) avec (sk, pk, cert) récupérés depuis skid .
- Vérification de la signature : on récupère (pk, cert, s′ ) depuis la signature, puis on fait V erif (pk, M, s′ ) et V erif (pkm , pk||id, cert)
(on a juste eu besoin de récupérer pkm et l’identité).
Le principe général est le suivant : lorsqu’un utilisateur veut signer, on lui génère un couple de clés et on incorpore
dans la clé privée le certificat prouvant la validité de pk. Ce certificat est ensuite ajouté à la signature pour que tout
le monde puisse vérifier la clé à utiliser.
Question c : quelle est la différence entre anonymat et protection de la vie privée, donner des exemples de pro-
tocoles de protection de la vie privée.
Question d : est-ce que le chiffrement permet de faire de la signature ? de l’échange de clé ? de l’authentification ? Si
oui comment ?
Question f : expliquer le type de procédure à mettre en place pour qu’une signature signée aujourd’hui soit en-
core valide dans 99 ans ?
19.1.2 Réponses :
Question a : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à du
RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de 2
points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc
qu’à partir d’une certaine taille de clé.
Question b : un certificat est un fichier qui contient des informations sur une personne / entité ainsi qu’une clé
publique et il est validé par une tierce partie (l’autorité de certification). Il peut être utilisé pour faire de l’authentifi-
cation serveur / client, ...
Question c : dans la protection de la vie privée on cherche à protéger les informations sensibles d’une personne
mais pas son identité alors que pour l’anonymat le focus est mis sur l’identité. Signal est un protocole de messagerie
qui fait en sorte que seules les 2 parties puissent déchiffrer les messages (même le serveur tiers ne peut pas déchiffrer),
on sait qui communique mais on ne sait pas quoi, cela protège donc la vie privée. TLS rentre aussi dans cette catégorie :
on sait qui communique avec le serveur mais encore une fois on ne sait pas quoi.
Question d :
Signature : cela marche seulement dans le cas de RSA (car le chiffrement et le déchiffrement sont ”les mêmes”) mais
en général non car on ne peut pas forcément chiffrer avec la clef privée.
Échange de clés : oui, Alice va choisir une clé K, elle va la chiffrer avec la clé publique de Bob qui pourra ensuite
déchiffrer avec sa clé privée pour récupérer K.
Authentification : oui, imaginons que Alice veut s’authentifier auprès de Bob, Bob va envoyer le chiffré avec la clé
publique d’Alice d’une valeur aléatoire, puis Alice sera la seule à pouvoir déchiffrer avec sa clef privée.
Question e : l’idée est que l’on veut laisser un utilisateur récupérer des informations d’une base de données sans
que la base de données sache quelle information nous avons retirée. Un exemple de protocole pour le résoudre est celui
d’Ostrovsky et Kushilevitz mais pour être efficace il faut avoir beaucoup de données de petite taille. C’est donc utile
dans le cadre des DNS, des données médicales, ...
Question f : une idée serait de signer le document de manière régulière avec une clé différente à chaque fois, cela
demande tout de même de savoir à quelle fréquence changer la signature et aussi plus on avance dans le temps plus
il faudra refaire la signature souvent pour éviter les attaques. Une autre solution est de choisir une clé de taille très
grande de façon à rester sécurisé contre l’augmentation en puissance des ordinateurs.
1. Alice fournit un engagement aléatoire k dans l’intervalle [0, q − 1] et calcule K = g k (mod p) puis l’envoie à
Bob.
2. Bob choisit un défi r au hasard dans [0, q − 1] et le transmet à Alice.
3. Alice calcule la réponse y = (k + a × r) (mod q) et la transmet à Bob.
Pour finir, Bob vérifiera que g y × Ar = K (mod p).
Question b : montrer que le protocole fonctionne (en ce sens que si on connaı̂t le secret, on répond convenable-
ment quoiqu’il arrive).
Question c : donner un exemple où en anticipant un défi, un tricheur peut se faire passer pour Alice avec une
probabilité de 1/q. En déduire que la probabilité de tricher est supérieure à 1/q (on admet par la suite que cette
probabilité est exactement 1/q).
Question d : quel est l’intérêt de de protocole par rapport au protocole de Fiat-Shamir (en terme de nombre de
passes).
19.2.2 Réponses :
Question a : voici le schéma :
Question b :
Il est possible de répondre à tout message vu qu’on envoie simplement (k + a × r) (mod q).
En connaissant la clé, si on envoie g k et y = (k + a × r) : Bob va calculer y × Ar = g y × g −a×r = g k+a×r−a×r = g k = K.
Question c :
Cela veut dire que l’attaquant connaı̂t la valeur du défi r (qui est une constante) mais il ne connaı̂t pas a.
L’attaquant peut commencer par envoyer K = Ar = g −a×r .
Ensuite, il va recevoir le défi r dont il a anticipé une valeur.
L’attaquant va ensuite envoyer y = 0 et du coup Bob va calculer g 0 × Ar = g −a×r qui est bien égal au K envoyé.
Vu qu’il y a q valeurs de r possibles, la probabilité de triche de l’attaquant est 1/q mais on ne peut pas exclure le
fait qu’il lui sera peut être possible de combiner les résultats pour plusieurs valeurs de r ce qui ferait augmenter sa
probabilité de triche.
Question d :
Dans le protocole de Shamir, la probabilité de triche est 1/2, du coup pour avoir une sécurité de n bits, il faut faire n
exécutions du protocole.
Dans le protocole au-dessus, la probabilité de triche est 1/q et q peut être choisi assez grand (par exemple avec un
premier de 1024 bits, on pourrait tout à fait avoir q sur 256 - 512 bits). Du coup avec de telles tailles, la sécurité
voulue peut être obtenue avec un tour de protocole.
Il faut tout de même noter que des exponentiations modulaires sont utilisées dans le second protocole et donc qu’il est
beaucoup plus long que celui de Shamir (pour un tour).
Question e :
La propriété de zero-knowledge est que ces échanges ne doivent rien dévoiler sur la clé : ici du point de vue d’un
adversaire r est aléatoire, la valeur de a est donc masquée totalement.
Question a : quelle est la différence entre le partage de secret et l’échange de clé ? Donner un exemple d’appli-
cation du partage de secret.
Question c : on suppose qu’un état major (composé de 1 général, 2 colonels et 5 capitaines) a la possibilité de
faire tirer un missile ultra-destructeur, le code du missile est un secret partagé, qui ne peut être activé que dans
certains cas :
1. Le général le souhaite.
2. Les deux colonels le souhaitent.
3. Les 5 capitaines le souhaitent.
4. 1 colonel et 3 capitaines le souhaitent.
Proposer une solution en utilisant le schéma de partage de secret de Shamir qui permet de résoudre ce problème.
19.3.2 Réponses :
Question a : pour un échange de clé, on veut pouvoir créer une clé qui sera connue de 2 personnes sans connaı̂tre
un secret auparavant. Pour le partage de secret chaque personne aura des bouts de secret et ce dernier ne pourra être
re-constitué que si un certain nombre de bouts de secrets sont récupérés.
Un exemple d’application réelle est dans une cérémonie des clés où toutes les personnes doivent mettre leur carte dans
le HSM (Hardware Security Module) pour l’initialiser : génération des clés les plus importantes.
Question b : dans le schéma de partage de secret de Shamir, k sera le nombre de bouts de secret à rejoindre pour
obtenir le secret et n le nombre de bouts de secret total. L’idée est donc de créer un polynôme P de degré k − 1 dont
les coefficients seront aléatoires, puis de prendre n points aléatoires sur ce polynôme (on prendra un x aléatoire, on cal-
culera P (x) et le bout de secret sera la paire (x, f (x))). Le secret commun sera le coefficient constant du polynôme P [0].
Question c :
1) Une solution simple consiste à prendre 10 bouts de secrets par général, 5 bouts de secret par colonel et 2 bouts de
secret par capitaine. Il faudra dans chacun des cas 10 bouts de secret pour le récupérer (le dernier produit 11 bouts
de secrets mais c’est pas grave, 1 capitaine de moins et il en reste que 9 ce qui n’est pas suffisant), on choisira donc
un polynôme aléatoire de degré k = 9 puis on devra donner 30 bouts de secret au total.
19.4.2 Réponses :
Question a : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à du
RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition de 2
points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera donc
qu’à partir d’une certaine taille de clé. Pour rappeler le schéma de fonctionnement, reprenez les 2 schémas que nous
avons fait au début.
Question b :
y 0 1 2 3 4 x 0 1 2 3 4
y2 0 1 4 4 1 x3 + x + 2 2 2 3 1 2
Cette courbe possède donc 3 points : (3, 1), (3, 4), 0.
Question c :
D’après le théorème de la courbe elliptique, la seule structure possible pour ce groupe est Z/1Z ⊕ Z/3Z qui possède 2
générateurs.
Question d :
Les 2 seuls générateurs possibles sont (3, 1) et (3, 4.
Nous pouvons calculer 1P , 2P dans chaque cas pour le vérifier :
(3, 1) :
0P = 0
1P = (3, 1)
2P = (3, 1) + (3, 1) = (3, 4) : coeff = 1/2 = 3, x3 = 32 − 2 × 3 = 3, y3 = 3 × (3 − 3) − 1 = 4
(3, 4) :
0P = 0
1P = (3, 4)
2P = (3, 4) + (3, 4) = (3, 1) : coeff = 1/2 = 3, x3 = 32 − 2 × 3 = 3, y3 = 3 × (3 − 3) − 4 = 1
L’idée derrière ce protocole est que le message ne passe jamais en clair (bien évidemment) et également que seul S
peut enlever le x qu’il a rajouté et seul R peut enlever le y qu’il a rajouté.
Question a : pourquoi a-t-on M zx = M (mod P ) ? Soyez complet dans vos explications !
Question b : que se passe-t-il précisément du point de vue mathématique lorsque S élève M xy à la puissance z ?
Question c : quelles sont précisément les opérations mises en oeuvre par R pour enlever y et pourquoi lui permettent-
elels de retrouver M ?
Question d : expliquez en vous servant par exemple du théorème de Bezout, pourquoi x et y doivent être pre-
miers avec P − 1.
Question e : en définitive, à quel schéma à clés publiques vu en cours le procédé décrit par J. H ; Ellis se ramène-t-il ?
Justifiez votre réponse ?
Question f : S et R ont choisir de travailler avec P = 101. Les valeurs utilisées par S sont 3 et 67, celles utilisées par
R sont 13 et 77. Au total, combien de multiplications seront effectuées au cours de l’échange, si les exponentiations se
font par la méthode rapide ?
19.5.2 Correction :
Question a : M zx (mod P ) = M k×(P −1)+1 (mod P ) = (M P −1 )k × M (mod P ) = 1 × M (mod P ) = M (mod P ).
Question c : R commence par trouver w tel que wy = 1 (mod P − 1) puis calcule M yw = M (mod P ).
Question d : supposons que x n’est pas premier avec P −1, la relation de Bézout nous dit qu’il sera possible de trouver
z et a tels que xz + a × (P − 1) = pgcd(x, P − 1), nous voyons donc qu’il sera impossible de trouver un inverse modu-
laire de x car ce dernier n’est pas premier avec P −1 : pgcd(x, P −1) ̸= 1. Le même raisonnement peut être appliqué à y.
Question e : ce schéma est très similaire à l’échange de clé diffie-hellman car les 2 parties génèrent une valeur
aléatoire, font une exponentiation modulaire puis arrivnet à dériver le même message en faisant des opérations sur les
exposants.
Question f : dans une exponentiation rapide, nous aurons 1 multiplication si le bit est à 0 et 2 multiplications
si le bit est à 1. Nous allons donc écrire les différents nombres en binaire et calculer le nombre de multiplications :
M x = M 3 : 3 = 11, 2 multiplications (on retire le premier 1)
M xy = (M x )13 : 13 = 1101, 5 multiplications.
M xyz = (M xy )67 : 67 = 1000011, 8 multiplications.
M wy = (M y )77 : 77 = 1001101, 9 multiplications.
Question c : qu’est-ce qu’un tiers de confiance, donner des exemples de telles entités.
Question d : est-ce que le chiffrement permet de faire de la signature ? de l’échange de clés ? de l’authentifica-
tion ? Si oui, comment ?
Question e : que permettent de fairer les schémas de Retrait d’Information Privé (PIR en anglais). Expliquer le
principe général. Donner des exemples d’utilisation concrète de ce type de protocole.
Question f : qu’est-ce qu’un chiffrement homomorphe ? Donner un exemple d’un tel protocole, et donner un exemple
d’application.
20.1.2 Réponses :
Question a : un certificat est un document numérique qui va contenir des informations sur une entité ainsi que la clé
publique de cette dernière. Cette clé publique sera signée par une autorité de degré supérieur.
Question b : une chaı̂ne de certificats contient le certificat de l’entité, puis le certificat utilisé pour signer le cer-
tificat de l’entité, puis le certificat utilisé pour signer ce certificat et ainsi de suite. Pour moi, on l’utilise pour vérifier
toute la chaı̂ne de confiance.
Question c : un tiers de confiance est comme son nom l’indique une entité tierce dont on va supposer qu’elle se
comporte de manière honête. Dans le cadre de la certification, un tiers de confiance entre un client et un serveur serait
l’autorité de certification qui est trusted par le client et qui lui permettra d’accepter le certificat du serveur.
Question d :
Signature : cela marche seulement dans le cas de RSA (car le chiffrement et le déchiffrement sont ”les mêmes”) mais
en général non car on ne peut pas forcément chiffrer avec la clef privée.
Échange de clés : oui, Alice va choisir une clé K, elle va la chiffrer avec la clé publique de Bob qui pourra ensuite
déchiffrer avec sa clé privée pour récupérer K.
Authentification : oui, imaginons que Alice veut s’authentifier auprès de Bob, Bob va envoyer le chiffré avec la clé
publique d’Alice d’une valeur aléatoire, puis Alice sera la seule à pouvoir déchiffrer avec sa clef privée.
Question e : l’idée est que l’on veut laisser un utilisateur récupérer des informations d’une base de données sans
que la base de données sache quelle information nous avons retirée. Un exemple de protocole pour le résoudre est celui
d’Ostrovsky et Kushilevitz mais pour être efficace il faut avoir beaucoup de données de petite taille. C’est donc utile
dans le cadre des DNS, des données médicales, ...
Question f : un chiffrement homomorphe est un algorithme de chiffrement asymétrique qui permet de faire des
opérations sur des textes chiffrés et ces opérations seront reflétées le texte en clair. Une propriété que l’on peut vouloir
est Enc(a) × Enc(b) = Enc(a + b) (ce qui a comme conséquence que Enc(a)b = Enc(a × b)).
Un exemple d’algorithme de chiffrement homomorphe est le chiffrement de Paillier (avec un module RSA n sur k bits)
où la taille du chiffré sera 2 × k.
Un exemple d’application est le vote électronique dans lequel chaque personne va envoyer le chiffré de son bulletin (0
s’il vote contre et 1 s’il vote pour) puis il suffira de multiplier tous ces chiffrés entre eux et de déchiffrer le résultat
pour avoir le nombre de voix. Une autre possibilité est dans le cadre d’un schéma PIR.
1. Alice fournit un engagement aléatoire k dans l’intervalle [0, q − 1] et calcule K = g k (mod p) puis l’envoie à
Bob.
2. Bob choisit un défi r au hasard dans [0, q − 1] et le transmet à Alice.
3. Alice calcule la réponse y = (k + a × r) (mod q) et la transmet à Bob.
Pour finir, Bob vérifiera que g y × Ar = K (mod p).
Question b : montrer que le protocole fonctionne (en ce sens que si on connaı̂t le secret, on répond convenable-
ment quoiqu’il arrive).
Question c : donner un exemple où en anticipant un défi, un tricheur peut se faire passer pour Alice avec une
probabilité de 1/q. En déduire que la probabilité de tricher est supérieure à 1/q (on admet par la suite que cette
probabilité est exactement 1/q).
Question d : quel est l’intérêt de de protocole par rapport au protocole de Fiat-Shamir (en terme de nombre de
passes).
20.2.2 Réponses :
Question a : voici le schéma :
Question b :
Il est possible de répondre à tout message vu qu’on envoie simplement (k + a × r) (mod q).
En connaissant la clé, si on envoie g k et y = (k + a × r) : Bob va calculer y × Ar = g y × g −a×r = g k+a×r−a×r = g k = K.
Question c :
Cela veut dire que l’attaquant connaı̂t la valeur du défi r (qui est une constante) mais il ne connaı̂t pas a.
L’attaquant peut commencer par envoyer K = Ar = g −a×r .
Ensuite, il va recevoir le défi r dont il a anticipé une valeur.
L’attaquant va ensuite envoyer y = 0 et du coup Bob va calculer g 0 × Ar = g −a×r qui est bien égal au K envoyé.
Vu qu’il y a q valeurs de r possibles, la probabilité de triche de l’attaquant est 1/q mais on ne peut pas exclure le
fait qu’il lui sera peut être possible de combiner les résultats pour plusieurs valeurs de r ce qui ferait augmenter sa
probabilité de triche.
Question d :
Dans le protocole de Shamir, la probabilité de triche est 1/2, du coup pour avoir une sécurité de n bits, il faut faire n
exécutions du protocole.
Dans le protocole au-dessus, la probabilité de triche est 1/q et q peut être choisi assez grand (par exemple avec un
premier de 1024 bits, on pourrait tout à fait avoir q sur 256 - 512 bits). Du coup avec de telles tailles, la sécurité
voulue peut être obtenue avec un tour de protocole.
Il faut tout de même noter que des exponentiations modulaires sont utilisées dans le second protocole et donc qu’il est
beaucoup plus long que celui de Shamir (pour un tour).
Question e :
La propriété de zero-knowledge est que ces échanges ne doivent rien dévoiler sur la clé : ici du point de vue d’un
adversaire r est aléatoire, la valeur de a est donc masquée totalement.
On considère une bi-clé de type RSA : clé publique (n, e) et clé privée (d, p, q) avec les notations habituelles.
Question b : soit m un message que l’on souhaite faire signer, sans que le signataire connaisse le contenu. Montrer
qu’on peut facilement adapter le schéma de signature RSA pour obtenir cette propriété (indice : il faut multiplier m
par quelque chose).
Question c : pourquoi un tel schéma est-il sûr et ne laisse-t-il pas passer d’information ?
Question d : la signature aveugle est un type de protocole utilisé pour garantir des propriétés de type anonymat,
connaissez-vous d’autres types de protocoles aussi utilisables dans un contexte d’anonymat.
Question e : délégation de signature : on suppose qu’Alice et Bob ont chacun une clé privée et une clé publique
permettant de fair ede la signature. Alice souhaite faire une délégation de signature à Bob pendant ses vacances, c’est
à dire que Bob doit pouvoir signer au nom d’Alice pendant une période de temps fixée, et ce bien sûr sans qu’Alice
soit obligée de donner sa clé privée. Comment peut-on faire cela ?
20.3.2 Réponses :
Question a : un exemple d’application est le vote électronique où l’on va vouloir signer notre bulletin pour pas que
le serveur ne triche mais cette signature ne peut être obtenue que par une entité tierce associée au serveur, du coup
on va vouloir cacher notre vote pour que l’entité tierce ne le connaisse pas.
Question b : On va envoyer m×re avec r une valeur aléatoire à l’oracle de signature qui va nous retourner s = (m×re )d
(mod n) = md × red = md × r (mod n).
Finalement, pour obtenir la signature associée au message m, il suffit de la multiplier par l’inverse de r modulo n !
Question c : a chaque étape, le message ou sa signature est toujours multiplié par une valeur r aléatoire que le
signataire ne connaı̂t pas et qui donc va agir comme un one time pad qui ne donne même pas un seul bit d’information
sur le message.
Question d : un VPN est un premier exemple d’obtention d’anonymat car notre IP est cachée et une personne
extérieure ne saura pas à qui est la session.
Partie 2 : la bombe :
Question a : on suppose maintenant qu’on veut mettre en place un système qui permet à certains type de combinai-
sons de militaires de retrouver le secret du code nucléaire. On veut que les combinaisons suivantes puissent retrouver
le secret : 3 généraux, 4 colonels + 1 général, 3 colonels + 5 capitaines ou encore 20 capitaines. Comment faire ?
Question b : le problème de la solution précédente est qu’il est possible qu’un groupe formé uniquement de capitaines
puisse retrouver le secret, ce qui pose problème. On souhaite donc mettre en place un système où pour retrouver le
secret il faille au moins : 1 général, 2 colonels, 4 capitaines qui collaborent. Cela signifie donc qu’un groupe formé
uniquement de capitaines ou de colonels (par exemple) ne pourra pas retrouver le secret. Comment faire ? (toujours
en utilisant un schéma basé sur le schéma de Shamir ou une variation).
20.4.1 Réponses :
1 - Question a : pour un échange de clé, on veut pouvoir créer une clé qui sera connue de 2 personnes sans connaı̂tre
un secret auparavant. Pour le partage de secret chaque personne aura des bouts de secret et ce dernier ne pourra être
re-constitué que si un certain nombre de bouts de secrets sont récupérés.
Un exemple d’application réelle est dans une cérémonie des clés où toutes les personnes doivent mettre leur carte dans
le HSM (Hardware Security Module) pour l’initialiser : génération des clés les plus importantes.
1 - Question b : dans le schéma de partage de secret de Shamir, k sera le nombre de bouts de secret à rejoindre
pour obtenir le secret et n le nombre de bouts de secret total. L’idée est donc de créer un polynôme P de degré k − 1
dont les coefficients seront aléatoires, puis de prendre n points aléatoires sur ce polynôme (on prendra un x aléatoire,
on calculera P (x) et le bout de secret sera la paire (x, f (x))). Le secret commun sera P (0).
1 - Question c : vu que 2 personnes peuvent retrouver le secret, nous avons un polynôme de degré 1, donc de
la forme y = ax + b (mod 43).
Avec le premier point : 2a + b = 8 (mod 43)
Avec le second point : 5a + b = 12 (mod 43)
En soustrayant les 2 équations on peut obtenir 3a = 4 (mod 43) ⇔ a = 29 × 4 (mod 43) ⇔ a = 30 (mod 43)
En réutilisant la première équation nous avons 60 + b = 8 (mod 43) ⇔ b = 34 (mod 43).
Le point (10, 33) est également sur cette droite (je pense que Gaborit s’est gouré dans le sujet et il a mis 23 pour le y
au lieu de 33).
La solution est donc f (x) = 30x + 34 (mod 43) et donc le secret sera 34.
2 - Question a : l’idée va être de demander 60 bouts de secret avant de pouvoir récupérer le secret final, les
généraux auront 20 bouts de secrets, les colonnes en auront 5 et les capitaines en auront 3. Je pense encore une fois
que Gaborit s’est gouré dans le sujet, pour que ça soit possible il aurait fallu mettre 10 capitaines pour la dernière
condition, voici une démonstration de pourquoi :
3G = X pour la première équation.
1G + 4C = X ⇔ 3G + 12C = 3X ⇔ 12C = 2X ⇔ 6C = X
3C + 5c = X ⇔ 6C + 10c = 2X ⇔ 10c = X
20c = X
On a donc une grosse contradiction sur les 2 dernières équations.
2 - Question b : ne connaissant pas le nombre total de capitaines, on ne pourra pas donner un nombre infini
de bouts de secrets aux généraux. L’idée sera donc de procéder en 2 étapes : dans une première étape chaque colonel
aura un bout d’un secret C1 et chaque capitaine aura un bout d’un secret c1 qui pourront être reconstitués quand
respectivement 2 colonels et 4 capitaines se mettront d’accord. Ensuite le groupe de 1 général, de 2 colonels et de 4
capitaines mettront en commun les secrets dérivés à la première étape pour arriver à un secret final (via un second
partage de Shamir).
Question d : donner un générateur du groupe (un point P tel que 0P, P, 2P, ... engendre le groupe). En déduire la
structure du groupe de la courbe.
20.5.2 Réponses :
Question a : l’intérêt de prendre les courbes elliptiques est que les tailles de clés sont plus petites par rapport à
du RSA ou du El-Gamal (car il n’y a pas d’opération de groupe non nécessaire). Mais, le temps pris pour l’addition
de 2 points est 10 fois supérieur au temps d’une multiplication modulaire, le choix des courbes elliptiques ne se fera
donc qu’à partir d’une certaine taille de clé. Pour le schéma, refaire celui au début de la partie sur les courbes elliptiques.
Question b :
y 0 1 2 3 4 x 0 1 2 3 4
y2 0 1 4 4 1 x3 + x + 3 3 0 3 3 1
Cette courbe possède donc 4 points : (1, 0), (4, 1), (4, 4), 0.
Question c :
2 × (1, 0) = 0
2 × (4, 1) = (1, 0) et 4 × (4, 1) = 0
2 × (4, 4) = (1, 0) et 4 × (4, 4) = 0
Question e :
Oui, il y a un générateur, il y en a même φ(4) = 2.
P = (4, 1) est un exemple de générateur.
D’après le théorème de la courbe elliptique, nous avons 2 possibilités :
Isomorphisme avec Z/1Z ⊕ Z/4Z (n2 = 1, n1 = 4, n2 divise p − 1 = 4 et n1 = 4).
Isomorphisme avec Z/2Z ⊕ Z/2Z (n2 = 2, n1 = 2, n2 divise p − 1 = 4 et n1 = 2).
Vu qu’il y a un générateur, cette courbe est isomorphe à Z/1Z ⊕ Z/4Z.