AFFICHER CET ARTICLE EN MODE PAGE ENTIERE

Sommaire

1) Rappels arithmétique
__1.1) Nombres premiers
__1.2) Congruence
__1.3) Algorithme d'Euclide

2) Introduction

3) Un peu d'histoire

4) Le principe abstrait
__4.1) Choix des clés
__4.2) Cryptage
__4.3) Décryptage

5) Exemple concret
__5.1) Choix des clés
__5.2) Cryptage
__5.3) Décryptage

6) Cracker RSA

7) Avantages et inconvénients

8) Conclusion

 


 

1) Rappels arithmétiques

1.1 Nombres premiers

Un nombre premier est un nombre qui n'est divisible que par 1 ou par lui - même ( une liste des 10 000 premiers nombres premiers est à ce lien).
Dire qu'un un nombre est premier avec un autre signifie que le PGCD de ces deux nombres est 1.

1.2 Congruence

a et b appartiennent à l'ensemble Z.
a et b sont congrues modulo n ssi a et b ont le même reste dans la division euclidienne par n, ou bien plus simplement si (a-b) est divisible par n.
a et b congrue modulo n s'écrit : .a b (mod n)
__________________________-a b [n]

1.3 Algorithme d'Euclide

a et b apartiennnent à N* (les entiers naturels privés de 0), on suppose b < a
On utilise l'algorithme d'Euclide c'est à dire on remplace le couple (a ; b) par des couples de nombre de plus en plus petit qui ont le même ensemble de diviseur compris.

Operations
Reste
Commentaire
on divise a par b
r0
0 ≤ ro < b et PGCD (a , b) = PGCD (b , r0)
si r0 ≠ 0 on divise b par r0
r1
0 ≤ r1< r0 et PGCD (b , r0) = PGCD (r0 , r1)
si r1≠ 0 on divise r0 par r1
r2
0 ≤ r2< r1 et PGCD (r0 , r1) = PGCD (r1 , r2)
.....
....
....
....
....
....
....
r(n)
....
si r(n)≠ 0 on divise r(n-1) par r(n)
....
PGCD ( r(n-2) , r(n-1) ) = r(n)


Après un nombre finie d'opération, on trouve un reste non nul, car les restes sont des nombres positifs et strictement décroissant.
On note r(n) le dernier reste non nul.
PGCD (a , b) = PGCD (b , r0)
___________= PGCD (r0 , r1)
___________= ....
___________= PGCD ( r(n-1) , r(n) )
___________= r(n)

Lorsque b ne divise pas a, le PGCD des entiers naturels non nuls a et b est égal au dernier reste non nul obtenu par l'algorithme d'Euclide;

Ex : PGCD (1636 , 1128)
1636 = 1128 * 1 + 208
1128 = 508 * 2 + 112
508 = 112 * 4 + 60
112 = 60 * 1 + 52
60 = 52 * 1 + 8
52 = 8 * 6 + 4
8 = 4 * 2

PGCD (1636 , 1128) = 4.

 

2) Introduction

Cet article a pour but de vous expliquer le fonctionnement de la très célèbre methode de cryptage RSA (du nom de ses créateurs Ronald Rivest, Adi Shamir et Léonard Adleman.).

 

 

3) Un peu d'histoire

Développé au MIT (Massachussets Institute of Technology) en 1977 par Ronald Rivest, Adi Shamir et Leonard Adleman, le système RSA est un système à clef publique très sûr. Il est intéressant de noter que son invention est fortuite : au départ, Rivest, Shamir et Adleman voulaient prouver que tout système à clé publique possède une faille.

La puissance de chiffrement du RSA repose sur le fait que tous les systèmes peuvent être en définitive forcés, mais que l'on peut parvenir à une sécurité suffisante en rendant totalement irréaliste la quantité de travail qu'il faudrait fournir pour le forcer.

Il est fondé, sur le fait qu'il est très difficile de décomposer en produit de facteurs premier un grand nombre (voir impossible quand le chiffre depasse 150 chiffres), en effet les ordinateurs actuels les plus puissants ne peuvent decomposer en produit de facteur premier un nombre premier comportant plus de 130 chiffres. Personne ne peut le décomposer si ce n'est l'auteur ( pour information d'après Ron Rivest, la décomposition d'un nombre de 200 chiffres nécessite 4 milliards d'années de calculs sur ordinateurs, celle d'un nombre de 500 chiffres plus de 1025 milliards d'années).

