C4 — Cryptographie asymétriqueDans le dialogue d’impression, choisissez « Enregistrer au format PDF » comme destination.
Retour

Master 1 · Cryptographie

Cours 4Cryptographie asymétrique

Fonder la clé publique sur trois problèmes difficiles : factorisation, logarithme discret, courbes elliptiques.

3 chapitres · 16 h de travail estimé

  1. 1. RSA5 h
  2. 2. Logarithme discret5 h
  3. 3. Courbes elliptiques6 h

Chapitre 1 · 5 h

RSA

Construction et factorisation, chiffrement OAEP, signature PSS, attaques par module commun, exposant faible, Coppersmith et canaux auxiliaires.

Jusqu'ici, chiffrer supposait une clé déjà partagée. Comment deux personnes qui ne se sont jamais rencontrées en établissent-elles une sur un canal public ? La réponse — la cryptographie à clé publique — est l'une des grandes ruptures du XXe siècle, et RSA en est le premier exemple complet, publié en 1977 par Rivest, Shamir et Adleman.

L'idée est asymétrique : une clé publique pour chiffrer ou vérifier, que le monde entier peut connaître, et une clé privée pour déchiffrer ou signer, gardée secrète. Ce chapitre construit RSA, puis — fidèle au fil du cours — le casse partout où il est mal employé.

La construction

Elle repose entièrement sur l'arithmétique du chapitre 2.

  1. Choisir deux grands premiers pp et qq, et poser n=pqn = pq. Le module nn est public, mais pp et qq restent secrets.
  2. Calculer φ(n)=(p1)(q1)\varphi(n) = (p-1)(q-1).
  3. Choisir un exposant public ee premier avec φ(n)\varphi(n) — en pratique e=65537e = 65537.
  4. Calculer l'exposant privé d=e1modφ(n)d = e^{-1} \bmod \varphi(n), par Euclide étendu.

La clé publique est (n,e)(n, e), la clé privée est dd. Chiffrement et déchiffrement :

c=memodnm=cdmodnc = m^e \bmod n \qquad\qquad m = c^d \bmod n

Le déchiffrement redonne le message parce que ed1(modφ(n))ed \equiv 1 \pmod{\varphi(n)}, donc medm(modn)m^{ed} \equiv m \pmod n par le théorème d'Euler. La signature inverse simplement les rôles : on signe avec dd, on vérifie avec ee.

Sur quoi repose vraiment la sécurité

L'attaquant connaît nn et ee. S'il savait factoriser nn, il obtiendrait pp et qq, donc φ(n)\varphi(n), donc dd : RSA serait mort. Sa sécurité repose donc sur la difficulté de la factorisation, un problème sous-exponentiel (chapitre 2) mais sans algorithme efficace connu sur machine classique.

Une nuance que les étudiants confondent souvent. Casser RSA — retrouver mm à partir de cc — n'est pas prouvé équivalent à factoriser : il pourrait exister un raccourci qui contourne la factorisation. On n'en connaît pas, mais l'équivalence n'est pas démontrée. C'est une hypothèse de plus, distincte de la difficulté de factoriser, et le chapitre 12 y reviendra en parlant de l'hypothèse RSA.

Les tailles se déduisent des records de factorisation : RSA-1024 est déconseillé, RSA-2048 est le minimum courant, RSA-3072 vise 128 bits de sécurité. À comparer aux 256 bits des courbes elliptiques du chapitre 11 pour la même sécurité — l'écart qui explique leur adoption.

Quiz · 1 question

Sur quelle hypothèse repose la sécurité de RSA, et qu'est-ce qui n'est PAS prouvé ?

  • Sur la difficulté du logarithme discret ; l'équivalence avec RSA est prouvéelogarithme discret
  • Sur la difficulté de factoriser n ; l'équivalence entre « casser RSA » et « factoriser » n'est PAS prouvéefactorisation
  • Sur la difficulté des collisions de hachage ; tout est prouvé équivalentcollisions

Réponse : Factoriser n donne p, q, φ(n), puis d : la sécurité de RSA exige donc que factoriser soit dur. Mais l'inverse n'est pas établi — casser RSA pourrait, en théorie, être plus facile que factoriser, par un raccourci inconnu. C'est l'hypothèse RSA, distincte de l'hypothèse de factorisation. Le logarithme discret est le fondement d'AUTRES schémas (chapitre 10), pas de RSA.

RSA « textbook » est cassé, et vous allez le casser

Le RSA nu — c=memodnc = m^e \bmod n, sans rembourrage — est un désastre pratique, pour deux raisons qui reprennent tout le chapitre 1. Il est déterministe : le même clair donne le même chiffré, donc un adversaire distingue et devine par dictionnaire. Et il est malléable : (m1m2)e=m1em2e(m_1 m_2)^e = m_1^e \, m_2^e, l'attaquant transforme le chiffré d'un message en celui d'un multiple sans le déchiffrer.

Le cas le plus spectaculaire combine un petit exposant et un message court. Si e=3e = 3 et si m3<nm^3 < n, la réduction modulo nn ne s'applique pas : le chiffré est le cube exact du message, et une simple racine cubique entière le rend — sans clé privée, sans factorisation. Montez-la.

Exercice de code

Cassez un chiffrement RSA à exposant 3 sans rembourrage, quand le message est court, par une simple racine cubique entière — sans clé privée ni factorisation.

Point de départ

// RSA jouet en BigInt. Le module est grand (RSA-ish), mais le message est
// COURT et le chiffrement n'a AUCUN rembourrage. C'est l'erreur.

// Deux premiers (petits pour l'exemple, la faille est indépendante de la taille).
const p = 32416190071n;
const q = 32416187671n;
const n = p * q;
const e = 3n;                 // exposant public minimal, très répandu

