Sécurité prouvéeDans le dialogue d’impression, choisissez « Enregistrer au format PDF » comme destination.
Retour

Cryptographie · C5 Protocoles et pratique · Chapitre 1 · 4 h

Sécurité prouvée

Réductions, jeux de sécurité, IND-CPA, IND-CCA2, EUF-CMA, modèle de l'oracle aléatoire et ses critiques.

Onze chapitres durant, « sûr » a été employé au fil de l'eau — IND-CPA au chapitre 4, EUF-CMA au chapitre 8, IND-CCA2 pour OAEP au chapitre 9. Il est temps de donner à ces sigles leur sens exact. C'est l'objet de la sécurité prouvée : définir précisément ce qu'on démontre, et par quel mécanisme — la réduction — on le rattache à un problème réputé difficile.

Ce chapitre arrive délibérément après les constructions asymétriques. Une réduction reste un exercice formel creux tant qu'on n'a pas RSA et ElGamal en tête comme objets concrets à réduire. Placé au début d'un cours, ce chapitre fait fuir ; placé ici, il range enfin ce qu'on a déjà manipulé.

Prouver, mais prouver quoi ?

La cryptographie ne prouve presque jamais qu'un schéma est sûr dans l'absolu — une telle preuve impliquerait PNPP \neq NP, hors de portée. Elle prouve des énoncés conditionnels : si tel problème est difficile, alors tel schéma est sûr. Toute la valeur est dans la qualité de l'implication et dans la solidité de l'hypothèse.

Trois ingrédients composent un énoncé de sécurité, et il faut les nommer séparément :

Un schéma n'est jamais « sûr » tout court : il est sûr pour tel objectif, dans tel modèle, sous telle hypothèse.

Les jeux de sécurité

On formalise l'objectif comme un jeu entre un défieur et un adversaire. La sécurité est l'affirmation que l'avantage de l'adversaire — l'écart entre son taux de succès et celui du pur hasard — reste négligeable pour tout adversaire polynomial (le vocabulaire du chapitre 1).

IND-CPA (indistinguabilité sous clairs choisis). L'adversaire soumet deux messages m0,m1m_0, m_1 de même longueur. Le défieur tire un bit bb, chiffre mbm_b, rend le chiffré. L'adversaire annonce bb'. Son avantage est Pr[b=b]1/2|\Pr[b' = b] - 1/2|. Que gagner ce jeu soit infaisable est la définition du secret : le chiffré ne dit rien du clair. On retrouve pourquoi un chiffrement déterministe échoue (chapitre 1) — l'adversaire y soumet deux fois le même message et distingue.

IND-CCA2 (sous chiffrés choisis, adaptatif). Même jeu, mais l'adversaire dispose en plus d'un oracle de déchiffrement qu'il peut interroger avant et après avoir reçu le défi — sur tout chiffré sauf le défi lui-même. C'est le modèle le plus fort, et le bon défaut dès qu'un serveur déchiffre : l'oracle de padding du chapitre 4 était précisément une attaque CCA. OAEP vise ce niveau ; le chiffrement authentifié du chapitre 8 l'atteint.

EUF-CMA (inforgeabilité existentielle sous messages choisis). Le jeu des signatures. L'adversaire obtient les signatures de messages de son choix, et gagne s'il produit une signature valide pour un message nouveau. C'est ce que garantissent RSA-PSS (chapitre 9) et ECDSA (chapitre 11).

Quiz · 1 question

Qu'est-ce qui distingue IND-CCA2 d'IND-CPA, et pourquoi ce modèle est-il le bon défaut ?

  • IND-CCA2 autorise des clés plus longueslongueur de clé
  • IND-CCA2 donne à l'adversaire un oracle de déchiffrement, avant et après le défi — le cas d'un serveur qui déchiffreoracle de déchiffrement
  • IND-CCA2 ne suppose aucune hypothèse de difficultésans hypothèse