En revanche si quelqu'un trouve comment factoriser rapidement de tels nombres, le RSA devient obsolète.

 

4) Le principe abstrait

Toute cette méthode repose principalement sur les nombres premiers.
Le développement du principe s'accompagne de démonstrations : elles nécessitent quelques bases en arithmétique.
Note : les signes , φ et ^ designe bien evidemment respectivement la congruence, phi (variable) et la puissance.

 

4.1 Choix des clés

On choisi 2 nombres premiers p et q (bien sûr plus p et q sont grand plus le cassage du code est difficile car il est difficile de décomposer un très grand nombre en facteurs premiers).
On calcule n = pq et φ(n) = (p - 1) (q - 1).
On choisit ensuite d tel que d premier avec φ(n).
On calcule ensuite e tel que ed 1 (mod φ(n)) avec e < φ(n).

n et e sont publics.
p, q, φ(n) et d sont privés.

cle cleCryptage(void)
{
cle c;
unsigned long int i;
FILE *premier;

premier = fopen("nb_premier_phi.txt","a"); /* On crée un fichier pour stocker les ___________________________________________/* nombres premier avec phi */
if (premier == NULL)
{
__printf("\n\nErreur création du fichier nb_premier_phi.txt");
__exit(42);
}

printf ("\n\nEntrez le nombre a crypter : ");
scanf("%lu",&c.nb);
printf("Entrez le nombre premier p : ");
scanf("%lu",&c.p);
printf("Entrez le nombre premier q : ");
scanf("%lu",&c.q);
printf("\nCALCUL DE LA CLE N EN COURS...");
c.n = c.p*c.q;
printf("\nLa cle n = %lu\n",c.n);
printf("\nCALCUL DE LA CLE PHI EN COURS...");
c.phi = (c.p-1)*(c.q-1);
printf("\nLa cle phi = %lu\n",c.phi);

for (i = 2; i< c.phi/2; i++) /* On incrit dans le fichier tous les nombres */
___if ( c.phi % i != 0) _____/* premiers avec phi jusqu'à phi/2 */
______fprintf(premier,"%lu\n",i);

fclose(premier);

printf("\nUne liste des cles possibles d est disponible dans le fichier" _______"nb_premier_phi.txt");
printf("\nEntrez la cle d (premier avec phi) : ");
scanf("%lu",&c.d);
printf("\nCALCUL DE LA CLE E EN COURS...");

for (c.e=1; c.e < (c.phi*c.phi); c.e++)/* On recherche une chiffre tel que e*d-1*/
___if (((c.e*c.d) % c.phi) == 1)_______/* soit divisible par phi */
______break;

printf("\ne = %lu\n",c.e);
return c;

}

 

 

4.2 Cryptage

Pour crypter un message M avec M < n il suffit de calculer C = M^e (mod n ) :

unsigned long int cryptage(unsigned long int nb, unsigned long int puiss, unsigned long int mod)
{
unsigned long int res = 1, nvar, nvar2;
unsigned long int resultat[100000];
int i, j, k,l; // compteurs
int nnb, compt, var, caze;
int tab[100000], tab2[100000];
int puissa = puiss;

printf("\nCRYPTAGE EN COURS...\n");
for (i=0; i<100000; i++) // on remplit le tableau avec des 5
___tab[i]=5;

for (i=0, compt = -1; puiss > 0; i++, compt++ ) // on convertit la puissance en binaire
{
if (puiss % 2 > 0)
nnb = 1;
if (puiss % 2 == 0)
nnb = 0;
tab[i]=nnb;
puiss = puiss / 2;
}

for (i=0, j=0; tab[i] != 5; i++) // on convertit le binaire en puissance de 2 : par
{________________________________// exemple (11101)b = 16 + 8+ 4 + 1
___if (tab[i] == 1)
____{
______var = puissance(2,i);
______tab2[j] = var;
______j++;
____}
}

l = j; // on sauvegarde la valeur de j cad le nombre d'element ds le tableau tab2[]

resultat[0]=0;
resultat[1]=nb; _______/* On met dans le tableau resultat[] les restes du nombre nb par les */
nvar2 = nb; ___________/* puissances successives jusqu'à la puissance egal au plus grand nombre */
nvar = nb;_____________/* du tableau tab2[] par le modulo mod */
for (i=2; i<=tab2[j-1]+1; i++)
_{ _________________________/* Par exemple pour 29 = 16 + 8 + 4 +1 et pour nb =3 on et dans le tableau */
___nvar2 = nvar * nvar2; ___/* les restes de 3^1, 3^2 jusqu'à 3^16 par le modulo mod */
___nvar2 = nvar2%mod;
___resultat[i] = nvar2;
_}

for (i=0, res=1; i<l; i++) /* Dans la case i du tableau resultat se trouve nb^i */
_{_______________/* Donc à partir du tableau tab2[i] qui contient la décomposition de la puissance puiss*/
___caze=tab2[i]; ___/* res = res * resultat[caze]; /* en puissance de 2 ( 29 = 16 + 8 + 4 + 1), on peut */
_____________________/* obtenir nb^puiss en multipliant */
___if (res > mod)____/* par exemple nb^16, on multiplie les cases
______res = res%mod; /* resultat[16]*resultat[8]*resultat[4]*resultat[1] */
}____________________/* pour obtenir enfin le chiifre crypté on fait le resultat precedent modulo mod */

return res;
}

 

 