// Chiffrement TEXTBOOK : c = m^e mod n, sans OAEP, sans rien.
function puissanceMod(base, exp, mod) {
  let r = 1n; base %= mod;
  while (exp > 0n) {
    if (exp & 1n) r = (r * base) % mod;
    base = (base * base) % mod;
    exp >>= 1n;
  }
  return r;
}

const m = 1234567n;           // message court : un code PIN, un identifiant...
const c = puissanceMod(m, e, n);
console.log("chiffré c =", c.toString());

// ── L'observation qui tue ─────────────────────────────────────────────────
// Si m^e < n, la réduction « mod n » ne fait RIEN : c = m^e comme entier.
// Retrouver m ne demande alors ni la clé privée, ni de factoriser n —
// seulement une racine e-ième ENTIÈRE.
console.log("m^3 < n ?", m ** 3n < n);

// ── À COMPLÉTER : racine cubique entière par dichotomie ───────────────────
function racineCubiqueEntiere(x) {
  if (x < 2n) return x;
  let lo = 0n, hi = 1n;
  while (hi ** 3n <= x) hi <<= 1n;   // borne haute
  // à compléter : resserrer [lo, hi] jusqu'à la racine cubique entière
  return lo;
}

const retrouve = racineCubiqueEntiere(c);
console.log("m retrouvé :", retrouve.toString());
console.log("correct ?", retrouve === m, "| sans clé privée, sans factoriser n");

Solution

function racineCubiqueEntiere(x) {
  if (x < 2n) return x;
  let lo = 0n, hi = 1n;
  while (hi ** 3n <= x) hi <<= 1n;
  while (lo < hi) {
    const mid = (lo + hi + 1n) >> 1n;
    if (mid ** 3n <= x) lo = mid;
    else hi = mid - 1n;
  }
  return lo; // plus grand entier dont le cube est <= x
}

// m est retrouvé exactement. La clé privée n'a jamais servi, n n'a pas été
// factorisé : on a simplement pris la racine cubique d'un cube parfait.
//
// La faille tient à DEUX fautes cumulées :
//   1. e = 3, si petit que m^3 peut ne pas déborder n ;
//   2. aucun rembourrage, donc le clair est utilisé tel quel.
//
// La parade est OAEP, qui remplit le message d'un bourrage aléatoire
// structuré : m devient toujours du même ordre de grandeur que n (donc m^e
// déborde et « mod n » redevient une vraie barrière), et deux chiffrements du
// même clair diffèrent. C'est aussi ce qui rend RSA-OAEP sûr contre CCA au
// sens du chapitre 1, là où le RSA textbook est malléable et déterministe.
//
// Variante à connaître : même avec rembourrage, si le MÊME message est envoyé
// à trois destinataires ayant chacun e = 3 (modules différents), le théorème
// des restes chinois reconstitue m^3 modulo le produit des trois modules, puis
// la racine cubique le livre — c'est l'attaque de Håstad.

Quiz · 1 question

Dans l'attaque à exposant 3, pourquoi la racine cubique suffit-elle à retrouver le clair ?

  • Parce que e = 3 rend la clé privée d égale à 3clé privée
  • Parce que si m^3 < n, alors c = m^3 exactement : la réduction mod n n'a rien changépas de réduction
  • Parce que la racine cubique factorise nfactorisation

Réponse : Quand m^3 est plus petit que n, « mod n » ne retire rien : c EST le cube de m comme entier. Prendre la racine cubique entière d'un cube parfait rend m directement, sans toucher à d ni à la factorisation. C'est la conjonction de deux fautes : un exposant minuscule et l'absence de rembourrage qui laisse m trop petit.

Les bons schémas : OAEP et PSS

La leçon n'est pas « RSA est mauvais » mais « RSA ne s'emploie jamais nu ». Deux rembourrages normalisés le rendent sûr.

OAEP (Optimal Asymmetric Encryption Padding) enrobe le message avant chiffrement d'une structure aléatoire construite sur des fonctions de hachage. Trois effets : le chiffrement devient probabiliste (deux chiffrements du même clair diffèrent), le message occupe toujours tout l'espace modulo nn (l'attaque à exposant faible s'effondre), et le résultat est sûr contre les attaques à chiffrés choisis — IND-CCA2, la cible du chapitre 12.

PSS (Probabilistic Signature Scheme) fait l'équivalent pour la signature. On ne signe jamais le message brut : on le hache, on lui adjoint un aléa, et l'on signe cette valeur. La signature devient inforgeable au sens EUF-CMA, avec une preuve dans le modèle de l'oracle aléatoire.

Le fil rouge du chapitre 7 se referme ici : puisqu'on signe le haché du message, une collision sur la fonction de hachage est une signature forgée. C'est concret — un faux certificat X.509 a été fabriqué en 2008 en exploitant une collision MD5, exactement de cette manière. La sécurité d'une signature n'excède jamais la résistance aux collisions du haché qu'elle emploie.

Les attaques qui restent, même bien rembourré

OAEP et PSS ferment les failles mathématiques, mais l'implémentation en ouvre d'autres.

Module commun, exposant faible. Un même message envoyé à trois destinataires d'exposant e=3e = 3 (modules distincts) se reconstitue par les restes chinois puis racine cubique — l'attaque de Håstad. Deux clés partageant un facteur premier se factorisent par un simple pgcd de leurs modules ; un balayage de clés publiques réelles en 2012 a ainsi cassé des milliers de clés RSA dont les premiers avaient été mal tirés.

Coppersmith. Sa méthode, fondée sur la réduction de réseaux (le monde du bloc V), trouve les petites racines d'un polynôme modulaire. Elle casse RSA quand une partie du message est connue, ou quand une fraction des bits d'un facteur premier fuit. C'est un pont inattendu entre RSA et les réseaux euclidiens du post-quantique.

