đ ParamĂštres RSA (exemple pĂ©dagogique)
Initiales de : Rivest, Shamir et Adleman les découvreurs de ce chiffrement
Supposons que nous avons :
p = 17,q = 19â deux petits nombres premiers, volontairement pour des raisons pĂ©dagogiquen = p Ă q = 17 Ă 19 = 323Ï(n) = (pâ1)(qâ1) = 16 Ă 18 = 288e = 7(choisi tel quegcd(e, Ï) = 1)d = 247(car7 Ă 247 ⥠1 mod 288â inverse modulaire de 7 mod 288)
âïž Message Ă chiffrer : 'A'
- Code ASCII de
'A'=65 - On veut chiffrer ce nombre avec la clé publique
(e = 7, n = 323)
đ Chiffrement
Formule : C=MemodâânC = M^e \mod nC=Memodn C=657modââ323C = 65^7 \mod 323C=657mod323
Faisons les puissances successives (modulo 323) :
- 652=4225modââ323=4225â13Ă323=4225â4199=2665^2 = 4225 \mod 323 = 4225 – 13Ă323 = 4225 – 4199 = 26652=4225mod323=4225â13Ă323=4225â4199=26
- 654=(652)2=262=676modââ323=676â2Ă323=676â646=3065^4 = (65^2)^2 = 26^2 = 676 \mod 323 = 676 – 2Ă323 = 676 – 646 = 30654=(652)2=262=676mod323=676â2Ă323=676â646=30
- 657=65Ă652Ă654=65Ă26Ă3065^7 = 65 Ă 65^2 Ă 65^4 = 65 Ă 26 Ă 30657=65Ă652Ă654=65Ă26Ă30
Calcul :
- 26Ă30=78026 Ă 30 = 78026Ă30=780
- 780Ă65=50700780 Ă 65 = 50700780Ă65=50700
- 50700modââ323=50700â157Ă323=50700â50711=â11âĄ312modââ32350700 \mod 323 = 50700 – 157Ă323 = 50700 – 50711 = -11 ⥠312 \mod 32350700mod323=50700â157Ă323=50700â50711=â11âĄ312mod323
đ Message chiffrĂ© = 312
đ DĂ©chiffrement
Formule : M=Cdmodâân=312247modââ323M = C^d \mod n = 312^{247} \mod 323M=Cdmodn=312247mod323
Câest long Ă faire Ă la main, mais en pratique on utiliserait l’exponentiation rapide ou un programme. Si on le fait (ou vĂ©rifie) Ă la machine : 312247modââ323=65312^{247} \mod 323 = 65312247mod323=65
âïž On retrouve bien le message original !
chiffrement pourquoi ?
Pourquoi câest un chiffrement, concrĂštement ?
- Transforme le message (texte clair) en un code incompréhensible (texte chiffré)
Ici, on transforme le nombreM = 65enC = 312. Sans la clé privée,312ne veut rien dire. - Reversible seulement avec la clé privée
Le dĂ©chiffrement utilise la clĂ© privĂ©edpour inverser lâopĂ©ration et retrouver le message initialM. - BasĂ© sur un problĂšme mathĂ©matique difficile
Le chiffrement RSA repose sur la difficulté de factorisern(ici 323) en ses facteurs premiers (petq).- Si tu ne connais pas
petq, il est extrĂȘmement compliquĂ© (pour des grands nombres) de calculerdet donc de dĂ©chiffrer. - Sans
d, tu ne peux pas récupérer le message clair.
- Si tu ne connais pas
- Fonction mathématique asymétrique
- Clé publique
epermet de chiffrer. - Clé privée
dpermet de déchiffrer.
Chiffrer aveceest facile, mais sansd, inverser la fonction est « facile Ă faire dans un sens, difficile dans lâautre ».
- Clé publique
En résumé :
- Tu passes du message clair (
M) au message chiffré (C) grùce à la clé publique. - Seule la clé privée peut transformer
CenM. - Sans la clĂ© privĂ©e, mĂȘme en connaissant
Cet la clĂ© publique, tu ne peux pas retrouverM(au moins pour des grands nombres). - Le message chiffrĂ© est un secret codĂ© que personne dâautre ne peut lire.
Théorie
On va volontairement travailler sur 16 bits pour comprendre le principe!
â Concepts RSA simplifiĂ©s :
- Choisir deux petits nombres premiers
petq. - Calculer
n = p * q. - Calculer
Ï(n) = (p-1) * (q-1). - Choisir un exposant
etel que1 < e < Ï(n)eteest premier avecÏ(n). - Calculer
d, l’inverse modulaire deemoduloÏ(n).
- Clé publique :
(e, n) - Clé privée :
(d, n) - Chiffrement :
c = m^e mod n - Déchiffrement :
m = c^d mod n
Clé privée / public 16 bits
// genrsa16.c : GénÚre une paire de clés RSA 16 bits
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <math.h>
bool est_premier(int n) {
if (n < 2) return false;
if (n % 2 == 0) return n == 2;
for (int i = 3; i <= sqrt(n); i += 2)
if (n % i == 0) return false;
return true;
}
int pgcd(int a, int b) {
while (b != 0) {
int tmp = b;
b = a % b;
a = tmp;
}
return a;
}
// Inverse modulaire : retourne d tel que (d * e) % phi == 1
int mod_inverse(int e, int phi) {
int t = 0, newt = 1;
int r = phi, newr = e;
while (newr != 0) {
int quotient = r / newr;
int tmp = newt;
newt = t - quotient * newt;
t = tmp;
tmp = newr;
newr = r - quotient * newr;
r = tmp;
}
if (r > 1) return -1; // Pas d'inverse
if (t < 0) t += phi;
return t;
}
int main() {
srand(time(NULL));
int p, q;
do {
p = rand() % 256;
} while (!est_premier(p));
do {
q = rand() % 256;
} while (!est_premier(q) || q == p);
int n = p * q;
int phi = (p - 1) * (q - 1);
int e;
do {
e = rand() % phi;
} while (pgcd(e, phi) != 1 || e <= 1);
int d = mod_inverse(e, phi);
printf("Clé publique (e, n) : (%d, %d)\n", e, n);
printf("Clé privée (d, n) : (%d, %d)\n", d, n);
printf("p = %d, q = %d, Ï(n) = %d\n", p, q, phi);
return 0;
}
bruno@debian:~/Works/langageC/rsa16$ ./genrsa16
Clé publique (e, n) : (6107, 10823)
Clé privée (d, n) : (5555, 10823)
p = 79, q = 137, Ï(n) = 10608
p = 79, q = 137
n = 79 Ă 137 = 10823
Ï(n) = (p-1)Ă(q-1) = 78 Ă 136 = 10608
Clé publique : (e = 6107, n = 10823)
Clé privée : (d = 5555, n = 10823)
Concepts Mathématiques utilisés
modulo (mod)
on a besoin de mod , qui est simplement le reste .
17/5= 3 et il reste 2
donc 17 mod 5 = 2
La congruence
on a besoin de la congruence.
ce symbole ⥠« congruent »
aâĄb mod n
| Terme | Signification |
|---|---|
| a ⥠b modâân | a et b laissent le mĂȘme reste modulo n |
| MĂȘme reste | â congruence |
| Base des maths modulaires | cryptographie, informatique |
Exemple de code C pour savoir si a et congru a b modulo n
congrus.c
#include <stdio.h>
#include <stdlib.h>
// Fonction qui teste si a ⥠b mod n
int est_congru(int a, int b, int n) {
return ((a - b) % n == 0);
}
int main() {
int a, b, n;
printf("Entrez a : ");
scanf("%d", &a);
printf("Entrez b : ");
scanf("%d", &b);
printf("Entrez le modulo n : ");
scanf("%d", &n);
if (est_congru(a, b, n)) {
printf("%d et %d sont congrus modulo %d : %d ⥠%d mod %d\n", a, b, n, a, b, n);
} else {
printf("%d et %d ne sont pas congrus modulo %d\n", a, b, n);
}
return EXIT_SUCCESS;
}
bruno@debian:~/Works/langageC/congruent$ ./congrus
Entrez a : 17
Entrez b : 2
Entrez le modulo n : 5
17 et 2 sont congrus modulo 5 : 17 ⥠2 mod 5
Génération :
p, q â choisis alĂ©atoirement (premiers)
n = p Ă q
Ï(n) = (p – 1) Ă (q – 1) , la fonction d’euler
e = exposant public, tel que gcd(e, Ï(n)) = 1
d = inverse modulaire de e mod Ï(n)
Clés :
Publique = (e, n)
Privée = (d, n)
exemple:
p = 17 et q = 11
n = p Ă q = 17 Ă 11 = 187
Ï(n) = (p – 1) Ă (q – 1) = 16 Ă 10 = 160
â
Choix de e (exposant public)
On veut 1 < e < Ï(n) et gcd(e, Ï(n)) = 1.
Prenons par exemple e = 7.
â VĂ©rification :
gcd(7, 160) = 1 â OK
â
Calcul de d (exposant privé)
On cherche d tel que :
d à e ⥠1 mod 160
d à 7 ⥠1 mod 160
On rĂ©sout cette Ă©quation avec lâinverse modulaire.
đ§ź RĂ©sultat (via lâalgorithme dâEuclide Ă©tendu) :
d = 23 (car 23 à 7 = 161 ⥠1 mod 160)
â RĂ©sumĂ© des clĂ©s
| Clé | Valeur |
|---|---|
| Publique | (e = 7, n = 187) |
| Privée | (d = 23, n = 187) |
Exemple avec Alice et Bob
Imaginons que Bob veut envoyer le nombre 88 Ă Alice.
Chiffrement (Bob utilise la clé publique (7, 187))
luaCopierModifier
c = m^e mod n
= 88^7 mod 187
88^7 = 33232930569601
33232930569601 mod 187 = 11
đ Message chiffrĂ© : c = 11
đ DĂ©chiffrement (Alice utilise sa clĂ© privĂ©e (23, 187))
m = c^d mod n = 11^23 mod 187
11^23 mod 187 = 88
â
Message dâorigine retrouvĂ© : m = 88
đ Conclusion
p = 17,q = 11n = 187,Ï(n) = 160e = 7,d = 23- Message original :
88 - Message chiffré :
11 - Message déchiffré :
88
rsa_demo.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
// Fonction d'exponentiation modulaire rapide : (base^exp) % mod
long long modexp(long long base, long long exp, long long mod) {
long long result = 1;
base %= mod;
while (exp > 0) {
if (exp % 2 == 1) // exp impair
result = (result * base) % mod;
base = (base * base) % mod;
exp /= 2;
}
return result;
}
int main(void) {
// Clés RSA fixes pour démonstration
long long p = 17;
long long q = 11;
long long n = p * q; // n = 187
long long phi = (p - 1) * (q - 1); // phi = 160
long long e = 7; // clé publique
long long d = 23; // clé privée
printf("Clé publique (e = %lld, n = %lld)\n", e, n);
printf("Clé privée (d = %lld, n = %lld)\n\n", d, n);
// Message clair Ă chiffrer
long long message;
printf("Entrez un message (entier < %lld) Ă chiffrer : ", n);
if (scanf("%lld", &message) != 1 || message <= 0 || message >= n) {
fprintf(stderr, "EntrĂ©e invalide. Le message doit ĂȘtre un entier entre 1 et %lld.\n", n - 1);
return EXIT_FAILURE;
}
// Chiffrement
long long chiffre = modexp(message, e, n);
printf("\nMessage chiffré : %lld\n", chiffre);
// Déchiffrement
long long dechiffre = modexp(chiffre, d, n);
printf("Message déchiffré : %lld\n", dechiffre);
return EXIT_SUCCESS;
}
Entrez un message (entier < 187) Ă chiffrer : 88
Message chiffré : 11
Message déchiffré : 88
