RSA – code Mupad

Le code est divisé en morceaux représentant chacun une étape

Les textes en rouge sont du code MuPad et doivent être inscrits dans des paragraphes de calcul (Insert Calaulation, raccourci : cmd-I pour Mac ou CTRL-I sur PC). Les textes en noir sont à inscire dans des paragraphes textes entre deux

Après chaque morceau de code, insérer un paragraphe calcul pour tester les fonctions définues sur un exemple

Il vaut toujours mieux fractionner le code en petits morceaux qu'on puisse tester séparément!!

Ce code Mupad vous permet

PARTIE 1 : texte <=> nombres
Convertir un texte en une suite de nombres et vice-versa

Notes sur les fonctions internes de Mupad utilisées

Code ASCII décalé

texte2nombres := texte -> map(numlib::toAscii(texte),x->x-32):

nombres2texte := nombres -> numlib::fromAscii(map(nombres,x->x+32)):
base := 95: // taille du jeu de caractères : 32 à 126
lettre_remplissage := 63:
// 0 à 31 exclus - 127 exclu
// Intervalle de 32 à 126 du code ASCII
// décalé vers l'intervalle 0 à 94

Code ASCII en trois tranches

alpha1 := nombres2texte([i $ i=0..31]):
alpha2 := nombres2texte([i $ i=32..63]):
alpha3 := nombres2texte([i $ i=64..94]):
print(NoNL, eval(alpha.i)."\n") $ i = 1..3:

Impression de la table de correpondance

for i from 0 to base-1 do
// enlever le // à la ligne ci-dessous pour créer la table de corrspondance
// print(NoNL, "" . i . "\t" . (i+32) . "\t" . nombres2texte([i]) . "\n"):
end_for:

Vérification des conversions dans les deux sens

txt00 := "L'Assemblée parlementaire du Conseil de l'Europe a adopté ce mardi à Strasbourg, en France, le rapport du conseiller aux Etats tessinois Dick Marty. Dans ce document, il dénonce un trafic d'organes prélevés sur les cadavres de prisonniers de l'Armée de libération du Kosovo (UCK) en Albanie dans les années 1990.":
txt0 := "L'Assemblee parlementaire du Conseil de l'Europe a adopte ce mardi a Strasbourg, en France, le rapport du conseiller aux Etats tessinois Dick Marty. Dans ce document, il denonce un trafic d'organes preleves sur les cadavres de prisonniers de l'Armee de liberation du Kosovo (UCK) en Albanie dans les annees 1990.":
nbrs := texte2nombres(txt0):
txt1 := nombres2texte(nbrs):
print(Typeset, x) $ x in [txt0, nbrs, txt1];

Regroupement d'une liste par blocs

nombres2blocs := proc(liste, k)
// regrouper la liste par blocs de k nombres
local n, nblocs, m;
begin
 n := nops(liste): // nombre de termes de la liste donnée
 m := -n mod k: // nombres de termes à ajouter pour obtenir un multiple de k
 nblocs := (n+m)/k: // nombre de blocs
 liste1 := liste . [lettre_remplissage $ i = 1..m]: // ajout de m termes
 [[liste1[l*k + i] $ i = 1..k] $ l = 0..nblocs-1]: // regroupement
end_proc:

Test

nbrsblocs := nombres2blocs(nbrs,3);
nbrsblocs27 := nombres2blocs(nbrs,27);

Conversion d'une liste de nombres regroupée par blocs en une liste de grands nombres

// convertir un bloc de nombres en un grand nombre
bloc2nombre := proc(liste)
local x;
begin
 x := 0:
 for y in liste do
  x := x*base + y:
 end_for:
 x:
end_proc:
// convertir une suite de bloces en une suite de grands nombres
blocs2nombres := (liste)->[bloc2nombre(l) $ l in liste]:

Test

nbrsgrands := blocs2nombres(nbrsblocs);
nbrsgrands27 := blocs2nombres(nbrsblocs27);

Conversion d'une liste de grands nombres une liste simple de petits nombres

grandnombre2bloc := proc(nombre, k)
local x, reste, quotient;
begin
 x := [0 $ i = 1..k]:
 quotient := nombre:
 reste := 0:
 for i from 1 to k do
  j := k - i + 1:
  reste := quotient mod base:
  quotient := floor(quotient/base):
  x[j] := reste:
 end_for:
 x:
end_proc:
// ===========
grandsnombres2nombres := (nombres, taille)->
_concat(grandnombre2bloc(nombre, taille) $ nombre in nombres);

Tests

// on doit retrouver la liste initiale de nombres
nbrs1 := grandsnombres2nombres(nbrsgrands, 3);
nbrs271 := grandsnombres2nombres(nbrsgrands27, 27);

Regroupement en une procédure de l'obtention de la liste de grands nombres

texte2grandsnombres := proc(texte, k)
local nombres, nombres_par_blocs, grandsnombres;
begin
 nombres := texte2nombres(texte):
 nombres_par_blocs := nombres2blocs(nombres,k):
 grandsnombres := blocs2nombres(nombres_par_blocs,base):
end_proc:

Test

grdsnbrs := texte2grandsnombres(txt0,3);
grdsnbrs27 := texte2grandsnombres(txt0,27);

Regroupement en une procédure de la conversion de grands nombres en texte

grandsnombres2texte := proc(grandsnombres, k)
local nombres;
begin
 nombres := grandsnombres2nombres(grandsnombres, k):
 nombres2texte(nombres):
end_proc:

Test

grandsnombres2texte(grdsnbrs,3);
grandsnombres2texte(grdsnbrs27,27);


