Transmiterea Securizata a Mesajelor

Transmiterea securizata a mesajelor

Cuprins

Introducere

1. Noțiuni introductive despre transmiterea de mesaje prin SMS

1.1. Statistici

1.2. Noțiuni tehnice

1.3. Utilizări

1.4. Legislație

2. Vulnerabilități ale serviciului SMS

2.1. Snooping

2.2. Spoofing

2.3. Interception

3. Metode de criptare a mesajelor SMS

3.1. Criptare simetrică

3.2. Criptare asimetrică

3.3. Funcțiile hash

4. Aplicație pentru securizarea comunicațiilor SMS – CryptSMS

Modus operandi

• Etapa 1 – Design

• Etapa 2 – Implementare

• Etapa 3 – Testarea

Concluzii

Bibliografie

Anexe

Anexa 1 – Clasa CryptoHelper

Anexa 2 – Clasa MySQLiteHelper

Anexa 3 – Clasa GeneralHelper

Introducere

Milioane de utilizatori ai telefoanelor mobile din întreaga lume comunică zi de zi prin mesaje SMS. Aceștia scriu orice în mesajele SMS, atât informații irelevante cât și informații importante și clasificate, însă puțini cunosc tehnologia prin care este posibilă această comunicare. În primul capitol al prezentei lucrări este realizată o prezentare de ansamblu a comunicării prin mesaje.

Majoritatea utilizatorilor de telefonie mobilă nu au cunoștință de dimensiunea infrastructurii din spatele comunicațiilor mobile și din această cauză nu cunosc vulnerabilitățile și riscurile din spatele acestei metode de comunicare. Majoritatea utilizatorilor nu cunosc, spre exemplu, cât de ușoară este interceptarea mesajelor SMS. În primul rând, furnizorii de servicii de telefonie mobilă stochează mesajele SMS într-o bază de date proprie, astfel angajații furnizorului sau terțe părți care au acces în rețeaua furnizorului pot accesa mesajele transmise de clienți. Pe de altă parte, mesajele transmise și cele recepționate sunt stocate local, pe dispozitivul folosit, ceea ce înseamnă că orice persoană interesată care poate obține acces fizic la acesta poate citi mesajele. În prezenta lucrare am făcut o trecere în revistă asupra principalelor vulnerabilități ale serviciului SMS: SMS snooping, SMS spoofing și SMS interception (Capitolul 2).

Din păcate, majoritatea telefoanelor mobile și a serviciilor de SMS oferite de furnizor nu asigură confidențialitatea acestor mesaje. Singura modalitate de a oferi confidențialitate conținutului mesajelor expediate este extinderea funcționalităților dispozitivului utilizat adăugându-i un serviciu de criptare/decriptare a mesajelor SMS.

Criptarea este o tehnică pentru transformarea informațiilor digitale în așa fel încât să nu poată fi citite de persoane neautorizate. Funcția de bază a criptării este translatarea textului normal în text cifrat. În capitolul 3 al prezentei lucrări am descris câteva metode de criptare a mesajelor SMS și am prezentat avantaje și dezavantaje pentru fiecare metodă.

Având în vedere aceste aspecte, am dezvoltat o aplicație care permite protejarea mesajelor SMS prin criptarea conținutului acestora înainte de expediere. Aplicația propusă în prezenta lucrare (detaliată în capitolul 4) folosește criptare asimetrică end-to-end pentru a asigura informațiilor transmise prin SMS confidențialitate, integritate, autenticitate și non-repudiere.

Noțiuni introductive despre transmiterea de mesaje prin SMS

Statistici

În prezent, cele mai comune metode de comunicare sunt folosirea mesajelor folosind serviciul SMS pus la dispoziție de operatorii de telefonie mobilă, serviciul e-mail disponibil prin rețeaua Internet, rețele de socializare ș.a.

Comunicarea prin mesaje instant este relativ nouă având în vedere faptul că primul mesaj a fost trimis pe 3 decembrie 1992 de un inginer britanic Neil Papworth de pe un calculator personal către un dispozitiv mobil din rețeaua GSM a companiei Vodafone din Marea Britanie. În scurt timp, a devenit o modalitate tot mai populară de a comunica și, după mai bine de 20 de ani, orice utilizator de telefonie mobilă folosește diferite metode (SMS, mIRC, e-mail, WhatsApp, Facebook etc).

Potrivit unui studiu peste jumătate dintre posesorii de telefoane mobile folosesc servicii de mesagerie pentru comunicare. În schema următoare este reprezentat grafic răspunsul persoanelor interogate la întrebarea „Pe telefonul mobil, de obicei …”.

Figura 1 – Reprezentarea grafică a activităților a modului de întrebuințare al telefoanelor

Același studiu a relevat modul de întrebuințare al telefoanelor mobile la nivelul unor state precum SUA, Spania, Marea Britanie, Rusia ș.a și se poate observa în tabelul următor tendința cetățenilor în a folosi mesajele text pentru comunicare aproape în același procent cu funcția principală a telefoanelor: inițierea de apeluri voce. În urma studiului s-a ajuns la concluzia că peste 85% din populația lumii deține un telefon mobil, iar dintre aceștia peste 75% folosesc aceste dispozitive pentru a comunica prin intermediul mesajelor text.

Tabelul 1 – Modul de întrebuințare al telefoanelor mobile în diferite țări

Conform altor studii s-a ajuns la următoarele statistici:

peste 95% din mesajele text primite sunt citite în cinci minute de la recepționare;

86% dintre clienții furnizorilor de telefonie mobilă primesc sau expediază un mesaj text pe săptămână;

2.12 trilioane de mesaje sunt transmise anual;

98% dintre mesajele text primite sunt citite în comparație cu 22% dintre e-mailuri, 29% din tweet-uri și 12% din postările Facebook;

timpul mediu de livrare al unui mesaj SMS este sub 7 secunde.

Noțiuni tehnice

Short Message Service (SMS) este un serviciu pentru transmiterea de mesaje scurte prin rețeaua de telefonie mobilă. Mesajul de la emițător este stocat într-o unitate centrală (central short message center), ulterior fiind redirecționat către dispozitivul mobil al destinatarului. Această practică asigură livrarea mesajelor chiar și în cazul în care dispozitivul destinatarului nu este disponibil.

O caracteristică interesantă a serviciului SMS este posibilitatea confirmării livrării. Acest lucru înseamnă că emițătorul, dacă dorește, poate primi un mesaj de notificare despre starea mesajului expediat.

O altă caracteristică este faptul că mesajele SMS pot fi trimise/primite simultan cu comunicațiile de date, voce sau fax pentru că folosesc canale de semnalizare și nu canale dedicate.

În plus, serviciul SMS permite roaming național, internațional și expedierea de mesaje către orice utilizator de telefonie mobilă din lume. Mai nou, având în vedere faptul că rețelele de calculatoare pot fi interconectate cu sistemele de comunicații GSM, CDMA și TDMA ce permit comunicarea prin mesaje, SMS-ul este un serviciu de date mobile universal.

