Sunteți pe pagina 1din 23

Studiu asupra sistemelor de

autentificare cu baze
criptografice
Paunoiu Alexandru Dumitru

2008-2009
Cuprins

1. Descrierea si scopul lucrarii 3


2. Criptografie 5
2.1. Definirea si importanta hashurilor 5
3. Concepte 7
3.1. Autentificari cu parola stocata 7
3.2. Autentificari fara parola stocata 9
3.3. Autentificari la distanta. Securizarea conexiunii 11
3.4. Alte metode de autentificare 15
4. Concluzii 16
5. Anexe. Implementari in C# 17
6. Bibliografie 23

2
Descrierea si scopul lucrarii

Aceasta lucrare este menita a fi un punct de start pentru dezvoltatorii software ce


isi propun crearea unor sisteme de autentificare sigure bazate pe criptografie. Se va trece
de la definirea unor concepte de baza pana la detalierea catorva concepte care ajuta la o
autentificare fara probleme. Nu se vor trece cu vederea nici conceptele care se refera la o
autentificare la distanta, desigur conexiunea fiind securizata.
Inainte de a se trece la alte lucruri trebuie sa intelegeti ca aceasta lucrare nu
trateaza si factorul uman, deci nu se vor trata problemele atacurilor de gen social
engineering. Implementarile vor fi scrise in pseudocod ca mai apoi, la Anexe, sa fie
oferite implementari in C#.

Cum citim aceasta lucrare?

Daca sunteti incepatori in sisteme de autentificare va recomand parcurgerea


lucrarii de la un cap la altul. In cazul in care aveti anumite notiuni puteti trece direct la
analiza conceptelor de autentificare si la implementarea acestora.

Cine sunt personajele?

Se vor folosi 3 personaje in aceasta lucrare si anume: Bob, Alice si Pat. Alice va fi
expeditorul, Bob destinatarul iar Pat va fi cel care va incerca sa distruga securitatea
“sistemului”.

De ce ne trebuie o autentificare sigura?

Daca ne referim la firme mici si mijlocii sau la corporatii vom vedea ca acest
lucru este vital deoarece o autentificare care nu este sigura poate duce la furt de
informatii, distrugerea sistemului informatic si alte astfel de scenarii. Deasemenea un
concept de autentificare prost facut poate compromite conturile clientilor unei anumite
banci.
Sa ne gandim la urmatorul scenariu: Bob trebuie sa afle parola contului lui de la
firma pentru a-l acesa de acasa, acesta fiind de administrator. Alice ii trimite parola. Daca
procesul de autentificare nu ar fi unul sigur, atunci Pat ar putea pur si simplu sa afle
parola “ascultand” comunicarea iar in acest caz el ar putea beneficia de drepturi de
administrator in cadrul firmei.

Si… daca nu am informatii importante de ascuns?

Daca aveti vreun cont si implicit o parola va intereseaza chiar ca si un simplu user
ca procesul de autentificare sa fie unul sigur la finalul caruia sa nu ramaneti fara cont. In
acest sens trebuie sa va alegeti serviciile pe care le folositi cu foarte mare grija!

3
De ce sistemele sunt bazate pe criptografie?

Aceasta intrebare si-ar pune-o orice programator care nu a avut contact cu aceste
concepte. Raspunsul este unul destul de simplu, folosind criptografia conexiunile si
datele pot fi securizate in asa maniera incat nu pot fi “citite” decat de destinatar si
expeditor. Deasemenea criptografia ofera posibilitatea crearii unei functii ireversibile
(hash) care poate fi folosita pentru a stoca parole sau diverse semnaturi. Peste toate
acestea se adauga faptul ca toate conceptele criptografice NU sunt dependente de niciun
sistem (au la baza matematica).

Criptanaliza inamicul nr.1! Daca apar alte atacuri criptanalitice?

Nu exista daca ci cand! Vor aparea anumite atacuri care pot usura spartul
functiilor existente, insa o sa incerc sa va dau si anumite sugestii cum puteti sa securizati
astfel incat informatiile dumneavoastra sa fie in siguranta chiar si in astfel de cazuri
“extreme” sau cum sa implementati astfel incat sa puteti schimba usor functia
criptografica folosita initial.