PARTIE 2 - création des clés

// adapter ces deux nombres puis choisissez e ci-dessous
// pour déterminer vos clés – publique et secrète
// deux grands nombres quelconques d'environ 25 à 30 chiffres
pp := 100000001231231321544566456:
qq := 23456789547687543546876545654:
nom := "Tartempion2": // mettez votre nom !!
//
// =========================================================
p := nextprime(pp):
// calcule le premier nombre premier après p
q := nextprime(qq):
n := p*q:
phi_n := (p-1)*(q-1):
// affiche les paramètres d'encryptage
hold(p)=p, hold(q)=q;
hold(n)=n;
hold(phi_n) = phi_n;
hold(phi_n) = factor(p-1)*factor(q-1);
// =========================================================
// on doit choisir un nombre premier avec phi_n = Φ(n)
// comme code d'encryptage e – la procédure ci-dessous
// cette procédure calcule le plus petit nombre premier possible
// =========================================================
e := 5:
e2 := 2:
while gcd(e2, phi_n) > 1 do
 e2 := nextprime(e2+1);
end_while:
e := e2;
// =========================================================
// calculer le code de décryptage d = inverse de e mod phi_n
// =========================================================
d := powermod(e, -1, phi_n):
// inverse de e modulo phi_n
print(Typeset, hold(e)=e,hold(d)=d);
// Afficher mon code privé
print(NoNL, "\n=============================="):
print(NoNL, "\nClé privée : \n n = " . n . " ;\n");
print(NoNL, " d = " . d . " ; \nAuteur : " . nom);
// Annoncer son code public (texte à envoyer)
print(NoNL, "\n=============================="):
print(NoNL, "\nVoici ma clé publique : \n n = " . n . " ;\n");
print(NoNL, " e = " . e . " ; \nAuteur : " . nom);
print(NoNL, "\n==============================");


PARTIE 3 - Regroupement des procédures de cryptage / décryptage

Fonction de cryptage/décryptage d'une liste de grands nombres

cryptage := (liste,n,e)->[powermod(x,e,n) $ x in liste];

Procédure pour envoyer un texte crypté

envoicrypte := proc(texte,n,e,destinataire)
local taille_blocs, grandsnombres, grandsnombrescryptes, textecrypte;
begin
 taille_blocs := floor(ln(n)/ln(base)): // calculer la taille des blocs
 grandsnombres := texte2grandsnombres(texte, taille_blocs): // convertir en grands nombres
 grandsnombrescryptes := cryptage(grandsnombres,n,e): // encrypter
 textecrypte := grandsnombres2texte(grandsnombrescryptes, taille_blocs+1): // reconvertir en texte
 print(NoNL, "==============================================\n"):
 print(textecrypte):
 print(NoNL, "==============================================\n"):
 textecrypte:
end_proc;

Test

messagecrypte := envoicrypte(txt0, n, e):

Procédure pour décrypter un message crypté

decrypter := proc(texte, n, d)
local taille_blocs1, grandsnombres, grandsnombresdecryptes, textedecrypte;
begin
 taille_blocs1 := floor(ln(n)/ln(base))+1: // calculer la taille des blocs
 grandsnombres := texte2grandsnombres(texte, taille_blocs1): // convertir en grands nombres
 grandsnombresdecryptes := cryptage(grandsnombres, n, d): // décrypter
 textedecrypte := grandsnombres2texte(grandsnombresdecryptes, taille_blocs1-1); // reconstituer le texte en clair
end_proc:

Test

decrypter(messagecrypte, n, d);


Partie 4 - test ce la procédure globale

Test avec un copier coller

messagecrypte := "\"y]tT*[YL+k(cw)/p3C&H>kGITU_ (wpNgvyf4?'ViDERYz( _XNgn] 6=/s!W_2Yf@T$<CKg`Lo-q6\\y*m iiH(jQ`&*j{[BsX's/lA0(ikCZ: 4,[/)Ln^n5>*k.DJyv?c4qjQ:HP'd!\\dc:m;E1zTuD?_uhAQR#w{Z~`#yaTvUV6QN&fTSYawV0M=={r.hZ#&|GIy./hDNZ(uOD Sd`te}5 G`Rk$-6/qX`63`_ZF)=gjqn$8BYI[|%y\"gc3,{#KDd%KN:_5>B=6=lo[v:; !$3uN.D7q`?Z*`x8scYUc*qC:.VQ)9-]}.*DT;c{LOGiJ`SCm(%t\\R j";
decrypter(messagecrypte, n, d);

Un autre test

message := "J'essaie d'ecrire n'importe quoi pour voir si ca code et decode correctement !!";
messagecrypte := envoicrypte(message,n,e,"test");
messagecryptecolle := " P(cz3f8$AGvh-T_tUvG~)K(&{Yh l4i.gLY\\=JwHN[8nUF)b>l`XA=3#Q~&3d~>Nqi}Z89A&1U{9\
fV(3=:8";
decrypter(messagecryptecolle, n, d);

4 - un autre test (avec les mêmes clés)

p := 100000001231231321544566477;
q := 23456789547687543546876545669;
n := 2345678983649488348679762549080463834066343577896938113;
e := 3;
d := 1563785989099658899119841683682449523431712472983883979;
message := "Le RSA est genial, mais il serait impossible de faire les calculs sans ordinateurs !!!";
messagecrypte := envoicrypte(message,n,e,"Tartempion"):
messagedecrypte := decrypter(messagecrypte,n,d):
print(Typeset, hold(messagedecrypte) = messagedecrypte):