4.3 Décryptage

Pour décrypter C il suffit de calculer M = C^d (mod n) (car M C^d (mod n)) :

unsigned long int cryptage(unsigned long int nb, unsigned long int puiss, unsigned long int mod)
{
__________________________________________________// Remarque : c'est exactement la même chose que pour cryptage
unsigned long int res = 1, nvar, nvar2;
unsigned long int resultat[100000];
int i, j, k,l; // compteurs
int nnb, compt, var, caze;
int tab[100000], tab2[100000];
int puissa = puiss;

printf("\nDECRYPTAGE EN COURS...\n");
for (i=0; i<100000; i++) // on remplit le tableau avec des 5
___tab[i]=5;

for (i=0, compt = -1; puiss > 0; i++, compt++ ) // on convertit la puissance en binaire
{
if (puiss % 2 > 0)
nnb = 1;
if (puiss % 2 == 0)
nnb = 0;
tab[i]=nnb;
puiss = puiss / 2;
}

for (i=0, j=0; tab[i] != 5; i++) // on convertit le binaire en puissance de 2 : par
{________________________________// exemple (11101)b = 16 + 8+ 4 + 1
___if (tab[i] == 1)
____{
______var = puissance(2,i);
______tab2[j] = var;
______j++;
____}
}

l = j; // on sauvegarde la valeur de j cad le nombre d'element ds le tableau tab2[]

resultat[0]=0;
resultat[1]=nb; _______/* On met dans le tableau resultat[] les restes du nombre nb par les */
nvar2 = nb; ___________/* puissances successives jusqu'à la puissance egal au plus grand nombre */
nvar = nb;_____________/* du tableau tab2[] par le modulo mod */
for (i=2; i<=tab2[j-1]+1; i++)
_{ _________________________/* Par exemple pour 29 = 16 + 8 + 4 +1 et pour nb =3 on et dans le tableau */
___nvar2 = nvar * nvar2; ___/* les restes de 3^1, 3^2 jusqu'à 3^16 par le modulo mod */
___nvar2 = nvar2%mod;
___resultat[i] = nvar2;
_}

for (i=0, res=1; i<l; i++) /* Dans la case i du tableau resultat se trouve nb^i */
_{_______________/* Donc à partir du tableau tab2[i] qui contient la décomposition de la puissance puiss*/
___caze=tab2[i]; ___/* res = res * resultat[caze]; /* en puissance de 2 ( 29 = 16 + 8 + 4 + 1), on peut */
_____________________/* obtenir nb^puiss en multipliant */
___if (res > mod)____/* par exemple nb^16, on multiplie les cases
______res = res%mod; /* resultat[16]*resultat[8]*resultat[4]*resultat[1] */
}____________________/* pour obtenir enfin le chiifre crypté on fait le resultat precedent modulo mod */

return res;
}

 

5) Exemple concret

5.1 Choix des clés

Tout d'abord on choisit A=3, H=641, D=2, S=201, '-'=1 pour crypter des mots.
Puis on choisit deux nombres premiers p = 29 et q = 31 d'où n = 899.