Canaux auxiliaires. L'exponentiation modulaire naïve du chapitre 2 n'est pas à temps constant : sa durée, sa consommation électrique, ses accès au cache dépendent des bits de dd. Une mesure fine les révèle. La parade a un nom, le blinding : on randomise l'entrée avant l'exponentiation pour décorréler la fuite du secret. Et l'attaque par faute du chapitre 2 rôde toujours — d'où la vérification de signature avant publication.

Ce que la suite en fait

RSA a montré qu'une seule fonction à sens unique — la multiplication facile, la factorisation dure — suffit à bâtir chiffrement et signature. Le chapitre 10 rebâtit tout sur un autre problème difficile, le logarithme discret, avec un avantage décisif : il rend naturel l'échange de clés, là où RSA ne fait que transporter un secret choisi par l'un des deux. Le chapitre 11 y ajoutera les courbes elliptiques et leurs clés courtes, et le chapitre 14 rappellera que Shor, sur un ordinateur quantique, factorise et calcule les logarithmes discrets en temps polynomial — abattant RSA et le chapitre 10 d'un même coup.

À retenir

Flashcards · 3 cartes

Quel problème fonde RSA, et par quel enchaînement le casserait-on en factorisant ?
La difficulté de factoriser n = pq. Factoriser donne p et q, donc φ(n) = (p−1)(q−1), donc l'exposant privé d = e^(−1) mod φ(n). L'inverse — que casser RSA soit AUSSI dur que factoriser — n'est pas prouvé : c'est une hypothèse distincte.
Pourquoi le RSA « textbook » est-il inutilisable, et que corrige OAEP ?
Nu, RSA est déterministe (donc distinguable) et malléable ((m1·m2)^e = m1^e·m2^e), et un petit exposant sur message court se casse par racine cubique. OAEP enrobe le message d'un rembourrage aléatoire structuré : chiffrement probabiliste, message toujours de l'ordre de n, et sécurité IND-CCA2.
Pourquoi la sécurité d'une signature RSA-PSS dépend-elle de la fonction de hachage ?
Parce qu'on signe le HACHÉ du message, pas le message : deux messages de même haché ont la même signature. Une collision sur le haché est donc une signature forgée — c'est ainsi qu'un faux certificat X.509 a été fabriqué en 2008 via une collision MD5. La sécurité de la signature n'excède pas la résistance aux collisions du haché.

Chapitre 2 · 5 h

Logarithme discret

Diffie-Hellman, ElGamal, DSA ; pas de bébé et pas de géant, rho de Pollard, calcul d'indices ; attaque par l'homme du milieu.

RSA transporte un secret : Alice choisit une clé et l'envoie chiffrée. Diffie et Hellman, en 1976 — un an avant RSA — avaient résolu un problème plus subtil : comment deux personnes fabriquent ensemble un secret commun sur un canal public, sans que ni l'une ni l'autre ne l'ait choisi seule, et sans que l'espion qui écoute tout puisse le calculer. Ce chapitre repose sur un second problème difficile, le logarithme discret, et sur la famille de schémas qui en découle.

Le problème du logarithme discret

Dans un groupe cyclique — par exemple (Z/pZ)(\mathbb{Z}/p\mathbb{Z})^* avec un générateur gg — calculer h=gxmodph = g^x \bmod p est facile, par exponentiation rapide. Le problème inverse — retrouver xx à partir de hh — est le logarithme discret, et on ne connaît pas d'algorithme efficace pour le résoudre dans un groupe bien choisi.

L'asymétrie est celle qui fonde toute la clé publique : une direction aisée, l'autre infaisable. Ici xx est le secret, gxg^x est public, et tout repose sur l'impossibilité de remonter.

Diffie-Hellman

Le protocole est d'une élégance qui tient en quatre lignes. Un premier pp et un générateur gg sont publics.

  1. Alice tire aa au hasard, envoie A=gamodpA = g^a \bmod p.
  2. Bob tire bb au hasard, envoie B=gbmodpB = g^b \bmod p.
  3. Alice calcule Ba=gbaB^a = g^{ba}. Bob calcule Ab=gabA^b = g^{ab}.
  4. Les deux obtiennent la même valeur gabmodpg^{ab} \bmod p : le secret partagé.

L'espion voit gg, pp, A=gaA = g^a et B=gbB = g^b. Pour obtenir gabg^{ab}, il lui faudrait aa ou bb — donc résoudre un logarithme discret. Ni Alice ni Bob n'a choisi le secret : il a émergé de leurs deux aléas. C'est l'acte de naissance de la cryptographie moderne.

Une précision de vocabulaire pour le chapitre 12 : la sécurité repose non pas exactement sur le logarithme discret, mais sur l'hypothèse — un cran plus forte — que gabg^{ab} est indistinguable d'un élément aléatoire (hypothèse décisionnelle de Diffie-Hellman, DDH). Retenez la distinction, le chapitre 12 la formalisera.

ElGamal et DSA

Diffie-Hellman établit un secret ; on en tire aussitôt un chiffrement et une signature.

ElGamal transforme l'échange en chiffrement. Pour envoyer mm à Bob de clé publique B=gbB = g^b, Alice tire un aléa kk, envoie (gk,  mBk)(g^k,\; m \cdot B^k) ; Bob retrouve Bk=(gk)bB^k = (g^k)^b et divise. Le chiffrement est naturellement probabiliste — l'aléa kk neuf à chaque message — là où RSA devait y être forcé par OAEP.

DSA est le pendant en signature, standardisé par le NIST. Sa sécurité tient à une condition impérative : l'aléa kk de chaque signature doit être secret et unique. La suite du chapitre montre ce que coûte de la violer.

Quiz · 1 question

Dans Diffie-Hellman, que doit résoudre l'espion qui voit g, p, g^a et g^b pour obtenir le secret ?

  • Factoriser pfactorisation
  • Un logarithme discret : retrouver a ou b, puis calculer g^(ab)logarithme discret
  • Une collision de hachage sur g^acollision