Una din limitările serviciului este dimensiunea mesajului, pentru că orice mesaj transmis prin SMS nu poate fi mai mare de 160 de caractere alfanumerice sau binare (Non-Text Short messages). Pentru a reduce efectul acestei limitări, a fost dezvoltată o extensie denumită SMS-uri concatenate (SMS lungi). Un SMS concatenat poate conține mai mult de 160 de caractere de caractere pentru că dispozitivul emițătorului va împărți textul lung în mai multe părți de maxim 160 de caractere, iar la destinație dispozitivul destinatarului va reconstrui textul inițiat. Totuși nu toate dispozitivele de pe piață suportă această extensie.

În figura de mai jos este ilustrată o modalitate de organizare a elementelor dintr-o rețea GSM ce suportă serviciul SMS.

Figura 2 – Organizarea componentelor dintr-o rețea de telefonie mobilă

Elementele reprezentate sunt următoare:

SME-urile (Short Message Entity) primesc și trimit mesajele și pot fi amplasate în rețelele fixe sau stațiile mobile.

SMC-ul (Short Message Center) este o entitate care are ca sarcină principală stocarea/direcționarea mesajelor de la/către stațiile mobile. Pentru a putea expedia mesaje este necesară setarea adresei către SMC pe dispozitiv. În cele mai multe cazuri, adresa SMC-ului este un număr de telefon în format internațional.

SMS GMSC (Gateway Mobile Switching Centre) este un gateway care, de asemenea, primește și transmite mesaje. Gateway-ul este un punct de contact al rețelelor de telefonie mobilă cu alte rețele. La primirea unui mesaj de la SMC, GMSC folosește protocolul de rețea SS7 pentru a interoga baza de date HLR pentru a afla MSC-ul către care va trimite informațiile având în vedere poziția curentă a stației mobile unde trebuie să ajungă informațiile.

HLR (Home Location Register) este baza de date principală dintr-o rețea de telefonie mobilă. Aici sunt stocate informații despre profilele clienților și informații despre rutare pentru un anumit client, de exemplu zona (acoperită de MSC) unde dispozitivul este situat. În acest fel, GMSC este capabil să transmită mesajul MSC-ului corect.

MSC-ul (Mobile Switching Center) este componenta principală a core-ului rețelelor GSM care are ca sarcină comutarea conexiunilor între stațiile mobile sau între stațiile mobile și stațiile fixe.

VLR-ul (Visitor Location Register) corespunzător fiecărui MSC conține informații despre dispozitivele mobile, informații precum codul de identificare al dispozitivului și celula (sau grupul de celule) în raza căreia dispozitivul este situat la un moment de timp. Folosind informațiile de la VLR, MSC-ul este capabil să comute comunicațiile către BSS (Base Station System) care transmit mesajele către dispozitivele finale.

BSS-ul este alcătuit din tranceivere care transmit și recepționează informații prin eter către și de la stațiile mobile. Aceste informații sunt transmise prin canalele de semnalizare, astfel încât dispozitivele pot primi mesaje chiar dacă sunt în cursul unui apel de voce.

MS – dispozitive mobile finale (telefoanele).

Utilizări

În prezent există multe aplicații bazate pe SMS-uri și multe încă în dezvoltare. În continuare voi enumera câteva exemple de întrebuințare a acestui serviciu:

Mesaje text de la o persoană către alta. Această utilizare este cea mai practicată. În acest scenariu, un utilizator scrie textul și numărul de telefon al destinatarului folosind tastatura după care, prin apăsarea unei taste („Trimite” sau ”OK”) expediază mesajul. Atunci când destinatarul primește mesajul îl poate citi imediat sau la un moment de timp viitor. Pentru acest tip de comunicații au fost dezvoltate de-a lungul timpului aplicații complexe de chat în care mesajele pot fi expediate către mai mult destinatari, iar răspunsurile pot fi vizionate în aceeași fereastră.

Mesaje pentru informare. Multe companii folosesc serviciul SMS pentru a informa clienții sau potențialii clienți despre noile ofere, facturile pe care le au de plătit, situația contului bancar etc.

Mesaje pentru alertare și înștiințare. Datorită faptului că dispozitivele mobile sunt în majoritatea timpului la purtător, serviciul SMS este recomandat a fi folosit pentru alertare și înștiințare a unor evenimente. În plus, folosind SMS-ul, alertele sunt trimise doar atunci când există date, spre deosebire de modelele de interogare în care utilizatorul accesează o resursă pentru a vedea dacă există modificări. La această metodă de utilizare pot fi încadrate aplicațiile care înștiințează o persoană despre primirea unui e-mail, fax, apel vocal, modificarea situației contului bancar sau modificarea parametrilor unui sistem de monitorizare.

Mesaje pentru autentificare într-un sistem. În ultima perioadă sunt folosite tot mai des sistemele de autentificare prin două căi. Pentru acest lucru, după ce un utilizator trimite credențialele de conectare unui sistem, acesta din urmă trimite utilizatorului un text scurt, reprezentând o parolă volatilă valabilă o perioadă scurtă de timp (cca. 1 min) pentru a se conecta. Astfel, autenticitatea utilizatorului este asigurată pentru că este mică probabilitatea ca altcineva să poată cunoaște aceste informații pentru a se conecta.

Mesaje pentru vot. Compania CaktusGroup a dezvoltat în anul 2014 prima soluție pentru sistemul de votare din Libia.

Legislație

În România, legile în vigoare care reglementează utilizarea serviciului SMS de către comercianți pentru a expedia mesaje comerciale sau exploatarea serviciului SMS de către agențiile guvernamentale pentru a colecta probe despre persoane de interes sunt următoarele:

Legea nr. 365/2002 a comerțului electronic (art. 1 pct. 8, Art. 6);

Legea nr. 506/2004 privind prelucrarea datelor cu caracter personal și protecția vieții private în sectorul comunicațiilor electronice (art. 12);

Normele metodologice pentru legea comerțului electronic (art. 7-9);

Ordonanța nr. 130/2000 republicată privind protecția consumatorilor la încheierea și executarea contractelor la distanță (art. 15);

Articolul 91 din Codul Procedură Penală: Condițiile și cazurile de interceptare și înregistrare a convorbirilor sau comunicărilor efectuate prin telefon sau prin orice mijloc electronic de comunicare.

Cadrul legislativ protejează majoritatea utilizatorilor mijloacelor electronice de comunicare din România de abuzuri din partea companiilor care vor să-și promoveze produsele și din partea agențiilor guvernamentale care ar putea efectua interceptări fără mandat judecătoresc. Totuși, la nivel internațional comunicațiile electronice ale unor persoane de interes ar putea fi urmărite de serviciile de informații din diferite țări care nu au reglementată activitatea de interceptare a comunicațiilor.

Vulnerabilități ale serviciului SMS

Snooping

O dată cu apariția telefoanelor mobile inteligente care rulează sisteme de operare complexe au apărut și dezvoltatori de aplicații malware care urmăresc exploatarea acestor dispozitive. O tehnică utilizată pentru spionarea unei persoane este snooping.

Această tehnică presupune instalarea pe dispozitivul persoanei de interes a unei aplicații care va redirecționa toate mesajele către o terță parte (un număr de telefon configurat la instalarea aplicației).

Trebuie menționat faptul că nu toate sistemele de operare care rulează pe dispozitive mobile permit instalarea acestui tip de aplicații. La momentul elaborării lucrării printre sistemele de operare vulnerabile sunt: Blackberry, Symbian, Windows Mobile și Android iar printre cele care nu prezintă această vulnerabilitate este sistemul de operare al dispozitivelor Apple.