- On calcule ensuite φ(n) = 28 *30 = 840.
- On choisit ensuite un cadenas d = 29 premier avec φ(n) (cad 840).
- On calcule maintenant e tel que ed 1 (mod 840) pour cela on utilise l'algorithme d'Euclide.
____ 840 = 28*29+28
____-29 = 1*28+1
puis :
____1 = 29-28
____1 = 29 - (840 - 28*29)
____1 = 29 * 29 - 840

- On obtient donc e = 29 car 29*29 1 (mod 840) (29*29-1 est divisible par 840).

 

5.2 Cryptage

Pour crypter le message M : AH-DHS cad M = (3, 641, 1, 2, 641, 201) il suffit de calculer C = (3^29 (mod 899), 641^29 (mod 899), 1^29 (mod 899), 2^29 (mod 899), 641^29 (mod 899), 201^9 (mod 899)).

Pour se faire on peut utiliser le code joint à l'article mais si vous voulez le faire à la main je vais vous donner la technique que j'utilise.

Tout d'abord il faut écrire 29 en binaire : 29 = (11101)b -> 29 = 16 + 8 + 4 + 1
On peut le faire directement si le chiffre n'est pas grand.

3^29 = 3^1 * 3^4 * 3^8 * 3^16 = 3 * 81 * 268 * 803 = 641 (mod 899).

Explication :
3^8 = 6561 mais comme 6561 > 899 on prend 268 car 6561 268 (mod 899).
3^16 ==> de même.

641^29 = 641^1 * 641^4 * 641^8 * 641^16 = 641 * 545 * 355 * 165 = 3 (mod 899).

De même :
1^29 = 1 (mod 899).

2^29 = 698 (mod 899).

201^29 = 897 (mod 899).

Le message envoyé sera donc C = (641, 3, 1, 698, 3, 897).

 

5.3 Décryptage

Pour décrypter le message il suffit de calculer C^d (mod 899) à l'aide du code joint à l'article ou à la main comme je vais l'expliquer.

Dans cet exemple e = d donc le décryptage est très facile, en effet :
641^29 3 (mod 899) (calculer plus haut).
3^29 641 (mod 899).
1^29 1 (mod 899).
698^29 = -201^29 2 (mod 899) car 698 - (-201) = 899.
3^29 641 (mod 899).
897^29 = -2^29 = -698 201 (mod 899) car 897 - (-2) = 899.

On obtient donc le message décrypté M' = (3, 641, 1, 2, 641, 201) cad M' = AH-DHS.
On a bien M = M'.

Si e != d il suffit de faire comme précedemment (pour le cryptage).

Exemple :
avec d = 15.
15 = 8 + 4 + 2 + 1.

641^15 = 641^1 + 641^ 2 + 641^4 + 641^8 = 641 * 38 * 545 * 355 = 867 (mod 899).
Bien sûr ici 867 ne correspond à aucune lettre.

On remarquera que 641^4 = (641^2)^2 donc si l'on connait 641^2 (mod 899) cad 38 pour trouver 641^4 (mod 899) il suffit de faire 38^2 (mod 899) cad 545 (de même avec 641^8 avec 641^4).

 

6) Cracker RSA

En théorie, cracker RSA n'a rien de diffcile il suffit juste de décomposer la clé publique n en produit de facteurs premiers (par exemple 33 = 11 * 3) mais lorsque n dépasse 150 chiffres ce n'est plus du tout facile bien au contraire, aucun supercalculateur actuel n'est capable de factoriser n en un temps raisonnable.

Une autre technique, celle fois ci dites de brute force consiste à essayer tous les chiffres de 1 jusqu'à n et de le mettre à la puissance e (clé publique) le tout modulo n jusqu'à trouver le même chiffre que le crypté, dans quelle cas on aurai trouvé le chiffre décrypté.

Voici un petit code permettant de faire la dernière technique citée.