Réponse : Le secret est g^(ab). L'espion connaît g^a et g^b mais pas a ni b ; combiner g^a et g^b pour obtenir g^(ab) sans exposant, c'est le problème Diffie-Hellman calculatoire, que l'on ne sait résoudre qu'en calculant un logarithme discret. La factorisation fonde RSA, pas Diffie-Hellman ; les collisions relèvent du hachage.

Résoudre le logarithme discret

Comme pour la factorisation, la taille des paramètres se déduit des meilleures attaques. Il y en a trois familles, et leur portée diffère radicalement selon le groupe.

Pas de bébé, pas de géant (baby-step giant-step). Générique — il marche dans tout groupe. En écrivant x=im+jx = im + j avec m=nm = \lceil\sqrt{n}\rceil, il résout le logarithme discret en O(n)O(\sqrt{n}) opérations et O(n)O(\sqrt{n}) mémoire. Encore un compromis temps-mémoire, dans la lignée du chapitre 6. Vous allez l'implémenter.

Exercice de code

Résolvez un logarithme discret par baby-step giant-step, en ~2√p opérations au lieu de p. Mesurez le gain et déduisez-en pourquoi un groupe d'ordre n n'offre que √n de sécurité.

Point de départ

// On cherche x tel que g^x = h (mod p), dans (Z/pZ)*.
// La force brute essaie x = 0, 1, 2, ... : jusqu'à p−1 multiplications.
// Baby-step giant-step le fait en ~2√p, au prix d'une table de √p entrées.

function puissanceMod(base, exp, mod) {
  let r = 1n; base %= mod;
  while (exp > 0n) {
    if (exp & 1n) r = (r * base) % mod;
    base = (base * base) % mod;
    exp >>= 1n;
  }
  return r;
}
function inverseMod(a, m) {
  let [oldR, r] = [((a % m) + m) % m, m];
  let [oldS, s] = [1n, 0n];
  while (r !== 0n) {
    const q = oldR / r;
    [oldR, r] = [r, oldR - q * r];
    [oldS, s] = [s, oldS - q * s];
  }
  return ((oldS % m) + m) % m;
}

const p = 1000003n;   // premier
const g = 2n;         // générateur
const x = 654321n;    // le secret, à retrouver
const h = puissanceMod(g, x, p);
console.log("instance : 2^x =", h.toString(), "(mod", p.toString() + ")");

// ── Principe ──────────────────────────────────────────────────────────────
// On écrit x = i·m + j  avec  m = ceil(√p),  0 <= i, j < m.
// Alors g^x = h  devient  g^j = h · (g^{-m})^i.
//   • BABY STEPS : tabuler g^j pour tous les j  →  table { g^j : j }
//   • GIANT STEPS : parcourir h·(g^{-m})^i pour i = 0,1,...  jusqu'à tomber
//     dans la table. Alors x = i·m + j.

function racineSup(n) {
  let r = 0n; while (r * r < n) r++; return r;
}

// ── À COMPLÉTER ───────────────────────────────────────────────────────────
function logDiscret(g, h, p) {
  const m = racineSup(p);

  // Baby steps : g^j pour j de 0 à m−1.
  const table = new Map();
  // à compléter : remplir la table

  // Facteur de saut : (g^{-1})^m = g^{-m}.
  const facteur = puissanceMod(inverseMod(g, p), m, p);

  // Giant steps : gamma = h, puis gamma *= facteur à chaque pas.
  let gamma = h % p;
  for (let i = 0n; i < m; i++) {
    // à compléter : si gamma est dans la table, renvoyer i*m + j
    gamma = (gamma * facteur) % p;
  }
  return null;
}

const t0 = Date.now();
const trouve = logDiscret(g, h, p);
console.log("x retrouvé :", trouve && trouve.toString(), "en", Date.now() - t0, "ms");
console.log("correct ?", trouve === x, "| ~2√p =", 2 * Number(racineSup(p)), "opérations, pas", p.toString());

Solution

function logDiscret(g, h, p) {
  const m = racineSup(p);

  // Baby steps.
  const table = new Map();
  let e = 1n;
  for (let j = 0n; j < m; j++) {
    if (!table.has(e)) table.set(e, j);
    e = (e * g) % p;
  }

  const facteur = puissanceMod(inverseMod(g, p), m, p);

  // Giant steps.
  let gamma = h % p;
  for (let i = 0n; i < m; i++) {
    if (table.has(gamma)) return i * m + table.get(gamma);
    gamma = (gamma * facteur) % p;
  }
  return null;
}

// x = 654321 est retrouvé en ~2·1000 = 2000 opérations au lieu de 10^6.
//
// C'est encore un compromis temps-mémoire (chapitre 6) : le TEMPS passe de p à
// 2√p, la MÉMOIRE coûte √p entrées. Le rho de Pollard obtient le même √p en
// temps SANS la mémoire — c'est lui qu'on utilise en pratique.
//
// La conséquence dimensionne les schémas : la sécurité d'un groupe d'ordre n
// n'est que de √n, soit la MOITIÉ des bits. Un logarithme discret « 128 bits »
// exige donc un sous-groupe d'ordre 256 bits. Sur les courbes elliptiques
// (chapitre 11), rho de Pollard EST la meilleure attaque connue, d'où une clé
// de 256 bits pour 128 bits de sécurité. Dans (Z/pZ)*, le calcul d'indices, lui
// sous-exponentiel, fait bien mieux — d'où des modules p de 3072 bits.

Rho de Pollard. Générique lui aussi, il atteint le même O(n)O(\sqrt{n}) en temps mais avec une mémoire négligeable — il exploite le paradoxe des anniversaires du chapitre 7 pour provoquer un cycle. C'est l'attaque de référence en pratique, et la seule qui compte sur les courbes elliptiques.