Datorită faptului că aplicația propusă în capitolul asigură informațiilor transmise confidențialitate, această vulnerabilitate este eliminată.

Spoofing

SMS spoofing este o tehnologie relativ nouă ce folosește serviciul SMS, disponibil pe majoritatea dispozitivelor mobile, pentru a modifica numărul de telefon al emițătorului cu un text alfanumeric. Spoofing este utilizat atât în mod legitim (setarea numelui companiei din partea căreia sunt expediate mesajele) cât și în mod nelegitim (impersonalizarea altei persoane sau companii).

Această tehnică a devenit posibilă după ce operatorii de telefonie mobilă au integrat rețelele de comunicații cu/în rețeaua Internet. Din acel moment oricine poate trimite mesaje SMS din Internet folosind diferite site-uri WEB care oferă acest serviciu sau aplicații special dezvoltate pentru acest lucru (ex: suita de aplicații SET de pe platforma KALI Linux).

Folosind această tehnică se pot lansa atacuri de tip spam sau phishing prin mesaje SMS urmărindu-se obținerea de foloase materiale necuvenite. În cazul atacurilor de tip spam obținerea fondurilor se realizează prin convingerea victimei să apeleze un număr cu suprataxă furnizat în mesaj, iar în cazul mesajelor de tip phishing obținerea fondurilor se realizează prin vânzarea informațiilor culese către terțe părți.

În cazul în care un individ este victimă a acestui tip atac trebuie să contacteze atât operatorul de telefonie mobilă cât și organele de poliție, iar operatorul trebuie să găsească, să blocheze și să ofere poliției detalii tehnice cu privere la atac. Această operațiune necesită însă mult timp și efort. În plus, programul de spamming poate folosi un număr de telefon al unui contact din agendă ceea ce îngreunează și mai mult identificarea atacului.

Aplicația propusă în capitolul asigură mesajelor recepționate autenticitate, astfel acest tip de atac nu mai este posibil.

Interception

În zilele noastre rețelele de telefonie mobilă sunt cea mai dinamică componentă a infrastructurii de comunicații și instrumentul cheie folosit pentru a efectua activitățile zilnice cum ar fi apeluri voce sau transmiterea de mesaje text.

În multe cazuri, se consideră că breșele de securitate sunt exploatate doar de agenții de informații, grupări de crimă organizată sau grupări de hackeri specializați din cauza costurilor ridicate. Această percepție este de înțeles deoarece majoritatea utilizatorilor nu au suficiente cunoștințe tehnice pentru a înțelege în detaliu modul de funcționare al rețelei de comunicații mobile și pornesc de la premiza că aceasta este un sistem format doar din tehnologii de ultimă generație precum dispozitivele pe care le dețin. Cu toate acestea, în realitate, o rețea de comunicații este un sistem complex construit din subsisteme cu niveluri tehnologice diferite. Nivelul de securitate al întregii rețele este dat însă de veriga cea mai slabă.

În particular, procesul plasării unui apel voce în rețelele de comunicații mobile moderne este încă bazat pe tehnologia SS7 care datează din anul 1970. La acea vreme, securitatea comunicațiilor presupunea protecția fizică a echipamentelor și a canalelor de comunicație, ceea ce făcea imposibil de obținut accesul la o rețea SS7 printr-un echipament de la distanță. În secolul XXI, a fost dezvoltat un set de protocoale de transmitere al semnalelor denumit SIGTRAN. Totuși, chiar și cu aceste specificații noi, vulnerabilitățile de securitate ale protocolului SS7 au rămas. Ca rezultat, un intrus poate trimite, intercepta sau altera mesaje SS7 executând diferite atacuri împotriva rețelelor de telefonie mobilă și a clienților.

Potrivit unui studiu [5] efectuat de cercetătorii Sergey Puzankov și Dmitry Kurbatov în anul 2014, vulnerabilitățile rețelelor de telefonie mobilă permit unui intrus, fără prea multe cunoștințe tehnice, să efectueze atacuri periculoase care pot conduce la pierderi financiare pentru abonați, scurgerea de informații clasificate sau întreruperea serviciilor de comunicații.

Figura 5 – Traseul mesajelor în situația unei interceptări

Pe perioada studiului cercetătorilor menționați mai sus a fost posibilă dezvăluirea locației unui abonat, întreruperea serviciilor furnizate către un abonat, interceptarea mesajelor SMS, redirecționarea și înregistrarea apelurilor voce și transferul de fonduri (în urma preluării conversației cu banca).

În România, toți operatorii majori de telecomunicații (Vodafone, Orange, RDS, Romtelecom, UPC) înregistrați la momentul elaborării lucrării folosesc protocolul SS7.

O altă metodă de interceptare este interpunerea între utilizator și celula GSM cu un echipament pe care și-l permite aproape orice agenție de detectivi sau divizie județeană de poliție. Însă se aplică doar pentru standardul GSM, care folosește un algoritm simplu de criptare. În cazul 3G sau CDMA, decodarea mesajului este aproape imposibilă.

Criptarea folosită de operatorii de telefonie mobilă pe canalul de comunicație nu mai protejează utilizatorul atunci când acesta este ascultat din centrală, operațiune care se face – de regulă – cu mandat de interceptare. Tot de regulă, beneficiarii sunt în acest caz agențiile guvernamentale. Această metoda de interceptare poate fi evitată cu ajutorul unor soluții proprii de criptare.

Se poate observa în urma celor menționate că operatorii de telefonie nu pun accent pe confidențialitatea mesajelor transmise între abonați. Pentru acest lucru, abonații care trimit informații importante prin intermediul serviciului SMS au responsabilitatea să securizeze conținutul mesajelor.

Metode de criptare a mesajelor SMS

Criptografia este definită de către prof. Adrian Atanasiu după cum urmează:

Criptografia este studiul metodelor matematice legate de securitatea informației, capabile să asigure confidențialitatea, autentificarea și non-repudierea mesajelor, precum și integritatea datelor vehiculate.

Aceeași sursă descrie obiectivele urmărite prin criptografie după cum urmează:

Confidențialitate (privacy): proprietatea de a păstra secretul informației, pentru ca aceasta să fie folosită numai de persoanele autorizate.

Integritatea datelor: proprietatea de a evita orice modificare (inserare, ștergere, substituție) neautorizată a informației.

Autentificare: proprietatea de a identifica o entitate conform anumitor standarde. Este compusă din

Autentificarea unei entități;

Autentificarea sursei informației;

Non – repudierea: proprietatea care previne negarea unor evenimente anterioare

Un sistem criptografic este compus din:

M – text clar

C – text cifrat

două funcții inverse E() și D() corespunzătoare criptării respectiv decriptării

un algoritm care produce cheile Ke (cheie de criptare) și Kd (cheie de decriptare) astfel încât: și .

Domeniul modern al criptografiei poate fi împărțit în câteva subdomenii de studiu abordate în subcapitolele 3.1, 3.2 și 3.3.

Criptare simetrică

Criptarea simetrică reprezintă modalitatea prin care un text este criptat cu o cheie și decriptat la destinație cu aceeași cheie.