Réponse : IND-CPA ne donne qu'un oracle de chiffrement ; IND-CCA2 ajoute un oracle de déchiffrement interrogeable même après le défi. C'est le modèle réaliste dès qu'un serveur déchiffre ce qu'on lui envoie — l'attaque par oracle de padding du chapitre 4 était une attaque CCA. Un schéma seulement IND-CPA peut s'y effondrer, d'où le choix d'IND-CCA2 comme cible par défaut.

La réduction, mécanique centrale

Comment démontre-t-on qu'un schéma gagne un jeu ? Par réduction — l'outil que le chapitre 2 a esquissé avec les classes de complexité, ici mis au travail.

On raisonne par contraposée. On suppose qu'existe un adversaire A\mathcal{A} qui gagne le jeu, et l'on construit avec lui un algorithme B\mathcal{B} qui résout le problème réputé difficile. Comme ce dernier est infaisable, un tel A\mathcal{A} ne peut exister. La forme est toujours la même :

adversaire contre le scheˊma    solveur du probleˋme difficile\text{adversaire contre le schéma} \;\Longrightarrow\; \text{solveur du problème difficile}

C'est l'exact analogue des réductions de complexité — on ramène la sécurité d'un objet compliqué à la difficulté d'un problème simple et étudié. On l'a déjà croisée sans la nommer : Merkle-Damgård (chapitre 7) réduit la résistance du haché à celle de sa compression ; la sécurité de RSA (chapitre 9) se raccroche à la factorisation.

Rien ne vaut de l'exécuter une fois. L'exercice transforme un adversaire IND-CPA contre un chiffrement à flot en un distingueur du générateur pseudo-aléatoire sous-jacent, et mesure l'avantage qui se transfère de l'un à l'autre.

Exercice de code

Exécutez une réduction : transformez un adversaire IND-CPA en distingueur du générateur pseudo-aléatoire sous-jacent, et mesurez l'avantage transféré.

Point de départ

// Chiffrement : c = m ⊕ PRG(clé, nonce). S'il existe un adversaire A qui gagne
// le jeu IND-CPA, on FABRIQUE avec lui un distingueur du PRG. Donc : PRG sûr ⇒
// chiffrement IND-CPA. On code la réduction et on la mesure.

// Une suite FRAÎCHE à chaque appel (nouveau nonce). Deux mondes :
//   pseudo = true  : pseudo-aléatoire, avec une FAILLE volontaire — le bit de
//                    poids faible du premier octet est toujours 0 ;
//   pseudo = false : vraiment aléatoire, aucune structure à exploiter.
let compteurNonce = 1;
function suiteFraiche(pseudo, longueur) {
  if (!pseudo) {
    return Array.from({ length: longueur }, () => (Math.random() * 256) | 0);
  }
  let x = (compteurNonce++ * 2654435761) >>> 0 || 1;
  const out = [];
  for (let i = 0; i < longueur; i++) {
    x ^= x << 13; x >>>= 0; x ^= x >> 17; x ^= x << 5; x >>>= 0;
    out.push(i === 0 ? (x & 0xfe) : (x & 0xff)); // biais sur l'octet 0
  }
  return out;
}
const xor = (a, b) => a.map((v, i) => v ^ b[i]);

// ── L'adversaire IND-CPA ──────────────────────────────────────────────────
// Il soumet m0 et m1 (de bits 0 différents sur l'octet 0), reçoit le chiffré de
// l'un, et devine lequel en exploitant le biais : l'octet 0 de la suite ayant
// son bit 0 à 0, l'octet 0 du clair a le même bit 0 que celui du chiffré.
function adversaire(chiffre, m0) {
  const bit0Clair = chiffre[0] & 1;
  return bit0Clair === (m0[0] & 1) ? 0 : 1;
}