Calcul d'indices. Spécifique à (Z/pZ)(\mathbb{Z}/p\mathbb{Z})^*, il est sous-exponentiel, de la même forme que le crible de factorisation. C'est lui qui rend RSA et le Diffie-Hellman modulaire comparables, et qui impose des modules pp de 3072 bits pour 128 bits de sécurité. Le point décisif du chapitre 11 : ce calcul d'indices n'a pas d'équivalent sur les courbes elliptiques, où seul le rho de Pollard s'applique. D'où des clés de 256 bits pour la même sécurité.

La règle générique à retenir : un groupe d'ordre nn n'offre que n\sqrt{n} de résistance, soit la moitié des bits. Un logarithme discret « 128 bits » exige donc un sous-groupe d'ordre 256 bits — exactement la taille des clés de courbe.

Deux fautes classiques

L'homme du milieu. Diffie-Hellman brut n'authentifie personne. Mallory intercepte, établit un secret avec Alice d'un côté et avec Bob de l'autre, et relaie en déchiffrant tout au passage. Chacun croit parler à l'autre. C'est la distinction attaquant passif / actif du chapitre 1 dans toute sa force : le protocole résiste parfaitement au premier et s'effondre devant le second. La parade est d'authentifier les échanges — signatures, certificats — et c'est tout l'objet du chapitre 13. Diffie-Hellman n'est jamais déployé nu.

Le nonce rejoué de DSA. Si deux signatures DSA réutilisent le même aléa kk, deux équations linéaires à deux inconnues suffisent à extraire kk, puis la clé privée. Ce n'est pas théorique : la console PlayStation 3 signait son code avec un kk constant, et la clé privée de Sony en a été extraite en 2010. Même un kk simplement biaisé — quelques bits prévisibles — se casse par les réseaux euclidiens du bloc V. On retrouve, transposé à la signature, le nonce rejoué des chapitres 3 et 5 : la faute la plus tenace de la discipline.

Quiz · 1 question

Pourquoi un groupe d'ordre n n'offre-t-il qu'environ √n de sécurité contre le logarithme discret ?

  • Parce que le calcul d'indices résout tout logarithme en √ncalcul d'indices
  • Parce que les attaques génériques — pas de bébé/pas de géant, rho de Pollard — tournent en O(√n)attaques génériques
  • Parce que la moitié des éléments du groupe sont des générateursgénérateurs

Réponse : Baby-step giant-step et le rho de Pollard résolvent le logarithme discret dans tout groupe d'ordre n en O(√n) opérations — la moitié des bits. Il faut donc un ordre de 256 bits pour 128 bits de sécurité. Le calcul d'indices fait ENCORE mieux, mais seulement dans (Z/pZ)*, pas sur les courbes elliptiques — ce qui explique l'écart de tailles du chapitre 11.

Ce que la suite en fait

Le logarithme discret a fondé l'échange de clés, le chiffrement et la signature sur un problème autre que la factorisation. Le chapitre 11 change de groupe sans changer d'idée : il remplace (Z/pZ)(\mathbb{Z}/p\mathbb{Z})^* par les points d'une courbe elliptique, où le calcul d'indices s'évanouit et où les clés deviennent courtes — ECDH et ECDSA sont les versions elliptiques de ce chapitre. Le chapitre 13 authentifiera enfin ces échanges pour clore l'homme du milieu, et le chapitre 14 rappellera que Shor abat le logarithme discret aussi sûrement que la factorisation.

À retenir

Flashcards · 3 cartes

Comment Diffie-Hellman fabrique-t-il un secret commun sans qu'aucun des deux ne le choisisse ?
Alice envoie g^a, Bob envoie g^b. Alice calcule (g^b)^a, Bob calcule (g^a)^b : tous deux obtiennent g^(ab). L'espion voit g^a et g^b mais ne peut en tirer g^(ab) sans résoudre un logarithme discret. Le secret émerge des deux aléas ; ni l'un ni l'autre ne l'a choisi.
Trois algorithmes pour le logarithme discret : lequel s'applique où, et avec quel coût ?
Pas de bébé/pas de géant et rho de Pollard sont GÉNÉRIQUES, en O(√n) — Pollard sans mémoire, c'est la référence sur courbes. Le calcul d'indices est SOUS-exponentiel mais spécifique à (Z/pZ)*, absent des courbes. D'où : 3072 bits pour un module p, 256 bits pour une courbe, à sécurité 128 bits égale.
Que se passe-t-il si deux signatures DSA réutilisent le même aléa k ?
Deux équations linéaires à deux inconnues donnent k, puis la CLÉ PRIVÉE. La PlayStation 3 signait avec un k constant : la clé privée de Sony a été extraite en 2010. Même un k faiblement biaisé se casse par les réseaux. C'est le nonce rejoué des chapitres 3 et 5, transposé à la signature — un aléa, une fois.

Chapitre 3 · 6 h

Courbes elliptiques

Loi de groupe, ECDH, ECDSA, choix de courbes, et l'avantage en taille de clé à sécurité égale.

Le chapitre 10 a fondé l'échange de clés sur le logarithme discret dans (Z/pZ)(\mathbb{Z}/p\mathbb{Z})^* — au prix de modules de 3072 bits, parce que le calcul d'indices y est redoutablement efficace. Ce chapitre change de groupe sans changer d'idée. Sur une courbe elliptique, le calcul d'indices n'a pas d'équivalent connu, seul le rho de Pollard subsiste, et une clé de 256 bits suffit là où RSA en réclame 3072. C'est pourquoi tout ce qui se déploie aujourd'hui — TLS, Signal, les passeports biométriques, Bitcoin — est elliptique.

Un groupe fait de points

Une courbe elliptique sur un corps fini Fp\mathbb{F}_p (le corps du chapitre 2) est l'ensemble des points (x,y)(x, y) vérifiant

y2=x3+ax+b(modp)y^2 = x^3 + ax + b \pmod p

auxquels on ajoute un point spécial, le point à l'infini O\mathcal{O}. Ce qui transforme cet ensemble en un objet cryptographique, c'est qu'on peut additionner deux points pour en obtenir un troisième, et que cette addition fait des points un groupe.