Algoritmii criptografici folosiți în sistemele simetrice de criptare se împart în cifruri bloc (block ciphers) și cifruri flux sau cifruri șir (stream ciphers). Cifrurile flux pot cripta un singur bit de text clar la un moment dat, pe când cifrurile bloc criptează mai mulți biți (64, 128, 256 sau alt număr de biți) la un moment dat.

Schema de criptare este reprezentată în imaginea de mai jos.

Figura 6 – Schema de criptare folosind un algoritm de criptare simetric

Cei mai cunoscuți algoritmi criptografici simetrici sunt:

DES ( Data Encryption Standard) și 3DES – cifruri bloc;

IDEA (International Data Encryption Algorithm) – cifru bloc;

TWOFISH – cifru bloc;

AES (Advanced Encryption Standard) – cifru bloc;

RC4 – cifru șir.

Avantajele sistemelor simetrice de criptare sunt următoarele:

viteză mare de criptare a datelor chiar dacă volumul de date este mare;

siguranță ridicată;

Unul dintre cele mai folosite sisteme de criptare simetrică este AES folosit de Guvernul SUA. Atunci când e folosit cu lungimea maximă a cheii (256 biți), necesită aproximativ un miliar de ani unui supercalculator tactat la 10 petaflopi să găsească cheia prin atac de tip brute-force.

nu necesită resurse multe;

nu folosesc operații aritmetice, ci doar operații la nivel de șiruri de biți

Dezavantajele sistemelor simetrice de criptare sunt următoarele:

impunerea schimbului de chei private înainte de începerea transmisiei de date;

în caz de compromitere al cheii, toată comunicația este periclitată;

nu asigură repudierea mesajelor.

Dacă facem referire la securizarea comunicațiilor prin intermediul SMS nu se justifică folosirea criptării simetrice pentru că este dificil de realizat schimbul de chei pentru fiecare mesaj expediat, mai ales că destinatarul nu trebuie să fie constrâns să citească mesajul la primire. În plus, pentru șiruri de caractere de lungime scurtă (cazul SMS) avantajele criptării simetrice nu își fac simțit efectul.

Criptare asimetrică

Criptarea bazată pe chei publice este caracterizată de faptul că în procesele de criptare și decriptare sunt folosite chei diferite; una publică și una privată. Cheia publică este pusă la dispoziția oricărei persoane care dorește să trimită un mesaj criptat. Cheia privată este utilizată pentru decriptarea mesajului, iar nevoia de a face schimb de chei secrete este eliminată. Această caracteristică a dat algoritmilor cu cheie publică și numele de algoritmi asimetrici.

În cazul utilizării unui algoritm asimetric în comunicarea dintre un emițător și un receptor, fiecare dintre aceștia va deține câte o pereche de chei – publică și privată. Emițătorul poate cripta mesajul cu cheia publică a receptorului, astfel încât doar acesta să poată decripta mesajul cu cheia sa privată. 

Cheile algoritmilor asimetrici sunt obținute pe baza unei formule matematice din algebra numerelor mari, pentru numere prime între ele, iar din valoarea unei chei nu poate fi dedusă valoarea cheii asociate.

Figura 7 – Schema de criptare folosind un algoritm de criptare asimetric

Securitatea sistemelor de criptare cu cheie publică este bazată pe probleme NP complete.

Exemple de algoritmi criptografici asimetrici:

RSA: bazat pe dificultatea descompunerii în factori primi a numerelor mari (de sute de cifre);

El Gamal: bazat pe dificultatea calculului logaritmului discret într-un corp finit;

Merkle – Hellman: bazat pe problema {0, 1} a rucsacului;

Sistemul McEliece: bazat pe teoria algebrică a codurilor, decodificarea unui cod liniar fiind o problema NP – completă;

Curbe eliptice: sisteme de criptare care își desfășoară calculele pe mulțimea punctelor unei curbe eliptice (în locul unui inel finit Zn).

Avantaje ale sistemelor de criptare cu cheie publică

sistemul este ideal pentru transmiterea informației prin canale nesigure;

sistemele cu cheie publică sunt simplu de definit și elegante matematic;

doar cheia de decriptare trebuie ținuta secretă.;

în funcție de modul de utilizare, o pereche de chei (publică, privată) poate fi păstrată o perioadă mai lungă de timp;

asigură repudierea mesajelor;

sunt folosite în multiple aplicații: semnături electronice, algoritmi de autentificare, componente de comerț electronic etc.

Dezavantaje ale sistemelor de criptare cu cheie publică

sunt semnificativ mai lente decât sistemele simetrice;

sunt necesare chei de lungimi mult mai mari;

teoretic nu se poate garanta securitatea absolută a nici unei scheme de criptare cu cheie publică, însă, practic, timpul necesar spargerii codului este foarte mare;

implementarea trebuie realizată cu foarte mare grijă.

Având în vedere aceste aspecte, folosirea sistemelor de criptare bazate pe chei publice sunt o soluție viabilă pentru securizarea comunicațiilor prin SMS. Cheia de decriptare și cheile publice ale corespondenților pot fi stocate pe dispozitivul utilizatorului. Pentru o siguranță sporită cheia privată poate fi criptată folosind un algoritm simetric cu o cheie derivată dintr-o parolă cunoscută doar de utilizator pentru a asigura protecția cheii în caz de accesare neautorizată a dispozitivului.

Funcțiile hash

Funcțiile hash criptografice (adesea numite message digest) sunt o clasă importantă de algoritmi criptografici care nu folosesc neapărat chei. Acestea primesc date de intrare (adesea un întreg mesaj) și produc un hash scurt, de lungime fixă, sub forma unei funcții neinversabile.

Figura 8 – Schema de funcționare a funcțiilor hash

Proprietățile funcțiilor hash sunt următoarele:

intrarea poate avea orice dimensiune însă ieșirea are lungime fixă;

coliziunile (două texte clare diferite care produc același hash) sunt extrem de dificil de găsit;

neinversabile (dacă se cunoaște hash-ul este greu de identificat mesajul în clar);

deterministe (pentru o valoare de intrare va genera de fiecare dată același hash).

Funcțiile hash sunt folosite în domeniul securității informațiilor în cadrul semnăturilor digitate, coduri pentru autentificarea mesajelor (MAC), sume de control, verificarea integrității unor date etc.

Exemple de funcții hash:

MD5 (Message Digest Algorithm): produce o valoare hash de 128 biți (16 octeți), de obicei, reprezentați într-un șir de 32 de caractere hexazecimale;

SHA1 (Secure Hash Algorithm): produce o valoare hash de 160 de biți (20 octeți), de obicei reprezentați într-un șir de 40 de caractere hexazecimale;

SHA2: versiunea nouă a SHA1 constă într-o familie de funcții hash de diferite dimensiuni diferite a rezultatului: 224, 256, 384 și 512 biți.

În cadrul aplicației propuse în prezenta lucrare funcțiile hash sunt folosite pentru a atașa o semnătură digitală mesajului expediat de către emițător și pentru a verifica integritatea mesajului recepționat de către destinatar înainte de a-l decripta.

Aplicație pentru securizarea comunicațiilor SMS – CryptSMS