Ce nu vom gasi in aceasta lucrare?

Scopul acestei lucrari este acela de a va prezenta anumite concepte de


autentificare asa ca NU veti gasi solutii impotriva atacurilor care nu tin de acestea dar
care totusi se pot folosi pentru a periclita siguranta autentificarii. Spre exemplu nu se vor
detalia metode de protectie impotriva SQL Injection (daca ne referim la o autentificare pe
un site) sau key loggerelor (care ar putea obtine parola tastata de Alice pentru ca apoi sa
o trimita lui Pat).

4
Criptografie

Definirea si importanta hashurilor criptografice


Ce este o functie hash?

O functie hash este acea functie care, dandu-i-se un anumit set de date, returneaza
un mesaj unic pentru datele introduse. O functie hash folosita in criptografie se
deosebeste de altele deoarece trebuie sa ofere securitate (este folosita de exemplu la
autentificari) si are lungime fixa.
Proprietatile unei functii hash criptografice:
− este o functie de tip one-way asta inseamna ca nu poate fi inversata (afiz celor
care vor sa sparga printr-un algoritm “standard”, nu se poate).
− rezistenta la coliziuni (este greu sa gasesti n mesaje care sa genereze acelasi
hash)
O functie hash poate fi privita ca o functie surjectiva (deoarece exista o
probabilitate chiar daca e mica de a gasi n mesaje pentru acelasi hash). Nu este una
bijectiva deoarece: asta ar inseamna ca poate fi inversata ceea ce este fals si ca exista o
corespondenta de 1 la 1 (la fel, fals penru anumite cazuri).
O functie care permite coliziuni este urmatoarea:
f(x)=x2 deoarece exista x2=-x1 pentru care f(x2)=f(x1)=x12.

Un exemplu de functie hash care insa nu poate fi considerata criptografica este


urmatoarea:

functie hash(intreg x)
intreg ret
ret=0
cat timp x<>0 executa
ret=ret+x MOD 10;
x=x/10;
returneaza ret

Aceasta functie va returna pentru un numar dat suma cifrelor sale. De ce nu este
criptografica? In primul rand deoarece se pot gasi usor 2 numere pentru care functia sa
returneze acelasi rezultat (de exemplu: 23 si 50) si in al doilea rand deoarece nu are
lungime fixa.
Exemple de functii hash criptografice: MD5, SHA1, SHA224, SHA512.

Criptanaliza

Pentru algoritmul MD5 au fost gasite foarte multe cazuri de coliziuni si mai mult
decat atat s-a creat un algoritm (nu este unul care da intotdeauna rezultate iar daca se

5
folosesc salturi se reduce foarte mult acest risc) numit Rainbow Tables. Ce sunt salturile?
Sunt stringuri care se pot adauga la mesajul initial astfel incat
hash(mesaj)<>hash(mesaj_saltuit).
Algoritmul SHA1 nu este recomandat deoarece complexitatea bruteforceului a
fost redusa seminificativ la doar 233.
Algoritmii SHA224, SHA512 si altele se pot folosi cu incredere deoarece pana
acum nu au fost gasite atacuri pentru acestea si nici coliziuni se pare ca nu au aparut (asta
NU inseamna ca ele nu exista).
Probabil ati observat ca in anumite cazuri se foloseste rehashuire de x ori. De
exemplu: md5(md5(x)). Acest lucru se foloseste pentru a se reduce problema coliziunilor
(cateodata e bine sa se foloseasca rehashuire de cateva mii de ori – pentru SHA1).

Practica

Cum folosim un hash pentru o autentificare? Pasii sunt urmatorii:


− Parola unui user este stocata sub un hash intr-o baza de date de exemplu
md5(parola)
− In momentul autentificarii se hashuieste parola introdusa dupa acelasi
algoritm
− Se compara cele doua hashuri, daca ele nu sunt identice atunci parola
introduse este incorecta.

6
Concepte

Autentificari cu parola stocata


Este poate cea mai folosita metoda in zilele noastre. Acest scenariu se poate privi
ca cel al unei autentificari pe un forum. Parola noastra a fost stocata hashuit la crearea
contului in baza de date iar noi dorim sa ne autentificam.