La règle est géométrique. Pour additionner PP et QQ, on trace la droite qui les joint ; elle recoupe la courbe en un troisième point, dont on prend le symétrique par rapport à l'axe des abscisses. Quand P=QP = Q, la droite devient la tangente. Le point O\mathcal{O} joue le rôle du neutre — c'est le zéro du groupe.

Traduites en formules dans le corps, ces constructions géométriques deviennent quelques divisions et multiplications modulaires. Implémentez-les : tout le chapitre tient dans cette unique opération.

Exercice de code

Implémentez la loi de groupe sur une courbe elliptique (sécante et tangente), vérifiez-la, et regardez ECDH en découler directement.

Point de départ

// Courbe  y² = x³ + ax + b  sur le corps F_p (chapitre 2).
// Le point à l'infini O est le neutre, noté null ici.

const p = 233n, a = 1n, b = 44n; // petite courbe pour l'exemple

function inverseMod(x, m) {
  let [oR, r] = [((x % m) + m) % m, m], [oS, s] = [1n, 0n];
  while (r !== 0n) { const q = oR / r; [oR, r] = [r, oR - q * r]; [oS, s] = [s, oS - q * s]; }
  return ((oS % m) + m) % m;
}
const mod = (x) => ((x % p) + p) % p;

function surLaCourbe(P) {
  if (P === null) return true;
  return mod(P.y * P.y) === mod(P.x * P.x * P.x + a * P.x + b);
}

// ── L'addition de deux points ─────────────────────────────────────────────
// Règle géométrique : la droite par P et Q recoupe la courbe en un troisième
// point ; son symétrique par rapport à l'axe des x est P + Q.
//   • pente sécante  λ = (yQ − yP) / (xQ − xP)      si P ≠ Q
//   • pente tangente λ = (3xP² + a) / (2yP)         si P = Q (doublement)
//   • xR = λ² − xP − xQ,   yR = λ(xP − xR) − yP
// Cas particuliers : O neutre, et P + (−P) = O quand xP = xQ, yP = −yQ.

function addition(P, Q) {
  if (P === null) return Q;
  if (Q === null) return P;
  if (P.x === Q.x && mod(P.y + Q.y) === 0n) return null; // P + (−P) = O

  let lambda;
  if (P.x === Q.x && P.y === Q.y) {
    // à compléter : pente de la TANGENTE (doublement)
    lambda = 0n;
  } else {
    // à compléter : pente de la SÉCANTE
    lambda = 0n;
  }
  const xR = mod(lambda * lambda - P.x - Q.x);
  const yR = mod(lambda * (P.x - xR) - P.y);
  return { x: xR, y: yR };
}

// Égalité de deux points (JSON ne sérialise pas les BigInt).
const egaux = (P, Q) =>
  (P === null && Q === null) ||
  (P !== null && Q !== null && P.x === Q.x && P.y === Q.y);

// Multiplication scalaire par doublements-et-additions : k·P.
function multiplier(k, P) {
  let R = null, base = P;
  while (k > 0n) {
    if (k & 1n) R = addition(R, base);
    base = addition(base, base);
    k >>= 1n;
  }
  return R;
}

// ── Vérifications ─────────────────────────────────────────────────────────
const G = { x: 3n, y: 105n }; // point de base, sur la courbe
console.log("G sur la courbe ?", surLaCourbe(G));

const P2 = addition(G, G);
console.log("2G =", P2, "| sur la courbe ?", surLaCourbe(P2));
console.log("2G == multiplier(2, G) ?", egaux(P2, multiplier(2n, G)));

// ── ECDH émerge de cette seule opération ──────────────────────────────────
const a_priv = 17n, b_priv = 23n;          // secrets d'Alice et Bob
const A = multiplier(a_priv, G);           // clé publique d'Alice
const B = multiplier(b_priv, G);           // clé publique de Bob
const secretAlice = multiplier(a_priv, B); // a·(b·G)
const secretBob = multiplier(b_priv, A);   // b·(a·G)
console.log("secret partagé identique ?", egaux(secretAlice, secretBob));

Solution

function addition(P, Q) {
  if (P === null) return Q;
  if (Q === null) return P;
  if (P.x === Q.x && mod(P.y + Q.y) === 0n) return null;

  let lambda;
  if (P.x === Q.x && P.y === Q.y) {
    // Tangente : dérivée implicite de y² = x³ + ax + b.
    lambda = mod((3n * P.x * P.x + a) * inverseMod(2n * P.y, p));
  } else {
    // Sécante : pente ordinaire, division dans le corps.
    lambda = mod((Q.y - P.y) * inverseMod(Q.x - P.x, p));
  }
  const xR = mod(lambda * lambda - P.x - Q.x);
  const yR = mod(lambda * (P.x - xR) - P.y);
  return { x: xR, y: yR };
}

// Tous les tests passent : 2G est sur la courbe, et le secret ECDH coïncide.
//
// Le point clé : ECDH est Diffie-Hellman (chapitre 10) où l'exponentiation
// g^x est remplacée par la multiplication scalaire x·G. Alice calcule a·(b·G),
// Bob calcule b·(a·G) — même point, car la multiplication scalaire commute.
// L'espion voit G, a·G, b·G et doit retrouver a·b·G : c'est le logarithme
// discret SUR LA COURBE, et seul le rho de Pollard s'y applique (pas de calcul
// d'indices). D'où 256 bits de clé pour 128 bits de sécurité, contre 3072 bits
// en RSA. Toute la construction tient dans cette unique addition de points.
//
// ECDSA signe avec la même structure — et hérite du même impératif que DSA :
// un nonce k unique et secret, sous peine de fuite de la clé privée.

ECDH et ECDSA : le chapitre 10, transposé