/* mod = clé n et puiss = clé e */
unsigned long int brutus_attack(unsigned long int nb, unsigned long int puiss, unsigned long int mod)
{

unsigned long int res = 1, nvar, nvar2;
unsigned long int resultat[100000];
int i, j, k,l; // compteurs
int nnb, compt, var, caze;
int tab[100000], tab2[100000];
int puissa = puiss;

printf("\nTENTATIVE DE BRUTE FORCING EN COURS...\n");
for (i=0; i<100000; i++) // on remplit le tableau avec des 5
___tab[i]=5;

for (i=0, compt = -1; puiss > 0; i++, compt++ ) // on convertit la puissance en binaire
{
__if (puiss % 2 > 0)
__nnb = 1;
__if (puiss % 2 == 0)
__nnb = 0;
__tab[i]=nnb;
__puiss = puiss / 2;
}

for (i=0, j=0; tab[i] != 5; i++) // on convertit le binaire en puissance de 2 : par
{________________________________// exemple (11101)b = 16 + 8+ 4 + 1
__if (tab[i] == 1)
____{
______var = puissance(2,i);
______tab2[j] = var;
______j++;
____}
}

l = j; // on sauvegarde la valeur de j cad le nombre d'element ds le tableau tab2[]

/* On essaye toutes les valeurs possibles de M^e (mod n) avec M < n jusqu'à ce que le resultat egal à C*/
for (nb=1; nb < mod; nb++)
_{
___resultat[0]=0;
___resultat[1]=nb; /* On met dans le tableau resultat[] les restes du nombre nb par les */
___nvar2 = nb; /* puissances successives jusqu'à la puissance egal au plus grand nombre */
___nvar = nb; /* du tableau tab2[] par le modulo mod */
___for (i=2; i<=tab2[j-1]+1; i++)
____{ ______________________/* Par exemple pour 29 = 16 + 8 + 4 +1 et pour nb =3 on et dans le tableau */
______nvar2 = nvar * nvar2; /* les restes de 3^1, 3^2 jusqu'à 3^16 par le modulo mod */
______nvar2 = nvar2%mod;
______resultat[i] = nvar2;
____}

___for (i=0, res=1; i<l; i++) /* Dans la case i du tableau resultat se trouve nb^i */
____{
___caze = tab2[i];
___res = res * resultat[caze];
___if (res > mod)
______res = res%mod;
_}
___if ( res == c)
______break;

____}
___return res;
}

 

7) Avantages et inconvénients

Ce système reste de nos jours le système cryptographique à clé publique le plus utilisé et le plus sûr. On estime qu'une clef RSA de 512Bits sera cassée au bout d'environ 107 millions d'années par une machine modeste (architecture x86, ~1Ghz), une clef de 1024Bits sera quant à elle 1.3x10^154 fois plus complexe à casser. Il permet également de valider l'authenticité des personnes (l'utilisation d'une clef de décryptage erronée entraînera fatalement un décryptage faux).

En revanche ses calculs consomment énormement de mémoire, il est considéré comme 1000 fois plus lent que son concurrent direct le DES. Cet inconvénient n'en est pas un sur un ordinateur récent mais il le devient quand il est question de ce type de cryptage pour une utilisation embarquée (de type carte bancaire ou téléphone portable [bien que quand je surf sur le wap avec mon téléphone portable les données soit cryptées en rsa])

De plus, le système RSA récupère également les avantages du principe de clefs publiques et privées. Appelé système à clef asymétrique, dans lequel seule la clef de déchiffrement doit être tenue secrète, la clef de chiffrement pouvant être rendue publique, à condition qu'il soit impossible virtuellement d'en déduire la clef secrète. Cela amène de nombreux avantages, parmi lesquels

8) Conclusion

En théorie, le cryptosystème RSA n'est pas inviolable, il "suffit juste" de factoriser n en produit de facteurs premiers. Cependant la puissance actuelle des supercalculateurs ne permet pas de réaliser ce travail à une échelle de temps raisonnable (voire humaine) à partir du moment où n dépasse 150 chiffres.. A partir de là, le RSA se révèle pour l'instant comme incassable.

Peut-on alors affirmer à partir de là que le RSA a un long futur devant lui ?

On pourra répondre par l'affirmative tant que la puissance de calcul disponible ne soit suffisante pour faire le travail de factorisation en un temps raisonnable. Ce sera aussi le cas tant que l'on ne trouvera pas un algorithme permettant de factoriser en un temps raisonnable. Dans ces cas là il faudra trouver une autre méthode.

Ainsi, malgré quelques inconvénients (mémoire utilisée, puissance nécessaire, ...), le RSA est un cryptosystème proche de la perfection.

9) Références
[] http://rsa.lissyx.dyndns.org/
[] http://www.commentcamarche.net/crypto/rsa.php3
[] http://www.security-labs.org/index.php3?page=6



Voici le code source de mon programme permettant de crypter, décrypter et de brute forcer un chiffre.