Cand se poate folosi acest concept?

Cazurile cele mai frecvente sunt acelea cand parola poate fi stocata intr-o baza de
date sau fisier la care NUMAI anumite persoane pot avea acces: baza de date al unui site
pe care ne putem autentificare, hashul parolei fiind in baza de date acesta nu poate fi
accesat de userul care se logheaza decat daca siteul prezinta vulnerabilitati (de exemplu
SQL Injection).

De ce avem nevoie?

Cunostiinte despre functiile hash, despre baze de date (optional) si despre un


limbaj de programare/scripting ce suporta conceptele mentionate anterior.

Care sunt pasii de baza ale conceptului?

1. Alice: Crearea unei parole (de preferinta una complexa pentru a nu avea
probleme pe parcurs cu atacuri care NU tin de complexitatea algoritmului de
hashuire) si trimiterea acesteia hashuit lui Bob.
2. Bob: Primirea hashului
3. Bob: Stocarea hashului in parola.
4. Alice: Trimite o cerere de autentificare catre Bob continand hashul parolei
data de ea.
5. Bob: Compara hashul primit cu hashul pe care l-a stocat in baza de date, in
cazul in care acestea sunt identice ii da acces lui Alice.
6. Alice: Primeste sau nu acces, in functie de parola introdusa.

Cum implementam?

Din perspectiva lui Bob:

//StocareDate se refera la stocarea hashului parolei


procedura StocareDate (parametru Hash)
Conectare baza de date
Stocare in baza de date Hash
Inchidere conexiune

7
//PrimireDate se refera la compararea hashurilor si acordarea
accesului
procedura PrimireDate(parametru Hash)
sir HashStocat
Conectare baza de date
Preluare hash stocat in HashStocat
Inchidere conexiune
daca Hash=HashStocat atunci
trimite 1 //autentificarea a fost facuta
altfel
trimite 0 //parola gresita

Din perspectiva lui Alice:

//trimite parola pentru stocare


procedura TrimiteHash(parametru Parola)
sir Hash=algoritm_hash(Parola)
trimite Hash

//trimite parola pentru autentificare


procedura TrimiteCerereAutentificare(parametru Parola)
sir Hash=algoritm_hash(Parola)
intreg Rezultat=trimite Hash
daca Rezultat=0 atunci
afiseaza Parola gresita
altfel
afiseaza Autentificare reusita

Avantaje si dezavantaje?

Problema acestui algoritm este ca daca hashul parolei este stocat intr-un loc in
care oricare user poate avea acces atunci gradul de securitate oferit este aproape
injumatatit deoarece daca parola este una slaba, doar prin tehnici de saltuire sau
rehashuire se poate preveni o eventuala spargere a acesteia.
Avantajul principal este acela ca acest algoritm se poate folosi indiferent daca
parola este folosita ca o cheie de criptare (pentru a securiza un anumit text) sau nu. De
exemplu pe un forum este nevoie doar de o simpla autentificare, informatiile de pe acesta
nefiind securizate. O sa primiti mai multe detalii in cadrul conceptului urmator!
Un alt avantaj (care se leaga de cel anterior) se refera la faptul ca parola se poate
schimba printr-o simpla inlocuire in baza de date a hashului fara a se mai umbla la alte
date ce au fost securizate cu acea parola (daca si NUMAI daca aceasta nu a fost folosita
ca o cheie de criptare).

8
Autentificari fara parola stocata

Conceptul se poate folosi in cazul in care dorim sa folosim o parola pentru a


cripta anumite informatii. Nu este raspandit pe web deoarece nu putem vorbi de o
autentificare, veti intelege si de ce dupa ce il voi prezenta.

Cand se poate folosi acest concept?

Cel mai simplu exemplu care il stiu este acela in care Alice doreste sa cripteze un
fisier folosind o parola introdusa. Exista sute de programe de securizare care folosesc
acest concept (inclusiv WinRAR).

De ce avem nevoie?

Notiuni despre criptosisteme si un limbaj de programare/scripting.

Care sunt pasii de baza ale conceptului?