Având în vedere faptul că, în general, furnizorii de telefonie mobilă nu asigură utilizatorilor confidențialitatea mesajelor SMS, rămâne în sarcina fiecărui utilizator să își ia măsuri în această privință.

Aplicația pentru securizarea comunicațiilor SMS, CryptSMS realizează criptarea și semnarea conținutului mesajelor SMS. Încă din faza de proiectare s-a avut în vedere îndeplinirea unor cerințe cu privire la asigurarea protecției cheilor de criptare, modalitatea de transmitere a datelor între utilizatori și alegerea sistemului de operare pe care va rula aplicația.

Având în vedere avantajele și dezavantajele generate de utilizarea criptării simetrice sau asimetrice, în aplicație a fost implementat un sistem criptografic bazat pe criptare cu chei publice deoarece utilizatorii nu sunt nevoiți să facă schimb de chei de fiecare dată când vor să comunice.

În cazul în care cheia privată este compromisă (prin folosirea dispozitivului de persoane neautorizate sau furtul acestuia) sistemul criptografic ales prezintă o vulnerabilitate majoră. Pentru a reduce efectul acestei vulnerabilități cheia privată este stocată într-un fișier criptat cu un cifru simetric pentru care cheia este generată derivând un șir de caractere (parolă) pe care doar utilizatorul ar trebui să îl cunoască.

Având în vedere dezbaterile publice din prezent legate de agențiile de informații care culeg date din serverele marilor companii, utilizatorii de dispozitive mobile care pun preț pe securitatea comunicațiilor sunt suspicioși în cazul folosirii aplicațiilor care stochează datele în clar pe serverele unor terți. Deși avantajele folosirii unui model client-server nu sunt de ignorat cea mai mare problemă este reprezentată de încredere. Din acest motiv în aplicație a fost implementat modelul de criptare end-to-end care nu presupune elemente de infrastructură ale unor terțe părți.

Utilizarea pe scară largă a sistemului de operare Android și faptul că este open-source au contribuit la luarea deciziei de a dezvolta aplicația pentru utilizatorii acestui sistem de operare.

Pentru a dezvolta o aplicație pentru dispozitivele ce rulează sistemul de operare Android este recomandat a se ține cont de următoarele aspecte:

Design. Înainte de a începe implementarea unei aplicații trebuie gândită interfața și modalitatea de interacțiune a utilizatorului cu aceasta. Designul trebuie să fie simplu și previzibil pentru ca aplicația să poată fi folosită un număr cât mai mare de utilizatori indiferent de cultura acestora sau nivelul de cunoștințe tehnice pe care le posedă.

Implementare. Pentru a pune în practică ideile de aplicații, platforma Android pune la dispoziție dezvoltatorilor un API prin care aceștia au acces la toate resursele dispozitivelor ce rulează Android: modul accelerometru, GPS, camera foto, interfața pentru legătura la Internet, interfață pentru acces la modulul telefon (apeluri voce, SMS-uri) etc.

Distribuire. După ce aplicația este finalizată, ultimul pas este distribuirea acesteia care poate fi realizată foarte ușor prin interfața Google Play sau prin orice altă metodă aleasă de dezvoltator.

Pentru atingerea obiectivelor propuse, aplicația CryptSMS a fost dezvoltată să funcționeze astfel:

Emitentului unui mesaj va cripta mesajul cu cheia publică a destinatarului și va semna rezultatul cu cheia sa privată (după ce este introdusă parola pentru decriptarea acesteia – informație pe care doar emițătorul o cunoaște). La primirea unui mesaj, destinatarul va verifica semnătura emițătorului cu cheia publică a acestuia și, dacă este în regulă, va decripta mesajul cu cheia sa privată (după ce este introdusă parola pentru decriptarea acesteia – informație pe care doar destinatarul o cunoaște). Funcționarea detaliată a aplicației este reprezentată în .

Modus operandi

Etapa 1 – Design

Pentru utilizarea facilă a aplicației în etapa de design au fost stabilite acțiunile pe care un utilizator le poate întreprinde pe parcursul utilizării.

În primul rând, utilizatorul va avea putea să genereze oricând o pereche de chei privată-publică și va putea să distribuie cheia publică.

În al doilea rând, utilizatorul va avea nevoie de o agendă în care să stocheze datele de contact (nume, număr de telefon și cheia publică) ale corespondenților. De asemenea, acesta va putea modifica oricând informațiile despre un contact existent.

Pentru funcționalitatea de bază a aplicației utilizatorul va folosi datele de mai sus într-un mod cât mai transparent pentru a cripta sau decripta mesaje.

Acțiunile prezentate sunt ilustrate în schema UML a cazurilor de utilizare de mai jos.

Având stabilite aceste acțiuni au fost proiectate interfețele pentru fiecare caz de utilizare. În imaginile de mai jos sunt reprezentate ferestrele pe care utilizatorul le are la dispoziție pentru a interacționa cu funcționalitățile aplicației.

Etapa 2 – Implementare

Pentru implementarea aplicațiilor create de utilizatori, dezvoltatorii Android furnizează un SDK (din engleză: Software Development Kit) care include un set complet de instrumente de dezvoltare. Acesta include un program de depanare, biblioteci, un emulator de dispozitiv și documentație. SDK-ul poate fi rulat pe platforme x86 sau x64 ce rulează sistemele de operare Linux, Windows, MAC OS. Totodată stația pe care se dezvoltă aplicația trebuie să aibă Java Development Kit (JDK), Apache Ant și Python 2.2 sau o versiune ulterioară. Mediul de dezvoltare (IDE) recomandat este Eclipse utilizând plug-in-ul Android Development Tool (ADT).

Având stabilite elementele interfeței de start a fost folosit Eclipse pentru construirea fișierului XML corespunzător activității principale.

Următorul pas a fost construirea bazei de date în care va fi stocată lista de contacte (nume, număr de telefon, cheia RSA publică).

API-ul Android are suport pentru crearea și utilizarea bazelor de date SQLite. Fiecare bază de date este asociată aplicației care o creează. Clasa SQLiteDatabase conține metode pentru a interacționa cu baza de date. Pentru crearea unei baza de date, se apelează rutina SQLiteDatabase.create() și, de asemenea, clasa SQLiteOpenHelper.

Android pune la dispoziția dezvoltatorilor utilitarului SQLite3 disponibil în SDK, ce permite accesarea conținutului, executarea de comenzi SQL, precum și alte funcții utile privind bazele de date SQLite. Toate bazele de date, SQLite sunt stocate pe dispozitivul pe care rulează aplicația la calea /data/data/nume_pachet/dabatases.

Baza de date „agenda.db” este creată la instalarea aplicației prin instanțierea clasei MySQLiteHelper ce extinde clasa java SQLiteOpenHelper.

Pentru a facilita accesul la baza de date a fost implementată o clasă AgendaDataSource care are metode pentru listarea contactelor, adăugare contact nou, selectarea unui anumit contact, actualizarea informațiilor unui contact etc.

Accesul la lista de contacte se realizează prin clasa activitate EditeazaContacteActivity care extinde Activity. Astfel, printr-un obiect de tip SPINNER, utilizatorul poate alege orice contact din baza de date și îi poate vizualiza informațiile stocate. Prin intermediul acestei activități se pot edita informațiile unui contact (nume, număr de telefon sau cheia publică). Interfața activității este proiectată după modelul stabilit în faza de design. În această interfață există un buton pentru deschiderea activității de adăugare a unui contact nou (AddContactActivity) conform .