// ── À COMPLÉTER : la réduction ────────────────────────────────────────────
// Le distingueur joue le jeu IND-CPA en masquant avec le PRG testé, sur de
// NOMBREUX défis indépendants (un masque frais par défi). Si l'adversaire gagne
// bien plus qu'une fois sur deux, le PRG était pseudo-aléatoire : le biais l'a
// trahi. Sinon, il était vrai aléa.
function tauxDeSucces(pseudo) {
  const m0 = [0, 0, 0, 0]; // bit 0 de l'octet 0 = 0
  const m1 = [1, 0, 0, 0]; // bit 0 de l'octet 0 = 1
  let succes = 0, tours = 2000;
  for (let t = 0; t < tours; t++) {
    const b = Math.random() < 0.5 ? 0 : 1;
    const s = suiteFraiche(pseudo, 4); // masque FRAIS à chaque défi
    // à compléter : chiffrer m_b avec s, interroger l'adversaire, compter succès
  }
  return succes / tours;
}

// ── Mesure : la réduction sépare-t-elle les deux mondes ? ──────────────────
const tauxPseudo = tauxDeSucces(true);
const tauxVrai = tauxDeSucces(false);
console.log("succès de l'adversaire, PRG PSEUDO-aléatoire :", (tauxPseudo * 100).toFixed(0) + " %");
console.log("succès de l'adversaire, vrai aléa         :", (tauxVrai * 100).toFixed(0) + " %");
console.log("avantage transféré au PRG :", ((tauxPseudo - tauxVrai) * 100).toFixed(0), "points");

Solution

function tauxDeSucces(pseudo) {
  const m0 = [0, 0, 0, 0];
  const m1 = [1, 0, 0, 0];
  let succes = 0, tours = 2000;
  for (let t = 0; t < tours; t++) {
    const b = Math.random() < 0.5 ? 0 : 1;
    const s = suiteFraiche(pseudo, 4);
    const chiffre = xor(b === 0 ? m0 : m1, s);
    if (adversaire(chiffre, m0) === b) succes++;
  }
  return succes / tours;
}

// Résultat : ~100 % sous le PRG pseudo-aléatoire (le biais de l'octet 0 laisse
// tout passer), ~50 % sous le vrai aléa (rien à exploiter). L'écart d'environ
// 50 points EST l'avantage que la réduction transfère du chiffrement au PRG.
//
// C'est cela, une RÉDUCTION. On ne prouve pas directement que le chiffrement
// est sûr : on établit une IMPLICATION. « Si un adversaire gagne le jeu
// IND-CPA avec un avantage ε, alors on distingue le PRG avec un avantage ε. »
// Par contraposée : PRG indistinguable ⇒ chiffrement IND-CPA. La sécurité du
// schéma est RÉDUITE à celle d'une brique — même mouvement que Merkle-Damgård
// ramenant la résistance du haché à celle de sa compression (chapitre 7).
//
// Le jeu IND-CPA : le défieur tire b, chiffre m_b, l'adversaire rend b' ;
// l'avantage est |Pr[b' = b] − 1/2|, qui doit être négligeable pour tout
// adversaire polynomial (chapitre 1). IND-CCA2 ajoute un oracle de
// déchiffrement même après le défi ; EUF-CMA est le jeu des signatures. Une
// même mécanique partout : un jeu, un avantage, une réduction.

La qualité d'une réduction se mesure. Une réduction est serrée (tight) si B\mathcal{B} réussit avec à peu près le même avantage et le même temps que A\mathcal{A}. Elle est lâche si B\mathcal{B} perd un facteur — disons le nombre de requêtes de l'adversaire. Ce n'est pas un détail théorique : une réduction lâche oblige à augmenter la taille des clés pour compenser la perte, avec un coût de performance bien réel. La finesse de la preuve a un prix en octets.

Quiz · 1 question

Que démontre-t-on exactement en réduisant la sécurité d'un schéma à un problème difficile ?

  • Que le schéma est sûr dans l'absolu, sans aucune hypothèsesécurité absolue
  • Que si un adversaire cassait le schéma, on saurait résoudre le problème réputé difficile — donc, par contraposée, le schéma est sûr sous cette hypothèseimplication conditionnelle
  • Que le problème difficile est en réalité facileproblème facile