1. Alice: Crearea unei parole (de preferinta una complexa pentru a nu avea
probleme pe parcurs cu atacuri care NU tin de complexitatea algoritmului de
hashuire) si trimiterea acesteia lui Bob.
2. Bob: Primeste parola si cripteaza in functie de ea un fisier fara a stoca cumva
parola in acesta.
3. Bob: Trimite fisierul securizat cu parola
4. Alice: Accesul poate fi obtinut doar daca parola este corecta, in caz contrar
fisierul va fi decriptat dar nu va fi in forma dorita (fisier corupt).

Cum implementam?

Din perspectiva lui Bob:

//primeste parola si trimite fisierul criptat


procedura PrimireSiTrimitereDate(parametru Parola)
Deschide fisier
sir TextFisier=citire fisier
Inchide fisier
TextFisier=cripteaza(TextFisier,Parola) //cripteaza este
functia care contine algoritmul de criptare folosit. Primul
parametru este textul care trebuie criptat iar al 2lea este
cheia de criptare.
Deschide fisiernou
Scrie TextFisier
Inchide fisiernou
trimite fisiernou

Din perspectiva lui Alice:

procedura TrimiteParola(parametru Parola)

9
trimite Parola

procedura Autentificare(parametru Parola, parametru fisier)


Deschide fisier
sir TextFisier=citire fisier
Inchide fisier
TextFisier=decripteaza(TextFisier,Parola)
Deschide fisiernou
Scrie TextFisier
Inchide fisiernou
Executa fisiernou

Avantaje si dezavantaje?

Unul dintre dezavantajele acestui concept este ca are o arie restransa in care se
poate folosi fiind mai mult bazat pe procesul de criptare/decriptare decat pe cel de
autentificare, pe cand daca parola ar fi stocata aria s-ar extinde putand fi folosit chiar si
pentru site-uri.
Un altul este ca trebuie sa asteptam decriptarea fisierului ca sa aflam daca am
tastat bine parola. Rezolvarea acestui dezavantaj ar insemna adaugarea unui text constant
in fisier care, daca este incorect dupa decriptare, atunci nu mai trebuie incercata si
decriptarea fisierului (acest lucru are un dezavantaj enorm si anume acela ca Pat poate
face un atac bruteforce NUMAI pe acel text constant ceea ce ar reduce enorm munca sa).
Avantajul acestui concept este ca parola nu este stocata deci munca lui Pat va fi
mult mai grea decat in cazul in care am fi stocat hashul parolei.

10
Autentificari la distanta. Securizarea conexiunii

Autentificarile si comunicarea la distanta sunt o problema des intalnita care a atras


atentia multor criptografi. Aceasta s-a rezolvat odata cu aparitia algoritmilor RSA, DSA
(pentru semnaturi digitale) si mai apoi Elliptic Curve.

De ce avem nevoie de o conexiune securizata?

Pat ar putea foarte simplu sa obtina documentele/parolele care sunt trimise de


catre Alice lui Bob iar acest lucru ar pune in pericol securitatea sistemului. Din aceasta
cauza a luat nastere dorinta securizarii comunicarii dintre Alice si Bob. Prima incercare
de creare a unui algoritm cat de cat solid pentru a trata astfel de sisteme a fost Diffie
Hellman, care, insa, prezinta anumite neajunsuri asa ca dupa un timp a aparut sistemul
RSA.

Cand poate fi utilizat un astfel de algoritm?

Oricand avem nevoie de o autentificare sau cand trebuie sa trimitem anumite date
de importanta maxima.

De ce avem nevoie?

Fata de cazurile anterioare, de data aceasta aveti nevoie de cunostiinte solide


despre algoritmi criptografici cu cheie publica si algoritmi de semnaturi digitale. La acest
lucru se adauga si cunoasterea protocolului TCP IP si al unui limbaj de programare.

Care sunt pasii de baza ale conceptului?

Ne vom axa pe securizarea autentificarii cu parola stocata.