Următoarea activitate implementată a fost MyContactActivity după modelul . Pentru a genera perechea de chei RSA, dar și pentru alte funcții ce fac apel la criptografie a fost implementată o clasă ajutătoare CryptoHelper ce conține metode statice pentru a fi ușor de folosit.

La apăsarea butonului „Generare pereche nouă de chei” metoda public static void genereaza_pereche_chei(Context c, int nr_biti, String password, String privateKeyFilename, String publicKeyFilename) va genera perechea de chei RSA și le va scrie pe fiecare în câte un fișier în memoria internă a dispozitivului pe care rulează aplicația. Parametrii funcției sunt următorii:

int nr_biti: numărul de biți al cheilor RSA;

String password: parola cu care va fi criptată cheia privată;

String privateKeyFilename: numele fișierului în care va fi salvată cheia privată criptată;

String publicKeyFilename: numele fișierului în care va fi salvată cheia publică.

Observație! După ce este generată, cheia privată este criptată folosind funcția private static byte[] passwordEncrypt(char[] password, byte[] plaintext), iar rezultatul este scris în fișier. Criptarea cheii private este realizată cu cifrul simetric Twofish cu o cheie de 256 de biți derivată dintr-un șir de caractere furnizat de utilizator. Parola (șirul de caractere furnizat de utilizator) este concatenată cu un șir de caractere aleatoriu („salt”) iar rezultatul este trecut printr-o funcție de hash (SHA256) și este salvat în fișierul „parola.txt”. Cheia publică este scrisă în clar în fișier în format BASE64.

Având generate cele două chei, în interfața activității MyContactActivity este afișată cheia publică a utilizatorului în format BASE64.

Utilizatorul poate expedia cheia publică proprie direct din aplicație prin SMS unui corespondent pe care îl are în lista de contacte a telefonului sau o poate distribui pe alte canale. Pentru cazul în care este folosit serviciul SMS se face apel la un Content Provider pentru a accesa lista de contacte de pe dispozitivul folosit.

Observație! Pentru a folosi date din altă aplicație, trebuie specificat acest lucru în fișierul XML AndroidManifest.xml, astfel, la instalarea aplicației, utilizatorul va fi înștiințat că aplicația necesită acces la lista de contacte de pe dispozitiv.

<uses-permission android:name="android.permission.READ_CONTACTS"/>

După această acțiune, având cunoscut numărul de telefon al destinatarului care va primi cheia publică, utilizatorul o poate expedia folosind butonul „Trimite cheia publică”. Șirul de caractere codat BASE64 va fi trimis folosind API-ul SmsManager.

Observație! Pentru a putea folosi API-ul SmsManager este nevoie de specificarea acestui lucru în fișierul AndroidManifest.xml:

<uses-permission android:name="android.permission.SEND_SMS" />

Având în vedere faptul că șirului de caractere corespunzător cheii depășește 160 de caractere (lungimea unui mesaj SMS), șirul de caractere este împărțit în mai multe segmente. La destinație, acesta va fi refăcut de sistemul de operare și va apărea în aplicația implicită de mesaje a dispozitivului destinatarului ca un singur mesaj.

La final, au fost implementate funcțiile pentru criptarea unui mesaj folosind cheia publică a destinatarului ales și semnarea rezultatului folosind cheia privată a utilizatorului respectiv, verificarea autenticității unui mesaj primit folosind cheia publică a emitentului și decriptarea mesajului folosind cheia privată a utilizatorului.

Observație! De fiecare dată când este folosită cheia privată, utilizatorul va trebui să introducă parola pentru a decripta conținutul fișierului unde aceasta este stocată. Hash-ul parolei introduse concatenate cu șirul „salt” este comparat pentru confirmare cu hash-ul salvat anterior în fișier.

Inițial, utilizatorul (denumit emitent) va scrie în aplicație textul ce urmează a fi transmis. Acesta va fi criptat cu cheia publică a destinatarului pentru a asigura confidențialitatea mesajului. După care, transparent pentru emitent, aplicația va genera o semnătură a mesajului criptat pe care o va concatena la textul criptat. Astfel, se asigură autenticitatea, integritatea și non-repudierea mesajului transmis.

În continuare este prezentată diagrama UML de activitate corespunzătoare activității de expediere a unui mesaj criptat.

Având toate funcțiile create, se pot adăuga acțiuni butoanelor din activitatea principală. Astfel, pentru criptarea mesajului scris de utilizator în aplicație este nevoie de preluarea informațiilor din baza de date despre contactul selectat către care se va trimite mesajul și apelarea funcției de criptare.

Figura 25 – Instrucțiunile de cod corespunzătoare

criptării și semnării unui șir de caractere ce urmează a fi expediat

Metoda public static String cripteaza_cu_cheia_publica(Context c, String text, String password, String cheia) criptează șirul de caractere primit ca parametru folosind cheia publică a destinatarului și semnează rezultatul (folosind metoda private static byte[] sign (Context c, byte[] cipher, String password) ) cu cheia privată a emițătorului.

Parametrii funcției sunt:

Context c: interfața către informațiile globale ale aplicației (având în vedere faptul că este o metodă statică);

String text: textul ce urmează a fi criptat;

String password: parola cu care este criptată cheia privată a utilizatorului;

String cheia: cheia publică a destinatarului în format BASE64.

Metoda returnează un șir de caractere format din concatenarea textului cifrat cu semnătura, ambele în format BASE64.

După criptarea și semnarea mesajului șirul de caractere final este afișat pe ecran iar utilizatorul îl poate expediat prin SMS folosind butonul din aplicație sau îl poate trimite prin alte canale.

Similar, conform , la primirea unui mesaj criptat, textul poate fi decriptat folosind butonul de decriptare.

Metoda public static String decripteaza_cu_cheia_privata(Context c, String text, String password, String cheia_publica_emitent) verifică semnătura șirului de caractere primit ca parametru folosind cheia publică a emitentului (folosind metoda private static boolean verify_signature(String cheia_publica_emitent, String text) ) și, în cazul în care semnătura este corectă, decriptează șirul de caractere folosind cheia privată a destinatarului.

Parametrii funcției sunt:

Context c: interfața către informațiile globale ale aplicației (având în vedere faptul că este o metodă statică);

String text: șirul de caractere în format BASE64 ce urmează a fi decriptat;

String password: parola cu care este criptată cheia privată a utilizatorului;

String cheia: cheia publică a destinatarului în format BASE64.

Metoda returnează textul în clar.

Observație! Pentru a avea acces la cheia publică, pentru criptarea și decriptarea mesajelor, utilizatorul trebuie să introducă parola.

Etapa 3 – Testarea

Pentru testarea aplicației și verificarea corectitudinii implementării funțiilor au fost utilizate două dispozitive mobile:

HTC DESIRE 500 cu sistem de operare Android 4.1.2;

SAMSUNG SM355HN cu sistem de operare Android 4.4.

Expedierea unui mesaj