Réponse : Une réduction construit, à partir d'un hypothétique casseur du schéma, un solveur du problème difficile. Comme ce problème est supposé infaisable, le casseur ne peut exister : le schéma est sûr SOUS l'hypothèse. La preuve est conditionnelle — elle ne rend pas le problème facile et ne prouve rien dans l'absolu, ce qui exigerait de résoudre P vs NP.

Le modèle de l'oracle aléatoire, et sa controverse

Beaucoup de schémas efficaces — OAEP, PSS, la plupart des signatures — ne se prouvent que dans le modèle de l'oracle aléatoire (ROM). On y fait une idéalisation : la fonction de hachage est traitée comme une fonction parfaitement aléatoire, une boîte noire que tout le monde interroge et qui répond de façon uniforme et cohérente.

Cette idéalisation rend les preuves possibles, et donne à la réduction un pouvoir supplémentaire : elle peut « programmer » l'oracle, choisir ses réponses pour piéger l'adversaire. C'est puissant, et c'est précisément là qu'est la critique.

Car aucune fonction réelle — ni SHA-256, ni SHA-3 — n'est un oracle aléatoire : ce sont des algorithmes publics, déterministes, courts à décrire. Canetti, Goldreich et Halevi ont même construit, en 1998, des schémas prouvés sûrs dans le ROM et cassés dès qu'on remplace l'oracle par n'importe quelle fonction réelle. La preuve ROM n'est donc pas une garantie au sens strict ; c'est une heuristique — un argument de bonne conception, un filtre qui élimine les schémas manifestement faibles, sans certifier les survivants.

La position raisonnable, et celle qu'adopte la pratique : une preuve dans le modèle standard (sans oracle idéalisé) est préférable ; une preuve ROM vaut mieux qu'aucune preuve ; et aucune de l'une ni de l'autre ne protège contre ce qu'aucun modèle ne capture — un canal auxiliaire, un générateur aléatoire défaillant, une clé lue en mémoire. Les preuves cadrent la primitive ; elles ne couvrent pas l'implémentation, qui est le sujet du chapitre 13.

Ce que la suite en fait

Ce chapitre a donné aux mots leur sens exact. Le chapitre 13 quitte les primitives isolées pour les protocoles : TLS 1.3, où un échange de clés authentifié doit atteindre des objectifs de sécurité composés, et où l'on verra que prouver un protocole entier est bien plus dur que prouver une brique. Il montrera aussi combien les hypothèses de ce chapitre sont fragiles face à la réalité — un générateur pseudo-aléatoire biaisé fait s'effondrer des schémas parfaitement prouvés.

À retenir

Flashcards · 3 cartes

Quels trois ingrédients composent un énoncé de sécurité, et pourquoi aucun ne suffit seul ?
Un objectif (que veut-on empêcher : distinguer, forger), un modèle d'attaque (les moyens de l'adversaire, COA à CCA2), une hypothèse (le problème supposé dur : factorisation, log discret, DDH). Un schéma n'est jamais « sûr » tout court, mais sûr POUR tel objectif, DANS tel modèle, SOUS telle hypothèse.
En quoi consiste une réduction de sécurité, et que signifie qu'elle soit « serrée » ?
Par contraposée : d'un hypothétique adversaire contre le schéma, on CONSTRUIT un solveur du problème difficile ; comme il est infaisable, l'adversaire ne peut exister. Elle est serrée si le solveur garde à peu près l'avantage et le temps de l'adversaire ; une réduction lâche perd un facteur, qu'il faut compenser en agrandissant les clés.
Qu'est-ce que le modèle de l'oracle aléatoire, et pourquoi une preuve ROM n'est-elle qu'une heuristique ?
On y idéalise la fonction de hachage en une fonction parfaitement aléatoire, ce qui rend les preuves possibles (OAEP, PSS). Mais aucune fonction réelle ne l'est, et Canetti-Goldreich-Halevi (1998) ont exhibé des schémas prouvés ROM et cassés par toute fonction concrète. Une preuve ROM est un bon filtre de conception, pas une garantie ; elle ne couvre pas non plus les canaux auxiliaires.