Une fois l'addition définie, la multiplication scalaire kP=P+P++Pk \cdot P = P + P + \dots + P (kk fois) se calcule par doublements-et-additions, exactement comme l'exponentiation rapide du chapitre 2. Et tout le chapitre 10 se réécrit mot pour mot, en remplaçant gxg^x par xGx \cdot G :

ECDH. Alice publie aGa \cdot G, Bob publie bGb \cdot G, et tous deux calculent abGa \cdot b \cdot G — le même point, car la multiplication scalaire commute. L'espion voit GG, aGa \cdot G, bGb \cdot G et doit retrouver abGa \cdot b \cdot G : c'est le logarithme discret sur la courbe (ECDLP). Vous l'avez vu émerger de l'exercice, sans rien de neuf.

ECDSA. La signature elliptique, celle de TLS, des certificats, du Bitcoin. Elle hérite intégralement de l'impératif de DSA : chaque signature exige un nonce kk secret et unique. Le chapitre 10 a raconté la PlayStation 3 ; l'histoire s'est répétée sur des portefeuilles Bitcoin dont le générateur d'aléa défaillant produisait des nonces répétés — et les clés privées, donc les fonds, ont été siphonnés. La même faute, encore, et le chapitre 13 dira pourquoi le générateur pseudo-aléatoire est un maillon aussi critique que la primitive elle-même.

Quiz · 1 question

Pourquoi une courbe elliptique de 256 bits offre-t-elle la sécurité d'un RSA de 3072 bits ?

  • Parce que l'addition de points est plus rapide que l'exponentiation modulairevitesse
  • Parce que le calcul d'indices, sous-exponentiel, n'a pas d'équivalent sur les courbes : seul le rho de Pollard en √n subsisteabsence de calcul d'indices
  • Parce que les courbes utilisent des corps plus grandstaille du corps

Réponse : Dans (Z/pZ)*, le calcul d'indices sous-exponentiel force des modules de 3072 bits. Sur une courbe bien choisie, aucun analogue n'est connu : la meilleure attaque reste générique, le rho de Pollard en O(√n). Un ordre de 256 bits donne donc 128 bits de sécurité — la moitié des bits, comme au chapitre 10. La rapidité de l'addition est un bonus, pas la raison de fond.

Choisir une courbe : là où le diable se cache

Toutes les courbes ne se valent pas, et le choix des paramètres est un champ de mines. Une courbe mal choisie effondre la sécurité sans que rien ne le signale.

Certaines familles sont explicitement faibles : les courbes supersingulières et anomales admettent des attaques qui ramènent l'ECDLP à un logarithme discret facile. L'ordre du groupe doit être premier, ou presque, faute de quoi les attaques par sous-groupes (l'analogue du générateur d'ordre trop petit, chapitre 2) s'appliquent. Et l'implémentation doit valider que les points reçus sont bien sur la courbe — l'attaque par courbe invalide, sinon, injecte des points d'un groupe faible.

D'où l'usage de courbes normalisées et auditées : les courbes NIST (P-256), et surtout Curve25519 de Daniel Bernstein, conçue pour rendre l'implémentation correcte par défaut — arithmétique naturellement à temps constant, validation implicite, pas de choix piégeux laissé au développeur. C'est la courbe de Signal, de SSH moderne, de TLS 1.3.

Un mot sur la défiance. Les paramètres des courbes NIST ont été fournis sans justification publique de leurs constantes, ce qui a nourri le soupçon — jamais démontré — d'une porte dérobée, sur fond de l'affaire bien réelle du générateur Dual_EC_DRBG (chapitre 13). Vrai ou non, ce soupçon a suffi à pousser la communauté vers Curve25519, dont chaque constante est justifiée par un critère rigide et vérifiable. La transparence des paramètres est devenue, depuis, un critère de confiance à part entière.

Quiz · 1 question

Pourquoi une implémentation ECDH doit-elle vérifier que les points reçus sont sur la courbe ?

  • Pour éviter une erreur d'arrondi dans les calculsprécision
  • Parce qu'un point hors courbe, ou sur une courbe invalide, peut appartenir à un groupe faible où le logarithme discret est facilecourbe invalide
  • Parce qu'un point hors courbe ralentit la multiplication scalaireperformance

Réponse : L'attaque par courbe invalide envoie un point qui n'est pas sur la courbe attendue mais sur une autre, d'ordre non premier, où le logarithme discret est facile — l'implémentation naïve calcule quand même et fuit des bits de la clé. Valider l'appartenance à la courbe ferme cette porte. Curve25519 rend cette validation implicite, une raison de sa robustesse par défaut.

Ce que la suite en fait

Le bloc asymétrique est complet : RSA, logarithme discret, courbes elliptiques — trois problèmes difficiles, un même schéma de clé publique. Le chapitre 12 prend enfin de la hauteur et formalise ce que « sûr » signifie pour ces objets : les jeux IND-CPA, IND-CCA2, EUF-CMA, et les réductions qui les démontrent — ces réductions qui restaient abstraites tant qu'on n'avait pas RSA et ElGamal en tête. Le chapitre 13 assemblera le tout en TLS 1.3, où ECDH authentifié établit la clé de session. Et le chapitre 14 posera la menace qui plane sur tout ce bloc : l'algorithme de Shor résout le logarithme discret elliptique aussi efficacement qu'il factorise — les clés courtes qui font la force des courbes ne sont d'aucun secours face à lui.

À retenir

Flashcards · 3 cartes