1. Alice: Se trimite o cerere de conexiune
2. Bob: Se preia cererea, se genereaza o cheie publica si una privata folosind
algoritmul cu cheie publica. Bob trimite apoi cheia publica.
3. Alice: Se cripteaza parola cu cheia publica si se trimite parola criptata
4. Bob: Se primeste parola criptata, se decripteaza folosind cheia privata si apoi
se bazeaza pe sistemul de autentificare cu parola stocata pentru a stabili daca
parola este sau nu corecta. Se trimit apoi rezultatele.
5. Alice: Se primesc rezultatele autentificarii.

Cum implementam?

Din perspectiva lui Bob:

//primeste o cerere de conexiune si trimite cheia publica


procedura PrimireConexiune()
generare cheie privata
generare cheie publica
trimite cheie publica

11
//primeste parola si trimite rezultatul
procedura PrimireSiTrimitere(parametru Hash)
Hash=decripteaza(Hash,cheie privata) //Hash este decriptat
folosind ca si cheie, cheia privata
daca Hash=HashStocat atunci
trimite 1
altfel
trimite 0

Din perspectiva lui Alice:

//trimite cerere conexiune


procedura CerereConexiune()
trimite cerere

//primeste cerere si trimite parola


procedura PrimireSiTrimitere(parametru Parola)
primeste cheie publica
sir Hash=algoritm_hash(Parola)
Hash=cripteaza(Hash,cheie publica) //Hash este criptat
folosind ca si cheie, cheia publica
trimite Hash
daca primeste 1 atunci
autentificare cu succes
altfel
parola gresita

Problema apare insa in momentul in care Pat intra in scena. El poate sabota
sistemul luand cheia publica, dandu-se drept Bob si astfel inlocuind cheia. Astfel, Alice
nu mai poate accesa sistemul deoarece cripteaza cu o cheie publica gresita. Pat, apoi
poate decripta informatiile trimise de Alice cu cheia privata generata de el si astfel va stii
hashul parola ei cu ajutorul caruia se poate autentifica.

Cum rezolvam problema identitatii?

Pentru acest lucru s-au creat algoritmii de semnatura digitala (de exemplu: DSA).
Astfel, ne referim la TOT conceptul securizarii conexiune ca fiind: DSA RSA sau DSA
Elliptic Curve (depizand de algoritmul cu cheie publica folosit).

Care sunt pasii de baza ale semnaturii digitale?

1. Alice: Se face o cerere de conexiune.


2. Bob: In acest pas, Bob, genereaza cheile privata si publica. Apoi se cripteaza,
folosind cheia PRIVATA (foloseste cheia privata pe post de cheie publica),
anumite date despre el: CNP, varsta etc. Acest lucru devine semnatura
digitala. Se trimite semnatura digitala impreuna cu cheia publica.
3. Alice: Primeste cheia publica. Se asigura ca aceasta este de la Bob decriptand
semnatura cu cheia publica. Cripteaza hashul parolei folosind cheia primita si
o trimite.

12
4. Bob: Se primeste parola criptata, se decripteaza folosind cheia privata si apoi
se bazeaza pe sistemul de autentificare cu parola stocata pentru a stabili daca
parola introdusa de Alice este sau nu corecta. Se trimit apoi rezultatele.
5. Alice: Se primesc rezultatele autentificarii.
Probabil problema care apare este ca Pat poate avea acces la datele pe care Bob le
trimite lui Alice. Intr-adevar, Pat poate decripta semnatura folosind cheia publica INSA
nu o poate schimba deoarece nu are cheia privata cu care a fost criptata semnatura.

Cum implementam?

Din perspectiva lui Bob:

//primeste o cerere de conexiune si trimite cheia publica


procedura PrimireConexiune()
generare cheie privata
generare cheie publica
sir Date_Bob="datele lui Bob"//a se schimba
Date_Bob=cripteaza(Date_Bob,cheie privata)
trimite cheie publica
trimite semnatura digitala

//primeste parola si trimite rezultatul


procedura PrimireSiTrimitere(parametru Hash)
Hash=decripteaza(Hash,cheie privata) //Hash este decriptat
folosind ca si cheie, cheia privata
daca Hash=HashStocat atunci
trimite 1
altfel
trimite 0

Din perspectiva lui Alice:

//trimite cerere conexiune