prototypes.h

typedef struct
_{
___unsigned long int p;
___unsigned long int q;
___unsigned long int n;
___unsigned long int phi;
___unsigned long int d;
___unsigned long int e;
___unsigned long int nb;
_}cle;

unsigned long int puissance(int a, int b);
unsigned long int cryptage(unsigned long int nb, unsigned long int puiss, unsigned long int mod);
unsigned long int decryptage(unsigned long int nb, unsigned long int puiss, unsigned long int mod);
unsigned long int brutus_attack(unsigned long int c, unsigned long int puiss, unsigned long mod);
cle cleCryptage(void);
cle cleDecryptage(void);
cle cleCassage(void);
void demande(void);


cryptage.h

unsigned long int cryptage(unsigned long int nb, unsigned long int puiss, unsigned long int mod)
{
unsigned long int res = 1, nvar, nvar2;
unsigned long int resultat[100000];
int i, j, k,l; // compteurs
int nnb, compt, var, caze;
int tab[100000], tab2[100000];
int puissa = puiss;

printf("\nCRYPTAGE EN COURS...\n");
for (i=0; i<100000; i++) // on remplit le tableau avec des 5
___tab[i]=5;

for (i=0, compt = -1; puiss > 0; i++, compt++ ) // on convertit la puissance en binaire
{
___if (puiss % 2 > 0)
___nnb = 1;
___if (puiss % 2 == 0)
___nnb = 0;
___tab[i]=nnb;
___puiss = puiss / 2;
}

for (i=0, j=0; tab[i] != 5; i++) // on convertit le binaire en puissance de 2 : par
{________________________________// exemple (11101)b = 16 + 8+ 4 + 1
__if (tab[i] == 1)
____{
______var = puissance(2,i);
______tab2[j] = var;
______j++;
____}
}

l = j; // on sauvegarde la valeur de j cad le nombre d'element ds le tableau tab2[]

resultat[0]=0;
resultat[1]=nb; _______/* On met dans le tableau resultat[] les restes du nombre nb par les */
nvar2 = nb; ___________/* puissances successives jusqu'à la puissance egal au plus grand nombre */
nvar = nb;_____________/* du tableau tab2[] par le modulo mod */
for (i=2; i<=tab2[j-1]+1; i++)
_{ _________________________/* Par exemple pour 29 = 16 + 8 + 4 +1 et pour nb =3 on et dans le tableau */
___nvar2 = nvar * nvar2; ___/* les restes de 3^1, 3^2 jusqu'à 3^16 par le modulo mod */
___nvar2 = nvar2%mod;
___resultat[i] = nvar2;
_}

for (i=0, res=1; i<l; i++) /* Dans la case i du tableau resultat se trouve nb^i */
{_______________/* Donc à partir du tableau tab2[i] qui contient la décomposition de la puissance puiss*/
___caze=tab2[i]; ___/* res = res * resultat[caze]; /* en puissance de 2 ( 29 = 16 + 8 + 4 + 1), on peut */
_____________________/* obtenir nb^puiss en multipliant */
___if (res > mod)____/* par exemple nb^16, on multiplie les cases
______res = res%mod; /* resultat[16]*resultat[8]*resultat[4]*resultat[1] */
}____________________/* pour obtenir enfin le chiifre crypté on fait le resultat precedent modulo mod */

return res;
}


decryptage.h

// Remarque : c'est exactement la même chose que pour cryptage()

