Laborator 5 Cuprins 1. Alegerea cheilor... 1 2. Criptarea RSA... 2 3. Problema rucsacului... 3 4. Merkle - Hellman. Generarea cheilor... 5 5. Merkle - Hellman. Criptarea... 6 6. Logaritmul discret... 7 1. Alegerea cheilor Explicaţii Utilizatorul A alege două numere prime mari şi. Calculează şi indicatorul lui Euler pentru, dat de: (. Alege astfel încât (,. Calculează astfel încât Cheia publică este dată de perechea Cheia privată este dată de perechea Soluție: # include "utile.h" citeste_alfabet(); long long p,q,n,phi,e,d; cout<<"programul va genereaza o cheie pentru criptare;"; srand((int)time(null)); p=da_prim(...);//generam numere astfel incat produsul a doua asemenea numere sa nu depaseasca domeniul pentru variabile q=da_prim(...); n=p*q; phi=(p-1)*(q-1); e=3+rand()%(phi-3); d=invers(e,phi); while(d<0)//pentru ca e sa fie inversabil e++; d=invers(e,phi); cout<<"\ncheia publica--> Ke=("<<n<<","<<e<<")"; cout<<"\ncheia secreta--> Kd=("<<n<<","<<d<<")"<<endl;
2. Criptarea RSA #include "utile.h" struct RSA_key long long n; long long e; long long d; int l, j; ; void RSA(ifstream in, ofstream out, RSA_key key) char* c = new char[key.l >= key.j? key.l : key.j]; long long i=0, m = 0; while (in >> noskipws >> c[i]) m = m * N + da_cod(c[i]); if (i == key.j - 1) m = a_la_b_mod_c(m, key.e, key.n); i = key.l - 1; while (m>0) c[i] = da_caracter(m%n); m = m / N; i--; while (i >= 0)c[i--] = da_caracter(0); for (i = 0; i<key.l; i++)out << c[i]; i = 0; i++; out.close(); in.close(); RSA_key generare_chei() long long p, q, n, phi, e, d; RSA_key key; srand((int)time(null)); p = da_prim(3,100000,3);//generam numere astfel incat produsul a doua asemenea numere sa nu depaseasca domeniul pentru variabile q = da_prim(3,100000,p); key.n = p * q; phi = (p - 1)*(q - 1); key.e = 3 + rand() % (phi - 3); key.d = invers(key.e, phi); while (key.d < 0) //pentru ca e sa fie inversabil key.e++; key.d = invers(key.e, phi); return key;
citeste_alfabet(ifstream("alfabet.txt")); RSA_key key; long long i, m; cout << "Dati cheia publica:" << endl; cout << " n="; cin >> key.n; cout << " e="; cin >> key.e; for (i = 0, m = 1; m < key.n; i++) m *= N; cout << "\ndati lungimea blocului de caractere la citire(<=" << i << ")"; cin >> key.j; cout << "\ndati lungimea blocului de caractere la scriere(>=" << i << ")"; cin >> key.l; RSA(ifstream("sursa.txt"), ofstream("destinatie.txt"), key); Exemplu (din curs): alfabet.txt ABCDEFGHIJKLMNOPQRSTUVWXYZ Vectorul de caractere devine: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z (lungimea blocurilor la citire), sursa.txt YESTERDAY Primul bloc YES: (lungimea blocurilor la scriere). Criptarea este BFIC. Al doilea bloc TER: Criptarea este BJHH. Al treilea bloc este DAY: Criptarea este BIEM. destinatie.txt BFICBJHHBIEM 3. Problema rucsacului Sub titlul de problema rucsacului sunt reunite mai multe probleme similare, care au la bază aceeași idee. Avem o valoare dată și o mulțime de obiecte cu diferite valori. Cerințele pot fi de la cele mai simple la cele mai complicate. Varianta clasică (problema rucsacului 0-1) este cea unde fiecare obiect are și o anumită masă și rucsacul are și el o anumită capacitate. Problema este de a maximiza valoarea pusă în rucsac fără a depăși capacitatea rucsacului. O implementare găsiți aici: http://karaffeltut.com/newkaraffeltutcom/knapsack/knapsack.html și o variantă de cod aici: http://www.infoarena.ro/problema/rucsac - programare dinamică. Formalizând în limbaj matematic: Avem de calculat cu restricția, unde.
dacă, punem în rucsac obiectul dacă, nu punem în rucsac obiectul Această variantă se poate complica, variantă care apare în jocuri precum Skyrim, unde, astfel că jucătorul trebuie să calculeze câte obiecte (poțiuni etc.) trebuie să ia. O altă variantă este cea în care vrem să plătim o sumă de bani având oricâte monede de valorile (problema rucsacului nemărginită) - backtracking. Formalizând în limbaj matematic, avem de calculat astfel încât. Această problemă este NP - completă. Varianta pe care o vom studia astăzi este o particularizare a celei de mai sus, cea în care. Vom particulariza și mai mult cerința, introducând conceptul de șir supercrescător. În acest caz, problema poate fi rezolvată în O(n). Mulțimea de valori formează un șir supercrescător dacă:. 1. Determinați care dintre șirurile de mai jos sunt supercrescătoare; ; 2. Rezolvați problema rucsacului pentru Rezolvare pentru șiruri supercrescătoare Cod Programul rezolvă problema rucsacului pentru cazul când sirul dat este supercrescător #include<iostream> using namespace std; int V, v[100],eps[100]=0,i,w,n; cout<<"dati V:"; cin>>v;//introducem valoarea V cout<<"\ndati n:"; cin>>n;//introducem numarul de obiecte for(i=0;i<n;i++) //Introducem valorile v_i cout<<"v["<<i+1<<"]="; cin>>v[i];//introducem sirul int s=v[0],supercrescator=1; for(i=1;i<n;i++) if(v[i]<=s) supercrescator=0;//verificam daca sirul este supercrescator. break;
s+=v[i]; if(!supercrescator) cout<<"sirul nu este supercrescator"; w=v; for(i=n-1;i>=0;i--) if(w>=v[i]) //Daca sirul este supercrescator, aplicam greedy. eps[i]=1; w=w-v[i]; if(w==0)break; if(w!=0) cout<<"\nproblema nu are solutii"<<endl; cout<<"\nsolutia problemei este:"<<endl; for(i=0;i<n;i++) cout<<eps[i]; \endlstlisting 4. Merkle - Hellman. Generarea cheilor Cod # include "utile.h" int* da_supercrescator(int n) int *v=new int[n],pas_max=50; srand(time(null)); int S=0;//pentru ca primul termen sa nu fie zero niciodata for(int i=0;i<n;i++) v[i]=s+1+rand()%pas_max; S+=v[i]; return v; citeste_alfabet(); int i,n,m,a,m,s,*v;
M=int(log(N+1.0)/log(2.0))+1;//numarul minim de biti pe care trebuie sa-i citim cout<<"\ndati numarul de elemente n (>="<<M<<"):"; cout<<"\nn="; cin>>n; if(n<m) cout<<"\nnumarul dat este prea mic!"; exit(0); v=da_supercrescator(n); cout<<"\na fost generat sirul supercrescator:"<<endl; for(i=s=0;i<n-1;i++) cout<<v[i]<<","; cout<<v[n-1]; m=s+1+rand(); cout<<"\na fost generat numarul m="<<m<<endl; a=1+(rand())%(m-1); while(cmmdc(a,m)!=1)//pentru ca a sa fie inversabil in Zm a++; cout<<"\na fost generat numarul a="<<a<<" relativ prim cu "<< m<<endl; system("pause"); 5. Merkle - Hellman. Criptarea #include<fstream> #include<iostream> using namespace std; ifstream fin("sursa.txt"); ofstream fout("destinatie.txt"); int w[8] = 295, 592, 301, 14, 28, 353, 120, 236; char a; int b, s=0; while (fin >> noskipws >> a) b = (int)a; for (int i = 0; i < 8; i++) s += ((b & (1 << i)) >> i)*w[8-1 - i]; fout << s << " "; s = 0;
6. Logaritmul discret Trial multiplication Logaritmul discret este o problemă similară cu factorizarea numerelor. Prima idee pe care o avem este de a calcula toate puterile lui până obținem. Exemplu.. Logaritmul discret al lui în baza 2 este 6. Remarcă. În acest laborator ne vom ocupa de grupuri finite de tipul, dar multe din principiile enunțate pot fi făcute pentru grupuri finite arbitrare. unsigned long long log1_d(unsigned long long g, unsigned long long y, unsigned long long p) unsigned long long i, j, *v; v = new unsigned long long[p + 1]; y = y%p; v[0] = 1; v[1] = g; if (y == g) return 1; for (i = 2; i < p; i++) v[i] = (v[i - 1] * v[1]) % p; for (i = 0; i<p; i++) if (y == v[i]) return i; return 0; Baby step, giant step unsigned long long log_d(unsigned long long b, unsigned long long y, unsigned long long p) unsigned long long i, j, *v, a; a = (unsigned long long)sqrt((double)p); v = new unsigned long long[a + 1]; v[0] = 1; v[1] = a_la_b_mod_c(b, a, p); for (i = 2; i <= a; i++) v[i] = (v[i - 1] * v[1]) % p; y = modulo(y, p); for (j = 0; j<a; j++) for (i = 0; i <= a; i++) if (y == v[i]) return modulo(i*a - j, p - 1); y = (y*b) % p; return 0; Bibliografie Exemplul numeric de la algoritmul Merkle - Hellman este preluat de pe Wikipedia. Codurile și elementele teoretice sunt inspirate din materialele prof. dr. Răzvan Lițcanu și lect. dr. Marius Apetrii.