procedura CerereConexiune()
trimite cerere

//primeste cerere si trimite parola


procedura PrimireSiTrimitere(parametru Parola)
primeste cheie publica
primeste semnatura digitala
sir Date_Bob=decripteaza(Date_Bob,cheie publica)
daca decriptarea nu poate avea loc atunci
semnatura digitala sau cheie publica invalida
sir Hash=algoritm_hash(Parola)
Hash=cripteaza(Hash, cheie publica) //Hash este criptat
folosind ca si cheie, cheia publica
trimite Hash
daca primeste 1 atunci
autentificare cu succes
altfel
parola gresita

13
Avantaje si dezavantaje?

Exista foarte multe avantaje asa ca nu le voi enumera, insa voi mentiona un
dezavantaj si anume faptul ca viteza de transfer este scazuta in cazul folosirii algoritmului
RSA deoarece criptarea se face greoi. Astfel, in cazul in care se transmit fisiere de cativa
MB, un transfer securizat folosind acest algoritm va avea loc foarte greu.

14
Alte metode de autentificare
Vom discuta in continuare despre alte metode folosite pentru autentificare, unele
mai complexe altele mai usoare, dar toate fiind destul de importante. TOATE insa, se
bazeaza si pe sistemele prezentate anterior!

De la ce pornim?

Se porneste de la autentificarea pe baza de poza deoarece acest lucru poate fi


extins. Vom vedea si cum. In acest caz poza inlocuieste parola. Poza se poate folosi si ca
si o cheie pentru a cripta anumite informatii (vezi autentificari fara parola stocata, partea
de criptare a informatiilor). Aceasta poate contine informatii despre cel care se autentifica
si asa se ajunge la cum se poate extinde acest algoritm…

Cum extindem autentificarea pe baza de poza?

Poza poate contine amprenta sau irisul dumneavoastra! Astfel se ajunge la


dezvoltarea unor algoritmi biometrici de citire ai irisului sau ai amprentei, stocandu-se
informatii vitale despre acestea. Foarte multe sisteme de autentificare pe baza de
amprenta sau iris exista deja si se folosesc chiar si la laptopuri.

Ofera algoritmii biometrici stabilitate?

Raspunsul este unul scurt si cuprinzator: NU! Deocamdata nu este niciun algoritm
creat care sa ofera o stabilitate foarte mare astfel incat se poate ajunge la probleme in care
doi indivizi se pot autentifica folosind amprente diferite sau unui individ nu ii mai este
recunoscut(a) amprenta sau irisul dupa o anumita perioada. Pentru cei interesati in
legatura cu algoritmii de recunoastere ai amprentelor puteti cauta informatii despre
algoritmul Minutia care este folosit momentan ca standard.

Cand folosim algoritmii biometrici?

Deobicei astfel de algoritmi se folosesc la laptopuri sau in cadrul firmelor pentru a


obtine acces intr-un anumit sector.

Alte avantaje si dezavantaje?

Printre dezavantaje ar mai fi faptul ca pentru un home user, un astfel de sistem ar


insemna achizitionarea unui cititor de iris/amprenta. In plus nu prea se folosesc astfel de
algoritmi pentru autentificare la distanta (desi daca ar oferi stabilitate mare ar putea
incepe sa fie folositi).
Avantaje exista si anume faptul ca nu mai trebuie tinuta minte o anumita parola
sau faptul ca ofera o siguranta poate mai mare decat o parola, asta in cazul in care s-ar
oferi stabilitate.

15
Concluzii

Inchei aceasta lucrare prin a va spune ca siguranta autentificarii este una foarte
importanta si deci sper ca aceasta lucrare v-a oferit un punct de start important. De-a
lungul acestei lucrari ati invatat cum sa asigurati o autentificare singura si apoi sa
securizati conexiunea folosind chiar si o semnatura digitala. Apoi ati studiat un rezumat
despre alte metode de autentificare care v-au facut sa realizati ca se poate renunta la
parola.

16
Anexe. Implementari in C#

Voi oferi o implementare in C# al celui mai complex algoritm si anume:


securizarea conexiunii cu autentificare cu parola stocata. In cazul in care vreti si
semnatura digitala puteti folosi pe langa clasa RSACryptoServiceProvider,
DSACryptoServiceProvider.

S-a folosit platforma .NET 2.0!

public class StateObject


{
private const int buffsize = 1024;
public Socket workSocket = null;
public int BUFFER_SIZE = buffsize;
public byte[] buffer = new byte[buffsize];
public StringBuilder sb = new StringBuilder();
}

public class ClientObject


{
public TcpClient tcpC = null;
public string MessageToSend = "";
public string Header = "";
}

public class DBSetup


{
public string dataSrc;
public int port;
public string dbname;
}

public class Crypto


{
public string Serialization(object cl)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream msBF = new MemoryStream();
bf.Serialize(msBF, cl);
msBF.Flush();
msBF.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(msBF,Encoding.Default);
string data = sr.ReadToEnd();
sr.Close();
return data;
}

public object DeSerialization(byte[] buff)


{

17
MemoryStream ms = new MemoryStream();
ms.Write(buff, 0, buff.Length);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
BinaryFormatter bf = new BinaryFormatter();
object ret=bf.Deserialize(ms);
ms.Close();
return ret;
}

public string RSAEnc(string text, RSAParameters rsaP)


{
if (rsaP.Exponent!=null)
{
RSACryptoServiceProvider rsac = new
RSACryptoServiceProvider();
rsac.ImportParameters(rsaP);
byte[] b =
rsac.Encrypt(Encoding.Default.GetBytes(text), false);
rsac.Clear();
return Encoding.Default.GetString(b);
}
else
{
return text;
}
}

public string RSADec(string text, RSAParameters rsaP)


{
RSACryptoServiceProvider rsac = new
RSACryptoServiceProvider();
rsac.ImportParameters(rsaP);
byte[] b = rsac.Decrypt(Encoding.Default.GetBytes(text),
false);
rsac.Clear();
return Encoding.Default.GetString(b);
}

public string generateHash(string text)


{
SHA256Managed shac = new SHA256Managed();
byte[] b =
shac.ComputeHash(Encoding.Default.GetBytes(text));
shac.Clear();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < b.Length; i++)
{
sb.Append(b[i].ToString("X"));
}
return sb.ToString();
}
}