unsigned long int decryptage(unsigned long int nb, unsigned long int puiss, unsigned long int mod)
{
______________________________________________
_unsigned long int res = 1, nvar, nvar2;
_unsigned long int resultat[100000];
_int i, j, k,l; // compteurs
_int nnb, compt, var, caze;
_int tab[100000], tab2[100000];
_int puissa = puiss;

_printf("\nDECRYPTAGE EN COURS...\n");
_for (i=0; i<100000; i++) // on remplit le tableau avec des 5
___tab[i]=5;

_for (i=0, compt = -1; puiss > 0; i++, compt++ ) // on convertit la puissance en binaire
_{
_____if (puiss % 2 > 0)
_____nnb = 1;
_____if (puiss % 2 == 0)
_____nnb = 0;
_____tab[i]=nnb;
_____puiss = puiss / 2;
_}

for (i=0, j=0; tab[i] != 5; i++) // on convertit le binaire en puissance de 2 : par
{________________________________// exemple (11101)b = 16 + 8+ 4 + 1
__if (tab[i] == 1)
____{
______var = puissance(2,i);
______tab2[j] = var;
______j++;
____}
}

l = j; // on sauvegarde la valeur de j cad le nombre d'element ds le tableau tab2[]

resultat[0]=0;
resultat[1]=nb; _______/* On met dans le tableau resultat[] les restes du nombre nb par les */
nvar2 = nb; ___________/* puissances successives jusqu'à la puissance egal au plus grand nombre */
nvar = nb;_____________/* du tableau tab2[] par le modulo mod */
for (i=2; i<=tab2[j-1]+1; i++)
_{ _________________________/* Par exemple pour 29 = 16 + 8 + 4 +1 et pour nb =3 on et dans le tableau */
___nvar2 = nvar * nvar2; ___/* les restes de 3^1, 3^2 jusqu'à 3^16 par le modulo mod */
___nvar2 = nvar2%mod;
___resultat[i] = nvar2;
_}

for (i=0, res=1; i<l; i++) /* Dans la case i du tableau resultat se trouve nb^i */
{_______________/* Donc à partir du tableau tab2[i] qui contient la décomposition de la puissance puiss*/
___caze=tab2[i]; ___/* res = res * resultat[caze]; /* en puissance de 2 ( 29 = 16 + 8 + 4 + 1), on peut */
_____________________/* obtenir nb^puiss en multipliant */
___if (res > mod)____/* par exemple nb^16, on multiplie les cases
______res = res%mod; /* resultat[16]*resultat[8]*resultat[4]*resultat[1] */
}____________________/* pour obtenir enfin le chiifre crypté on fait le resultat precedent modulo mod */

return res;
}


brutus_attack.h

unsigned long int brutus_attack(unsigned long int c, unsigned long int puiss, unsigned long int mod)
{
__________________________________________________/* mod = clé n et puiss = clé e */
unsigned long int res = 1, nvar, nvar2;
unsigned long int resultat[100000];
int i, j, k,l; // compteurs
int nnb, compt, var, caze;
int tab[100000], tab2[100000];
int puissa = puiss;

printf("\nTENTATIVE DE BRUTE FORCING EN COURS...\n");
for (i=0; i<100000; i++) // on remplit le tableau avec des 5
___tab[i]=5;

for (i=0, compt = -1; puiss > 0; i++, compt++ ) // on convertit la puissance en binaire
{
___if (puiss % 2 > 0)
___nnb = 1;
___if (puiss % 2 == 0)
___nnb = 0;
___tab[i]=nnb;
___puiss = puiss / 2;
}

for (i=0, j=0; tab[i] != 5; i++) // on convertit le binaire en puissance de 2 : par
{________________________________// exemple (11101)b = 16 + 8+ 4 + 1
___if (tab[i] == 1)
____{
______var = puissance(2,i);
______tab2[j] = var;
______j++;
____}
}

l = j; // on sauvegarde la valeur de j cad le nombre d'element ds le tableau tab2[]

/* On essaye toutes les valeurs possibles de M^e (mod n) avec M < n jusqu'à ce que le resultat egal à C*/
for (nb=1; nb < mod; nb++)
_{
___resultat[0]=0;
___resultat[1]=nb; /* On met dans le tableau resultat[] les restes du nombre nb par les */
___nvar2 = nb; /* puissances successives jusqu'à la puissance egal au plus grand nombre */
___nvar = nb; /* du tableau tab2[] par le modulo mod */
___for (i=2; i<=tab2[j-1]+1; i++)
____{ ______________________/* Par exemple pour 29 = 16 + 8 + 4 +1 et pour nb =3 on et dans le tableau */
______nvar2 = nvar * nvar2; /* les restes de 3^1, 3^2 jusqu'à 3^16 par le modulo mod */
______nvar2 = nvar2%mod;
______resultat[i] = nvar2;
____}

___for (i=0, res=1; i<l; i++) /* Dans la case i du tableau resultat se trouve nb^i */
___{
______caze = tab2[i];
______res = res * resultat[caze];
______if (res > mod)
_________res = res%mod;
___}
___

___if ( res == c)
______break;

}
___return res;
}


crypt-rsa-ge.c

#include <stdio.h>
#include "prototypes.h"
#include "cryptage.h"
#include "decryptage.h"
#include "brutus_attack.h"