Dacă contactul persoanei cu care emițătorul dorește să comunice există în lista de contacte a aplicației, acesta selectează numele corespondentului (), scrie mesajul și apasă butonul „Criptează”. Instantaneu aplicația va solicita parola () pentru a putea accesa cheia privată a emițătorului cu care va fi semnat mesajul, după care va afișa în câmpul „Rezultat” mesajul criptat, concatenat cu semnătura acestuia. La apăsarea butonului „Trimite SMS” se va trimite criptograma prin SMS destinatarului ().

În cazul în care contactul destinatarului nu este salvat în lista de contacte a emițătorului, cei doi trebuie să facă schimbul de chei publice (, , ) și să adauge fiecare informațiile (nume, număr de telefon și cheia publică) în lista de contacte (, ). După care să urmeze pașii de la punctul a.

Recepționarea unui mesaj

Dacă receptorul unui mesaj criptat știe că are salvate informațiile despre emițător în aplicația CryptSMS atunci poate copia textul primit în căsuța de mesaje în aplicația CryptSMS și poate decripta mesajul selectând numele emițătorului și introducând parola.

Observație! În cazul în care emițătorul a schimbat perechea de chei de la ultimul schimb de chei cu emițătorul sau mesajul a fost modificat pe canalul de comunicație se va afișa mesajul: „Mesajul a fost alterat. Semnătura emitentului nu se verifică”.

Dacă nu are salvată cheia publică a emițătorului va trebui să facă schimbul de chei publice cu acesta (asemenea punctului 1b).

Pe parcursul testării dispozitivele utilizate nu au prezentat întârzieri în a executa sarcinile, mesajele transmise și recepționate nu au fost alterate pe canalul de comunicație și interfața intuitivă a permis folosirea imediată a aplicației și de către utilizatori neexperimentați.

Concluzii

Asigurarea protecției confidențialității comunicațiilor electronice este un domeniu foarte important și sensibil în prezent.

Aplicația CryptSMS prezentată asigură utilizatorilor serviciului de mesagerie confidențialitatea, autentificarea, integritatea și non-repudierea informațiilor transmise.

Bibliografie

William Stallings, Cryptography and Network Security: Principles and Practice (Ediția VI);

Prof. Adrian Atanasiu, Curs criptografie disponibil on-line la http://www.galaxyng.com/adrian_atanasiu/cursuri/cript/c1.pdf accesat la data 10.05.2015;

Prof. Aureliu Zgureanu, Note de curs – Criptarea și securitatea informației disponibil on-line la http://www.aticmd.md/wp-content/uploads/2011/05/ Zgureanu-A_Criptarea_Securitatea_Inform_Note-de-curs.pdf accesat la data 11.05.2015;

http://androidsourcecode.blogspot.ro accesat la data 01.06.2015;

http://stackoverflow.com;

http://www.openhandsetalliance.com accesat în perioada 01.04.2015 – 20.06.2015;

Nick Jones, Don't Use SMS for Confidential Communication disponibil on-line la https://www.gartner.com/doc/379178 accesat la data 01.05.2015;

Point-to-Point (PP) Short Message Service (SMS) support on mobile radio interface – http://www.etsi.org/deliver/etsi_ts/124000_124099/124011/ 12.00.00_60/ts_124011v120000p.pdf;

RFC2719 – Framework Architecture for Signaling Transport;

RFC3331 – Signaling System 7 (SS7) Message Transfer Part 2 (MTP2) – User Adaptation Layer;

RFC3332 – Signaling System 7 (SS7) Message Transfer Part 3 (MTP3) – User Adaptation Layer (M3UA);

RFC3788 – Security Considerations for Signaling Transport (SIGTRAN) Protocols.

Sergey Puzankov and Dmitry Kurbatov, How to Intercept a Conversation Held on the Other Side of the Planet disponibil on-line la http://www.slideshare.net/phdays/phd4-pres-callinterception119 accesat la data 02.05.2015;

Anexe

Anexa 1 – Clasa CryptoHelper

package com.example.cryptsms;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStreamWriter;

import java.io.UnsupportedEncodingException;

import java.security.InvalidAlgorithmParameterException;

import java.security.InvalidKeyException;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.SecureRandom;

import java.security.spec.InvalidKeySpecException;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import java.util.Arrays;

import javax.crypto.BadPaddingException;

import javax.crypto.Cipher;

import javax.crypto.IllegalBlockSizeException;

import javax.crypto.NoSuchPaddingException;

import javax.crypto.SecretKey;

import javax.crypto.SecretKeyFactory;

import javax.crypto.spec.PBEKeySpec;

import javax.crypto.spec.PBEParameterSpec;

import android.content.Context;

import android.util.Base64;

public class CryptoHelper {

static Context fileContext;

public static String cripteaza_cu_cheia_publica(Context c, String text, String password, String cheia){

byte[] key_bytes = Base64.decode(cheia, 0);

PublicKey publickey = null;

byte[] criptedText = null;

byte[] semnatura = null;

Cipher cipher;

try {

//criptez textul initial cu cheia publica a destinatarului ales

publickey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(key_bytes));

cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE, publickey);

criptedText = cipher.doFinal(text.getBytes());

//construiesc semnatura textului cifrat

semnatura = sign(c,criptedText, password);

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

} catch (NoSuchPaddingException e) {

e.printStackTrace();

} catch (IllegalBlockSizeException e) {

e.printStackTrace();

} catch (BadPaddingException e) {

e.printStackTrace();

} catch (InvalidKeyException e) {

e.printStackTrace();

}catch (InvalidKeySpecException e) {

e.printStackTrace();

} catch (InvalidAlgorithmParameterException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

//concatenez textul cifrat cu semnatura in format base64

return Base64.encodeToString(criptedText, Base64.DEFAULT) + "&" + Base64.encodeToString(semnatura, Base64.DEFAULT);

}

public static String decripteaza_cu_cheia_privata(Context c, String text, String password, String cheia_publica_emitent){

// password -> parola cu care a fost criptat fisierul cheii private

String continut = text.split("&")[0];

byte[] cyptedPrivateKeyBytes = GeneralHelper.readBytesFromFile(c, "private.key" );

byte[] decrypedPrivateKeyBytes = null;

byte[] decriptedText = null;

try {

if(verify_signature(cheia_publica_emitent, text)){

decrypedPrivateKeyBytes = passwordDecrypt(password.toCharArray(), cyptedPrivateKeyBytes);

PrivateKey key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decrypedPrivateKeyBytes));

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE, key);

decriptedText = cipher.doFinal(Base64.decode(continut, 0));

return new String(decriptedText, "UTF-8");

}

else return "Mesajul a fost alterat. Semnatura emitentului nu se verifica";

} catch (InvalidKeyException e) {

e.printStackTrace();

} catch (IllegalBlockSizeException e) {

e.printStackTrace();

} catch (BadPaddingException e) {

e.printStackTrace();

} catch (InvalidAlgorithmParameterException e) {

e.printStackTrace();

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

} catch (NoSuchPaddingException e) {

e.printStackTrace();

} catch (InvalidKeySpecException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

private static byte[] sign (Context c, byte[] cipher, String password ) throws NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException, InvalidKeySpecException, IOException{

// creez hash-ul mesajului

MessageDigest digest = MessageDigest.getInstance( "SHA-1" );

digest.update(cipher, 0, cipher.length);

byte[] data = digest.digest();

//preiau cheia privata

byte[] cyptedPrivateKeyBytes = GeneralHelper.readBytesFromFile(c, "private.key" );

byte[] decrypedPrivateKeyBytes = passwordDecrypt(password.toCharArray(), cyptedPrivateKeyBytes);

PrivateKey key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decrypedPrivateKeyBytes));