class Program
{
static DBSetup db=new DBSetup();

18
static string connStr;
static RSACryptoServiceProvider rsac;

static void Main(string[] args)


{
//RSA SERVER DATA
Crypto cr = new Crypto();
rsac = new RSACryptoServiceProvider();
string rsa =
cr.Serialization((object)rsac.ExportParameters(false));
//end
InitConnection();
//StoreData("alex", "newpass");
StartServer(200);
//server to client
SendData("127.0.0.1", 200, rsa,"RSA");
WaitForResponse();
//client to server
SendData("127.0.0.1", 200, "alex\nnewpass","AUTH");
Console.ReadLine();
}

private static void InitConnection()


{
db.dataSrc = "127.0.0.1";
db.port = 1599;
db.dbname = "testdb";
connStr = String.Format("Data Source={0},{1};Integrated
Security=true;Initial Catalog={2};", db.dataSrc, db.port.ToString(),
db.dbname);
}

private static void StoreData(string user, string pass)


{
Crypto cr = new Crypto();
pass = cr.generateHash(pass);
SqlConnection sqlconn = new SqlConnection(connStr);
sqlconn.Open();
SqlCommand sqlComm = new SqlCommand("INSERT INTO tbl
(username,password) VALUES ('" + user + "','" + pass + "')",sqlconn);
sqlComm.ExecuteNonQuery();
sqlconn.Close();
}

private static string ReadData(string user)


{
Crypto cr = new Crypto();
SqlConnection sqlconn = new SqlConnection(connStr);
sqlconn.Open();
SqlCommand sqlComm = new SqlCommand("SELECT * FROM tbl
WHERE username='"+user+"'", sqlconn);
SqlDataReader sqlDR = sqlComm.ExecuteReader();
sqlDR.Read();
string StoredHash=(string)sqlDR["password"];
sqlconn.Close();
return StoredHash;
}

19
private static void CompareReceivedAuth(string auth)
{
Crypto cr = new Crypto();
string user = auth.Split('\n')[0];
string pass = auth.Split('\n')[1];
//server to client
//TODO: replace client ip
if (pass == ReadData(user))
{
SendData("127.0.0.1", 200, "","AUTH OK\n");
}
else
{
SendData("127.0.0.1", 200, "","AUTH NOT OK\n");
}
}

private static void StartServer(int port)


{
TcpListener tcpL = new TcpListener(IPAddress.Any, port);
tcpL.Start();
tcpL.BeginAcceptSocket(new
AsyncCallback(AcceptConnectionsCallback), tcpL);
}

private static void AcceptConnectionsCallback(IAsyncResult


async)
{
TcpListener tcpL = (TcpListener)async.AsyncState;
Socket transfer = tcpL.EndAcceptSocket(async);
StateObject so=new StateObject();
so.workSocket=transfer;
transfer.BeginReceive(so.buffer, 0, so.BUFFER_SIZE, 0, new
AsyncCallback(ReadDataCallback), so);
tcpL.BeginAcceptSocket(new
AsyncCallback(AcceptConnectionsCallback), tcpL);
}

private static RSAParameters RSAP;

private static void ReadDataCallback(IAsyncResult async)


{
StateObject so = (StateObject)async.AsyncState;
Socket sData = so.workSocket;
int size = sData.EndReceive(async);
if (size > 0)
{
so.sb.Append(Encoding.Default.GetString(so.buffer, 0,
size));
sData.BeginReceive(so.buffer, 0, so.BUFFER_SIZE, 0,
new AsyncCallback(ReadDataCallback), so);
}
else
{
if (so.sb.Length > 0)
{

20
Crypto cr = new Crypto();
string strData = so.sb.ToString();
string Header = strData.Split('\n')[0];
string Data = strData.Split(new char[] { '\n' },
2)[1];
switch (strData.Split('\n')[0])
{
//server, obtains auth data
case "AUTH":
Data = cr.RSADec(Data,
rsac.ExportParameters(true));
CompareReceivedAuth(Data);
break;
//client, obtains public key
case "RSA":
RSAP =
(RSAParameters)cr.DeSerialization(Encoding.Default.GetBytes(Data));
break;
//server, writes results
default:
Console.Write(Header);
break;
}
}
sData.Close();
}
}

private static void WaitForResponse()


{
while (RSAP.Exponent == null)
{
}
}

private static void SendData(string IP, int port,string


Message,string Header)
{
TcpClient tc = new TcpClient();
ClientObject co = new ClientObject();
co.MessageToSend = Message;
co.Header = Header;
co.tcpC = tc;
tc.BeginConnect(IPAddress.Parse(IP), port, new
AsyncCallback(AsyncConnectCallback), co);
}

private static void AsyncConnectCallback(IAsyncResult async)


{
Crypto cr = new Crypto();
ClientObject co = (ClientObject)async.AsyncState;
TcpClient tc = co.tcpC;
/*
* co.Header=RSA => server to client sends public key
* co.Header=AUTH => client to server sends auth data
* */
string Message;

21
if (co.Header == "AUTH")
{
string user=co.MessageToSend.Split('\n')[0];
string pass=co.MessageToSend.Split('\n')[1];
co.MessageToSend = user + "\n" +
cr.generateHash(pass);
}
Message = co.Header+"\n"+cr.RSAEnc(co.MessageToSend,RSAP);
tc.EndConnect(async);
byte[] buff = Encoding.Default.GetBytes(Message);
Stream nets = tc.GetStream();
nets.Write(buff, 0, buff.Length);
nets.Flush();
tc.Close();
}
}

22
Bibliografie

- “Cartea Codurilor” Simon Singh


- “Introducere in algoritmi” Thomas H. Cormen
- “Cryptography for Developers” Tom St Denis
- “Studiu in evolutia criptografiei” Paunoiu Alexandru, Oana Mirela
- “Handbook of Applied Cryptography” A. Menezes, P. van Oorschot, si S.
Vanstone
- “Cryptography and Network Security Principles and Practices, Fourth Edition”
William Stallings

23