void demande(void)
{
int choix;
unsigned long int res, nb;
cle c;
FILE *premier;

if ((premier = fopen("nb_premier_phi.txt","r")) != NULL)
_{ ____________________/* On supprime les eventuels fichier résultant d'une */
___fclose(premier); ___/* execution du programme */
___system("del nb_premier_phi.txt");
_}

system("cls");
/*------------------------------------------Menu---------------------------------------------*/
printf("---------------------------[Bienvenue dans CRYPT-RSA-GE]---------------------------\n\n");
printf("----[Que voulez vous faire ?");

printf("\n\n--------[1 Crypter un nombre\n");
printf("--------[2 Decrypter un nombre\n");
printf("--------[3 Tenter un cassage d'un chiffre crypte\n");
printf("--------[4 Quitter le programme\n");
printf("\nChoix : ");
scanf("%d",&choix);
printf("\n°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°");
/*-------------------------------------------------------------------------------------------*/

switch(choix)
_{
___case 1 : c = cleCryptage(); res = cryptage(c.nb, c.e, c.n); printf("Le nombre cypte est C = %lu",res); break;
___case 2 : c = cleDecryptage(); res = decryptage(c.nb, c.d, c.n); printf("Le nombre decypte est M = %lu",res); break;
___case 3 : c = cleCassage(); res = brutus_attack(c.nb, c.e, c.n); printf("Le nombre decypte est M = %lu",res); break;
___default: exit(0); /* si choix autre que 1, 2 ou 3 alors on sort du programme */
_}

getch();
demande();
}

unsigned long int puissance(int a, int b)
{
int i;
unsigned long int res = 1;

for (i=0; i<b; i++)
___res = res * a;

return res;
}

cle cleCryptage(void)
{
cle c;
unsigned long int i;
FILE *premier;

premier = fopen("nb_premier_phi.txt","a"); /* On crée un fichier pour stocker les nombres */
if (premier == NULL) /* premiers avec phi */
_{
___printf("\n\nErreur création du fichier nb_premier_phi.txt");
___exit(42);
_}

printf ("\n\nEntrez le nombre a crypter : ");
scanf("%lu",&c.nb);
printf("Entrez le nombre premier p : ");
scanf("%lu",&c.p);
printf("Entrez le nombre premier q : ");
scanf("%lu",&c.q);
printf("\nCALCUL DE LA CLE N EN COURS...");
c.n = c.p*c.q;
printf("\nLa cle n = %lu\n",c.n);
printf("\nCALCUL DE LA CLE PHI EN COURS...");
c.phi = (c.p-1)*(c.q-1);
printf("\nLa cle phi = %lu\n",c.phi);

for (i = 2; i< c.phi/2; i++) /* On incrit dans le fichier tous les nombres */
___if ( c.phi % i != 0) /* premiers avec phi jusqu'à phi / 2 */
______fprintf(premier,"%lu\n",i);
fclose(premier);

printf("\nUne liste des cles possibles d est disponible dans le fichier nb_premier_phi.txt");
printf("\nEntrez la cle d (premier avec phi) : ");
scanf("%lu",&c.d);
printf("\nCALCUL DE LA CLE E EN COURS...");

for (c.e=1; c.e < (c.phi*c.phi); c.e++) /* On recherche une chiffre tel que e*d-1 soit divisible par phi */
___if (((c.e*c.d) % c.phi) == 1)
______break;

printf("\ne = %lu\n",c.e);
return c;

}

cle cleDecryptage(void)
{
cle c;
printf ("\n\nEntrez le nombre a decrypter : ");
scanf("%lu",&c.nb);
printf("Entrez la cle prive d : ");
scanf("%lu",&c.d);
printf("Entrez la cle public n : ");
scanf("%lu",&c.n);
return c;
}

cle cleCassage(void)
{
cle c;
printf ("\n\nEntrez le nombre a decrypter : ");
scanf("%lu",&c.nb);
printf("Entrez la cle public e : ");
scanf("%lu",&c.e);
printf("Entrez la cle public n : ");
scanf("%lu",&c.n);
return c;
}

int main(void)
{
system("title CRYPT-RSA-GE by Skyrunner");
demande();
return 0;

}

 

HAUT DE PAGE

 

BY SKYRUNNER

Copyright © 2005 ARENHACK - DHS