TD: Cryptage RSA 1 Position du problème On propose de réaliser la méthode de cryptage due à Rivest, Shamir et Adleman (dite méthode RSA). Cet algorithme date de 1977, il repose sur le fait que, si l’on multiplie ensemble deux nombres premiers très grands (p et q), il est très difficile1 de redécomposer le résultat obtenu (n = p.q) en facteurs premiers (p et q). La méthode RSA, dite à clef publique, est la suivante2 : 1. à chaque lettre ` de l’alphabet, on affecte un nombre n` compris entre 1 et nmax . (Si on ne prend que les lettres majuscules non accentuées et le caractère blanc, on a nmax = 27). `X max 2. on transforme le texte à transmettre (formé de `max lettres) en un nombre: message = n` × n`max . `=1 3. un interlocuteur 1 choisit secrètement deux nombres premiers très grands p1 et q1 congrus3 à 2 modulo 3. Il publie leur produit (la clef publique): n1 = p1 .q1 . Il garde secrètement le résultat d’un autre calcul (la clef 1 −1)+1 (k1 est forcément un entier). privée): k1 = 2.(p1 −1).(q 3 La fonction codage de x consiste à calculer une certaine fonction fn1 (x); la fonction décodage de x consiste à calculer la fonction inverse: fn−1 (x). 1 ,k1 2 −1)+1 . 4. un interlocuteur 2 fait de même avec p2 , q2 , n2 = p2 .q2 et k2 = 2.(p2 −1).(q 3 5. lorsque 1 veut transmettre le message à 2, il envoie: xxxx = fn2 (fn−1 (message)). 1 ,k1 6. lorsque 2 veut décoder xxxx, il calcule fn1 (fk−1 (xxxx)) = message. ,n 2 2 7. le récepteur décompose le nombre message dans la base nmax et transforme chaque nombre de la décomposition en lettre de l’alphabet pour retrouver le texte. La fonction codage fni (yyyy) consiste à décomposer yyyy dans la base ni puis à élever chaque terme de la décomposition au cube modulo ni . La fonction décodage fn−1 (zzzz) consiste à élever zzzz à la puissance 3.ki modulo ni . Cette procédure i ,ki utilise le petit théorème de Fermat généralisé: - soit m et n deux nombres premiers entre eux (m < n); - soit Φ(n) la fonction d’Euler donnant le nombre des entiers inférieurs et premiers avec n. Ici Φ(n) = (p − 1) ∗ (q − 1). On a alors: mΦ(n) ≡ 1 [n] ⇒ m(p−1).(q−1) ≡ 1 [n] ⇒ ∀k ∈ N, mk.(p−1).(q−1) ≡ 1 [n] ⇒ ∀k ∈ N, mk.(p−1).(q−1)+1 ≡ m [n] Comme p ≡ q ≡ 2 [3], on a: 2.(p − 1).(q − 1) + 1 ≡ 0 [3] et donc ∃k ∈ N tel que 2.(p − 1).(q − 1) + 1 = 3.k 2 Code avec Mathematica RSA Transformation: lettres <-> chiffres In[1]:= Code[texte ]:=Module[{elements,ii,imax}, elements=ToCharacterCode[texte]; imax=Length[elements]; For[res=0;ii=1,ii<=imax,ii++,res=res+elements[[ii]]*65537^(imax-ii)]; Return[res]]; Decode[nombre ]:=( texte=IntegerDigits[nombre,65537]; FromCharacterCode[texte]); Code["message"] Decode[Code["message"]] 1 Historiquement, p était un nombre de 64 chiffres et q un nombre de 65 chiffres. En 1994, le nombre n = p.q de 129 chiffres (RSA129) a pu être décomposé en p et q grâce à 1600 ordinateurs travaillant en parallèle pendant deux jours. 2 Les 2 premières étapes sont communes à toutes les méthodes de codage. 3 i.e. dont le reste de la division euclidienne par 3 est 2. 1 ISEN-Brest. Kany. TD: Cryptage RSA Out[3]= 8636782494647089498447787918053 Out[4]= message Clefs de 1 et 2 In[5]:= p1=Prime[30001] q1=Prime[30002] Mod[p1,3] Mod[q1,3] Out[5]= 350381 Out[6]= 350411 Out[7]= 2 Out[8]= 2 In[9]:= n1=p1*q1 k1=(2*(p1-1)*(q1-1)+1)/3 Out[9]= 122777356591 Out[10]= 81851103867 In[11]:= p2=Prime[30003] q2=Prime[30004] Mod[p2,3] Mod[q2,3] Out[11]= 350423 Out[12]= 350429 Out[13]= 2 Out[14]= 2 In[15]:= n2=p2*q2 k2=(2*(p2-1)*(q2-1)+1)/3 Out[15]= 122798381467 Out[16]= 81865120411 Codage In[17]:= ListeEnNombre[liste ,cle ]:=Module[{NbreTermes,ii,res}, NbreTermes=Length[liste]; For[res=0;ii=1,ii<=NbreTermes,ii++,res+=liste[[ii]]*cle^(ii-1)]; Return[res];]; Codage[liste ]:=Module[{nombre,cle}, nombre=liste[[1]];cle=liste[[2]];Return[Mod[nombre^3,cle]]]; In[19]:= (*Pour insersion de la clef entre chaque element de la liste*) Sow[expr ,object ]:=Insert[expr,object,List/@Range[2,Length[expr]+1]] RSA[nombre ,ClePublique ]:=Module[{ListeCodee,ListeDecodee,res}, 2 ISEN-Brest. Kany. TD: Cryptage RSA ListeDecodee=IntegerDigits[nombre,ClePublique]; ListeDecodee=Partition[Sow[ListeDecodee,ClePublique],2]; ListeCodee=Map[Codage,ListeDecodee]; Return[ListeEnNombre[ListeCodee,ClePublique]];]; MessageCode=RSA[Code["Message"],n1] Out[22]= 683863267296776668652927526278887 Decodage In[23]:= expomodulo[xx ,nn ,mm ]:=Module[{liste,ii,imax,res,puissance}, puissance=Mod[xx,mm]; liste=IntegerDigits[nn,2]; imax=Length[liste]; If[liste[[imax]]==1,res=xx,res=1]; For[ii=imax-1,ii>=1,ii--, puissance=Mod[puissance^2,mm]; If[liste[[ii]]==1,res=Mod[res*puissance,mm];];]; Return[res];] Decodage[liste ]:=Module[{nombre,ClePrivee,ClePublique}, nombre=liste[[1]];ClePrivee=liste[[2]][[1]];ClePublique=liste[[2]][[2]]; Return[expomodulo[nombre,ClePrivee,ClePublique]]]; ASR[nombre ,ClePrivee ,ClePublique ]:=Module[{ListeCodee,ListeDecodee,res}, ListeCodee=IntegerDigits[nombre,ClePublique]; ListeCodee=Partition[Sow[ListeCodee,{ClePrivee,ClePublique}],2]; ListeDecodee=Map[Decodage,ListeCodee]; Return[ListeEnNombre[ListeDecodee,ClePublique]];]; ASR[MessageCode,k1,n1] Out[26]= 6101249171578647385225561440965 1 envoie un message 2 In[27]:= Code["Bonjour, ca va ?"] ASR[Code["Bonjour, ca va ?"],k1,n1] MessageEnvoye=RSA[ASR[Code["Bonjour, ca va ?"],k1,n1],n2] Out[27]= 116641592712282001463149217660028982581610315105012093918877189000477672773 Out[28]= 159071632319608592115103484642891131233449708039690962730108017175548532624434 Out[29]= 351613662903029463412718813642207235213337678647855147225107131666234478270218 2 décode le message de 1 In[30]:= ASR[MessageEnvoye,k2,n2] MessageRecu=RSA[ASR[MessageEnvoye,k2,n2],n1] Decode[MessageRecu] Out[30]= 159071632319608592115103484642891131233449708039690962730108017175548532624434 Out[31]= 116641592712282001463149217660028982581610315105012093918877189000477672773 Out[32]= Bonjour, ca va ? 3 connait n1 et n2 mais pas k2, il ne peut pas décoder. Exemple: In[33]:= p3=Prime[30008] q3=Prime[30009] Mod[p3,3] 3 ISEN-Brest. Kany. TD: Cryptage RSA Mod[q3,3] k3=(2*(p3-1)*(q3-1)+1)/3 Out[33]= 350447 Out[34]= 350453 Out[35]= 2 Out[36]= 2 Out[37]= 81876334395 In[38]:= Decode[RSA[ASR[MessageEnvoye,k3,n2],n1]] Out[38]= ΛûDû? ⊂ û!µû > û?GûpûOX ûê?ûë ← ûQ?ûl&ûË∃û ∪ +û]9û??û? 3 Code avec Python Téléchargez la bibliothèque PyPrime à l’adresse: https://pypi.python.org/pypi/pyprimes/ et installez le package pyprimes-0.1.1a.tar.gz à l’aide de WinPython Control Panel suivi de Install packages). # -*- coding: utf-8 -*import random import pyprimes import math 4 (Add packages