Qu'est-ce qui fait des points d'une courbe elliptique un groupe utilisable en cryptographie ?
Une loi d'addition géométrique : la droite par P et Q recoupe la courbe en un troisième point, dont le symétrique est P + Q (tangente si P = Q), avec le point à l'infini pour neutre. La multiplication scalaire k·P qui en découle joue le rôle de l'exponentiation g^x, et son inverse — l'ECDLP — est le problème difficile.
En quoi ECDH est-il exactement le Diffie-Hellman du chapitre 10 ?
On remplace g^x par x·G. Alice publie a·G, Bob publie b·G, tous deux calculent a·b·G (la multiplication scalaire commute). L'espion doit résoudre l'ECDLP. Seule différence, décisive : pas de calcul d'indices sur les courbes, donc 256 bits de clé pour 128 bits de sécurité au lieu de 3072.
Quels pièges guettent le choix et l'usage d'une courbe, et que fait Curve25519 ?
Courbes supersingulières/anomales faibles, ordre non premier ouvrant les attaques par sous-groupe, points hors courbe injectant un groupe faible (courbe invalide). Curve25519 neutralise ces pièges par construction : temps constant naturel, validation implicite, constantes justifiées — l'implémentation correcte par défaut.

QCM de synthèse — Bloc III — Cryptographie asymétrique

Le QCM ci-dessous porte sur l'ensemble du bloc : plusieurs questions relient les leçons entre elles. En cas d'erreur, le bilan indique le chapitre à revoir.

QCM de bloc · 6 questions

Bloc III — Cryptographie asymétrique

1. Pourquoi une clé de courbe elliptique de 256 bits égale-t-elle un module RSA de 3072 bits à sécurité équivalente ?

  • Parce que l'addition de points est plus rapide que l'exponentiation
  • Parce que le calcul d'indices, sous-exponentiel, n'a pas d'équivalent sur les courbes : seul le rho de Pollard en O(√n) y subsiste
  • Parce que les courbes emploient des corps plus grands

Réponse : Dans (Z/pZ)*, le calcul d'indices sous-exponentiel force des modules de 3072 bits. Sur une courbe bien choisie, aucun analogue n'est connu : la meilleure attaque reste générique (rho de Pollard, O(√n)). Un ordre de 256 bits donne donc 128 bits de sécurité — la moitié des bits, comme pour tout logarithme discret. Cet écart explique l'adoption des courbes.

2. Le nonce rejoué, déjà vu au bloc I, réapparaît en signature. Que se passe-t-il si deux signatures DSA ou ECDSA partagent le même aléa k ?

  • Rien : k est public de toute façon
  • Deux équations linéaires à deux inconnues donnent k, puis la CLÉ PRIVÉE — la PlayStation 3 (k constant) et des portefeuilles Bitcoin en sont morts
  • La signature devient seulement déterministe, sans autre conséquence

Réponse : Deux signatures de même k forment un système linéaire dont on tire k, puis la clé privée. La PlayStation 3 signait avec un k constant (clé de Sony extraite en 2010) ; des portefeuilles Bitcoin à générateur défaillant ont été siphonnés. Même un k faiblement biaisé se casse par les réseaux. C'est le nonce rejoué des blocs précédents, transposé à la signature — un aléa, une fois.

3. Le RSA « textbook » avec e = 3 et un message court se casse par une simple racine cubique. Quelles DEUX fautes se combinent ?

  • Une clé trop courte et un mauvais générateur d'aléa
  • Un exposant minuscule (m³ peut ne pas déborder n, donc c = m³) ET l'absence de rembourrage, qui laisse le message trop petit
  • Un module non premier et une signature non vérifiée

Réponse : Si m³ < n, la réduction « mod n » ne retire rien : c est le cube exact de m, et la racine cubique entière rend m — sans clé privée ni factorisation. Deux fautes cumulées : e = 3 si petit que m³ ne déborde pas, et aucun rembourrage. OAEP corrige les deux — le message occupe alors tout l'espace modulo n, et le chiffrement devient probabiliste (et IND-CCA2).

4. Une signature RSA-PSS ou ECDSA signe le HACHÉ du message. Quelle conséquence sur sa sécurité ?

  • Aucune : le haché n'est qu'une optimisation de vitesse
  • Une collision sur la fonction de hachage est une signature forgée — un faux certificat X.509 a été fabriqué en 2008 via une collision MD5
  • Le haché doit être secret, sinon la signature fuit

Réponse : Puisqu'on signe le haché, deux messages de même empreinte ont la même signature : une collision est une signature valide transférée d'un message à un autre. C'est le pont avec le bloc II — la sécurité d'une signature n'excède jamais la résistance aux collisions de son haché. Un faux certificat a été forgé en 2008 exactement ainsi, sur une collision MD5.

5. La sécurité de RSA repose sur la difficulté de factoriser n. Qu'est-ce qui, précisément, n'est PAS prouvé ?

  • Que factoriser n donne la clé privée : ce n'est qu'une conjecture
  • Que casser RSA soit AUSSI dur que factoriser : un raccourci contournant la factorisation pourrait exister (hypothèse RSA)
  • Que n soit réellement un produit de deux premiers

Réponse : Factoriser n donne p, q, φ(n) puis d : la sécurité EXIGE donc que factoriser soit dur. Mais l'inverse — que retrouver m à partir de c soit aussi dur que factoriser — n'est pas démontré. Un raccourci contournant la factorisation pourrait exister ; on n'en connaît pas, mais c'est une hypothèse distincte (l'hypothèse RSA), que le bloc IV formalise.

6. Diffie-Hellman brut résiste à l'écoute mais s'effondre devant un attaquant ACTIF. Quelle attaque, et quelle parade annoncée pour plus tard ?

  • L'attaque par faute ; parade : vérifier la signature
  • L'homme du milieu : Mallory établit un secret avec chacun et relaie. Parade : authentifier l'échange (signatures, certificats), l'objet du bloc IV
  • Le calcul d'indices ; parade : agrandir le module

Réponse : Le secret DH est bien calculé, mais rien ne certifie l'identité : Mallory s'intercale, établit un secret avec Alice et un autre avec Bob, et relaie en déchiffrant tout. C'est la distinction passif/actif du bloc 0 dans toute sa force. La parade est l'échange de clés AUTHENTIFIÉ — signer les messages, attester par certificat — développé au bloc IV.