//criptez hashul mesajului

Cipher cipher1 = Cipher.getInstance("RSA");

cipher1.init(Cipher.ENCRYPT_MODE, key);

byte[] sigBytes = cipher1.doFinal(data);

return sigBytes;

}

private static boolean verify_signature(String cheia_publica_emitent, String text) throws InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{

// separ textul criptat de semnatura

String continut = text.split("&")[0];

String semnatura = text.split("&")[1];

//refac cheia publica a emitentului

byte[] key_bytes = Base64.decode(cheia_publica_emitent, 0);

PublicKey publickey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(key_bytes));

//decriptez semnatura

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE, publickey);

byte[] hash_decriptat = cipher.doFinal(Base64.decode(semnatura, 0));

//calculez hashul textului primit

MessageDigest digest = MessageDigest.getInstance( "SHA-1" );

digest.update(Base64.decode(continut, 0), 0, Base64.decode(continut, 0).length);

byte[] hash_calculat = digest.digest();

//verific daca hashul primit si cel calculat sunt identice

boolean isSigValid = Arrays.equals(hash_decriptat,hash_calculat);

return isSigValid;

}

public static void genereaza_pereche_chei(Context c, int nr_biti, String password, String privateKeyFilename, String publicKeyFilename){

KeyPairGenerator keyPairGenerator = null;

try {

keyPairGenerator = KeyPairGenerator.getInstance("RSA");

} catch (NoSuchAlgorithmException e2) {

e2.printStackTrace();

}

keyPairGenerator.initialize(nr_biti);

KeyPair keyPair = keyPairGenerator.genKeyPair();

byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

String publicKeyString = Base64.encodeToString(publicKeyBytes, 0);

OutputStreamWriter fos;

try {

fos = new OutputStreamWriter(c.openFileOutput(publicKeyFilename, Context.MODE_PRIVATE));

fos.write(publicKeyString);

fos.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

FileOutputStream f;

byte[] encryptedPrivateKeyBytes = null;

try {

encryptedPrivateKeyBytes = passwordEncrypt(password.toCharArray(), privateKeyBytes);

f = c.openFileOutput(privateKeyFilename, Context.MODE_PRIVATE);

f.write(encryptedPrivateKeyBytes);

f.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

}

private static byte[] passwordEncrypt(char[] password, byte[] plaintext) throws Exception {

int MD5_ITERATIONS = 1000;

byte[] salt = new byte[8];

SecureRandom random = new SecureRandom();

random.nextBytes(salt);

PBEKeySpec keySpec = new PBEKeySpec(password);

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");

SecretKey key = keyFactory.generateSecret(keySpec);

PBEParameterSpec paramSpec = new PBEParameterSpec(salt, MD5_ITERATIONS);

Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");

cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

byte[] ciphertext = cipher.doFinal(plaintext);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

baos.write(salt);

baos.write(ciphertext);

return baos.toByteArray();

}

private static byte[] passwordDecrypt(char[] password, byte[] cypher ) throws IOException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException{

int MD5_ITERATIONS = 1000;

ByteArrayInputStream bais = new ByteArrayInputStream(cypher);

byte[] salt = new byte[8];

if (bais.read(salt, 0, 8) == -1) return null;

byte[] encryptedPrivateKeyBytes = new byte[cypher.length – 8]; //null;

bais.read(encryptedPrivateKeyBytes, 0, cypher.length – 8);

PBEKeySpec keySpec = new PBEKeySpec(password);

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");

SecretKey key = keyFactory.generateSecret(keySpec);

PBEParameterSpec paramSpec = new PBEParameterSpec(salt, MD5_ITERATIONS);

Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");

cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

byte[] plaintext = cipher.doFinal(encryptedPrivateKeyBytes);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

baos.write(plaintext);

return baos.toByteArray();

}

public static String computeHash(String input) throws NoSuchAlgorithmException, UnsupportedEncodingException{

MessageDigest digest = MessageDigest.getInstance("SHA-256");

digest.reset();

byte[] byteData = digest.digest((input + "CmIaJXzOVkH70dKmqJTw" ).getBytes("UTF-8"));

StringBuffer sb = new StringBuffer();

for (int i = 0; i < byteData.length; i++)

sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));

return sb.toString();

}

Anexa 2 – Clasa MySQLiteHelper

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

public class MySQLiteHelper extends SQLiteOpenHelper{

private static final String DATABASE_NAME = "agenda.db";

private static final int DATABASE_VERSION = 1;

public static final String TABLE_Contacte = "contacte";

public static final String COLUMN_ID = "_id";

public static final String COLUMN_NUME = "nume";

public static final String COLUMN_TELEFON = "telefon";

public static final String COLUMN_CHEIE = "cheie";

private static final String DATABASE_CREATE = "create table "

+ TABLE_Contacte + "("

+ COLUMN_ID + " integer primary key autoincrement, "

+ COLUMN_NUME + " text not null, "

+ COLUMN_TELEFON + " text null ,"

+ COLUMN_CHEIE + " text not null);";

private Context context;

public MySQLiteHelper(Context context){

super(context, DATABASE_NAME, null, DATABASE_VERSION);

}

@Override

public void onCreate(SQLiteDatabase db) {

db.execSQL(DATABASE_CREATE);

}

Anexa 3 – Clasa GeneralHelper

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import android.content.Context;

public class GeneralHelper {

public static String readFromFile(Context context, String fileName) {

if (context == null) {

return null;

}

String ret = "";

try {

InputStream inputStream = context.openFileInput(fileName);

if ( inputStream != null ) {

InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

int size = inputStream.available();

char[] buffer = new char[size];

inputStreamReader.read(buffer);

inputStream.close();

ret = new String(buffer);

}

}catch (Exception e) {

e.printStackTrace();

}

return ret;

}

public static byte[] readBytesFromFile(Context context, String fileName) {

if (context == null) {

return null;

}

byte[] buffer = null;

try {

FileInputStream inputStream = context.openFileInput(fileName);

if ( inputStream != null ) {

int size = inputStream.available();

buffer = new byte[size];

inputStream.read(buffer);

inputStream.close();

}

}catch (Exception e) {

e.printStackTrace();

}

return buffer;

}

public static Boolean writeHashToFile(Context context, String hash){

try {

OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("parola.txt", Context.MODE_PRIVATE));

outputStreamWriter.write(hash);

outputStreamWriter.close();

return true;

}

catch (IOException e) {

return false;

}

}

public static String readHashFromFile(Context context){

StringBuilder stringBuilder = new StringBuilder();

String line;

BufferedReader in = null;

try {

in = new BufferedReader(new FileReader(new File(context.getFilesDir(), "parola.txt")));

while ((line = in.readLine()) != null) stringBuilder.append(line);

in.close();

} catch (FileNotFoundException e) {

return "";

} catch (IOException e) {

return"";

}

return stringBuilder.toString();

}

}

Similar Posts