Sigurnost u C Sharp-u
Temu rezervirao: Bernard Curić
Članovi:
- Bernard Curić
- Filip Faletar
Link na repozitorij: https://github.com/ffaletar/securityCSharp
Uvod
U ovom projektu obraditi će se tema "Sigurnost u C#". Objasniti ćemo principe, savjete i preporuke Owasp.org-a, te Microsofta na ovu temu, te ćemo na primjeru pokazati jedan od načina realizacije sigurnosti u C#.
Programski jezik C# je programski jezik koji je potpuno baziran na principima objektno orijentiranog programiranja, svi elementi unutar njega predstavljaju objekt. Prethodnici C# su C i C++, te je sličan programskom jeziku Java. Razvili su ga Anders Hejlsberg, Scott Wiltamuth i Peter Golde kao dio .Net projekta. Prvi puta ga je javnosti predstavio Microsoft 2002. godine. Najnovija verzija je C# 6.0. 2014. Godine Microsoft je promijenio kompajler za C# koji je open-source kod, čime su omogućene lakše promjene na programskom jeziku. .Net Framework je glavna Microsoft-ova platforma za razvoj aplikativnih rješenja, koja podržava API za ASP.NET, Windows desktop aplikacije, Windows Communication Foundation servise, Share Point, Visual Studio alate za Office i druge tehnologije. Microsoft održava .Net Framework up-to-date putem Winodws Update servisa, te programeri ne moraju zasebno provoditi ažuriranje Frameworka. Pojedini framework-ovi mogu se ažurirati koristeći NuGet.
.Net Framework smjernice Owasp.org-a
Pristup podatcima
- Koristite parametrizirane SQL naredbe za pristup svim podatcima bez iznimke.
- Ne koristite SQL naredbe u nizu parametara koji tvore SQL string.
- Whitelist-ajte dopuštene vrijednosti koje unosi korisnik. Koristite enum-e, TeyParse ili lookpu vrijednosti kako bi se osigurali očekivani podatci koji dolaze od korisnika.
- Enum-i su idalje ranjivi na neočekivane vrijednosti jer .Net potvrđuje samo uspješan cast na temeljne vrste podataka, integer-i po defoltu. Enum.IsDefined može provjeriti da li ulazna vrijednost vrijedi u listi definiranih vrijednosti.
- Primjenjujte načelo najmanje privilegija prilikom kreiranja baze korisnika u vašoj proizvoljnoj bazi podataka. Korisnik baze podataka bi trebao biti u mogućnosti pristupiti stvarima koje imaju smisla u UseCase-u.
- Korištenje Entity Framework-a je vrlo učinkovit mehanizam prevencije SQL injection-a. Zapamtite da su vlastiti ad hoc upiti u EF jednako osjetljivi na SQLi kao i obični SQL upiti.
- Kada koristite SQL Server, preferirajte integriranu provjeru preko SQL autentifikacije.
- Koristite Always Encrypted gdje god je to moguće za osjetljive podatke (SQL Server 2016 i SQL Azure)
Enkripcija
- Nikad ne pišite vlastitu enkripciju
- Koristite Windows Data Protection API (DAPI) za sigurnu lokalnu pohranu osjetljivih podataka.
- Standardne .Net Framework biblioteke nude samo neautentificirane implementacije enkripcije. Autentične načine enkripcije kao što su AES-GCM na kojima se temelji moderni Cryptography API : Next Generation su dostupni putem CLRSecurity biblioteke.
- Koristite jake hash algoritme.
- U .Net-u (i u Framework-u i u Core-u) najjači hash algoritam za opće hash potrebe je System.Security.Cryptography.SHA512.
- U .Net Framework-u najjači algoritam za hash lozinki je PBKDF2, implementiran kao System.Security.Cryptography.Rfc2898DeriveBytes.
- U .Net Core-u najjači algoritam za hash lozinki je PBKDF2, implementiran kao Microsoft.AspNetCore.Cryptography.KeyDerivation.Pbkdf2, koji ima nekoliko značajnijih prednosti u odnosu na Rfc2898DeriveBytes.
- Prilikom korištenja hash funkcije za hash ne unikatnih unosa kao što su lozinke, koristite salt vrijednosti, dodane orihinalnoj vrijednosti prije hash-iranja.
- Provjerite da li vaša aplikacija ili protokol može lako podržati buduće promjene kriptografskih algoritama.
- Koristite NuGet kako bi održali sve svoje pakete up-to-date. Pazite na ažuriranja vaših postavki razvoja i plan ažuriranja odredite u skladu s tim.
Općenito
- Zaključajte config datoteku.
- Uklonite sve aspekte konfiguracije koji nisu potrebni.
- Enkriptirajte osjetljive dijelove web.config koristeći aspnet_regiis-pe.
- Za Click Once aplikacije .Net Framework bi trebalo nadograditi na verziju 4.6.2 kako bi se osigurala TLS 1.1/1.2 podrška.
Smjernice za ASP.NET Web Forme
- Uvijek koristite HTTPS.
- Omogućite requireSSL za kolačiće i elemente forme, te HttpOnly za kolačiće u web.config-u.
- Implementirajte customErrors.
- Uvjerite se da je tracing isključen.
- Dok ViewState nije uvijek prikladan za web development, koristeći ga možete ublažiti CSRF. Da bi ViewState štitio protiv CSRF napada trebate postaviti ViewStateUserKey.
- Razmotrite HSTS(HTTP Strict Transport Security) u IIS-u.
- Uklonite verzijska zaglavlja.
- Uklonite zaglavlja servera.
-- Bernard Curić
Smjernice za Windows Forms aplikacije
- Koristite djelomično povjerenje kada god je to moguće. Widnows aplikacije s djelomičnim povjerenjem smanjuju mogućnost napada na aplikaciju. Dodjeljivanje dozvola aplikaciji samo za one koje mora koristiti, a ono što može koristiti neka napravi zahtjev za tim dozvolama za vrijeme izvođenja.
- Koristite ClickOnce implementaciju. Za poboljšane dozvole, koristite podizanje dozvola za vrijeme izvođenja ili povjerljivim aplikacijama za vrijeme instačacije.
.Net Framework mehanizmi za zaštitu
.Net Framework nudi nekoliko mehanizama za zaštitu resursa i koda neautoriziranog koda i korisnika:
- ASP.Net Web Application Security pruža pomoć pri ograničavanju pristupa stranici, tako da se usporede autentificirani podatci na Windows NT datotečnom sustavu ili u XAML datoteci koja sadrži autorizirane korisnike, autorizirane uloge ili autorizirane Http metode.
- Sigurnost pristupa kodu koristi dozvole kako bi pomoglo ograničiti pristup koji kod ima prema zaštićenim resursima i operacijama. Pomaže u zaštiti računalne sustave od zlonamjernih mobilnih kodova te pruža način da se mobilni kodovi sigurno pokrenu.
- Sigurnost temeljena na ulogama pruža informacije koje su potrebne za donošenje odluka o tome što je korisniku dozvoljeno raditi. Ove odluke mogu se temeljiti na korisnikovu identitetu, članstvu ili oboje.
SQL Injection
SQL Injection je tehnika umetanja nedopuštenog koda na mjesta gdje aplikacija traži korisnički unos. Prema Owasp.org-u, napad SQL Injection-om ocijenjen je kao najkorišteniji napad od strane hackera. Ova tehnika se prvi put pojavila 1998. godine te se od tada konstantno širila. Do danas su razvijene mnoge tehnologije i načini obrane od SQL Injection-a. Ovakav se napad najviše pojavljuje u web aplikacijama, no moguć je u svim aplikacijama koji imaju svoju SQL bazu podataka. Danas je vrlo teško napasti web aplikaciju na ovaj način, čak i ako web aplikacija nije razvijena prema smjernicama koje predlaže Owasp.org kao najbolju obranu od napada. Razlog je taj što svi moderniji web preglednici imaju ugrađene razne funkcije sprječavanja unošenja nedopuštenog koda na mjesta predviđena za korisnički unos, kao npr. prijava, registracija korisnika, pretraživanje itd.
Iako današnji web preglednici svojim metodama smanjuju ranjivosti web aplikacija, ipak je pri razvitku aplikacija potrebno poduzeti preventivne mjere svođenja aplikativnih ranjivosti na minimum. SQL Injection je vrlo poznati napad po svojoj jednostavnošću, ali poznat je i po svojoj lakoj prevenciji s jednostavnim mjerama opreza.
Primjeri SQL Injection-a
Primjer 1
Početni upit:
upit = "SELECT * FROM korisnik WHERE korisnickoIme = '" + korisnickoIme + "';"
Za prethodno navedeni upit moguće je izvšiti SQL Injection na dva načina:
- Umetanje '1 = 1' u upit
' OR '1'='1Upit s prethodnim unosa:
SELECT * FROM korisnik WHERE korisnickoIme = '' OR '1'='1';
Rezultat ovog upita je uvijek true, stoga je napadač uspio dohvatiti sve podatke iz tablice korisnik.
- Umetanje komentara ( -- , /* ) kako bi se blokirao ostatak upita
' OR '1'='1' -- ' OR '1'='1' /*Upit s prethodnim unosom:
SELECT * FROM korisnik WHERE korisnickoIme = '' OR '1'='1' -- ';
Primjer 2
Početni upit:
upit = "SELECT * FROM korisnik WHERE korisnickoIme = '" + korisnickoIme + "';"Unos:
1; DROP TABLE korisnikUpit s prethodnim unosom:
upit = "SELECT * FROM korisnik WHERE korisnickoIme = 1; DROP TABLE korisnik;
Napadač ovim upitom izvršava naredbu za brisanje tablice u bazi podataka te na taj način stvara veliku štetu žrtvi.
Prevencija SQL Injection-a
Parametrizirani upiti
Umjesto umetanja korisničkih unosa u SQL upit, preporučeno je da se koriste parametrizirani upiti čije su vrijednosti poznate tek prilikom izvršenja naredbe. Korištenim parametrima je određen tip parametra, što onemogućuje korisnicima upisivanje raznih znakova kao što su navodnici, zagrade, razmaci itd.
Primjer parametriziranog upita u C#:
string upit = "UPDATE Korisnik SET korisnickoIme = @korisnickoIme " + "WHERE id = @id;"; SqlCommand naredba = new SqlCommand(upit, connection); naredba.Parameters.AddWithValue("@korisnickoIme", "ffaletar"); naredba.Parameters.AddWithValue("@id", 5);
Object Relational Mapping
Korištenjem ORM-a izbjegavamo pisanje SQL naredbi. ORM samostalno generira parametrizirane SQL naredbe iz objektno orijentiranog koda.
Upotreba uzoraka
Bez obzira kojeg tipa podataka je parametar, preporučuje se korištenje uzoraka (eng. pattern). Potrebno je odrediti pattern koji program prihvaća pri unosu podataka, dakle provjerava se odgovara li uneseni podatak određenom uzorku, odnosno patternu.
Primjer regexa:
Regex rgx = new Regex(@"^[a-zA-Z0-9]\d{2}[a-zA-Z0-9](-\d{3}){2}[A-Za-z0-9]$");
Dozvole baze podataka
DENY SELECT ON korisnik TO korisnik123;
Dozvole baze podataka omogućuju kontrolu nad upitima. Korisnicima se može onemogućiti dohvaćanje podataka iz neke tablice ili dohvaćanje određenog podatka iz tablice.
Cross-Site Request Forgery
CSRF je vrsta napada kojom se korisnici prisiljavaju da naprave neke neželjene akcije na web aplikacijama gdje predstavljaju trenutno prijavljenog korisnika. Ovi napadi se najčešće obavljaju preko mail servisa. Na taj način napadači šalju poveznice korisnicima web aplikacije, koji zapravo izvrše neželjenu akciju. Ova vrsta napada se ne koristi za prikupljanje podataka, već za promjene raznih podataka web aplikacije.
Primjer CSRF-a
Dobar primjer CSRF napada je objašnjen na stranici Owasp.org. Postoje tri uloge na bankovnoj web aplikaciji, Alice koja želi poslati prijatelju Bob-u $100 te Maria, koja kao napadač želi da Alice upravo njoj pošalje $100000.
Ovisno o tome koristi li banka za izvršenje ove akcije POST ili GET metodu, razlikujemo sljedeća dva napada:
Napad preko GET metode
Pošto web aplikacija ove banke za prebacivanje novca s jednog na drugi račun koristi GET metodu, napadač Maria mora izvršiti napad preko GET metode, također. Reći ćemo da se zahtjev za prijenos novca obavlja na ovaj način:
GET http://bank.com/transfer.do?acct=BOB&amount=100 HTTP/1.1
Kao što je vidljivo, u GET metodi naveden je primatelj, odnosno račun primatelja te iznos novca kojeg Alice želi poslati. Kako je Maria odlučila napasti Alice, ona uzima originalnu GET naredbu te mijenja parametre, koji su ovom primjeru račun primatelja i iznos novca. Sada zahtjev izgleda ovako:
GET http://bank.com/transfer.do?acct=MARIA&amount=100000
Maria sada želi ovaj zahtjev nekako podmetnuti Alice, kako bi ona umjesto originalne akcije, upravo izvršila ovu. To može obaviti na sljedeće dva načina:
- Slanje mail-a u kojem se nalazi GET poziv.
- Umetanje skripte na stranicu koju će vrlo vjerojatno Alice posjetiti prilikom u korištenja web aplikacije banke. Bitno je da je Alice prijavljena u bankovni sustav tijekom izvršenja napada.
Ovo je dobar primjer HTML koda koji prikazuje vrlo jednostavan način da Alice pozove GET metodu:
<a href="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my Pictures!</a>
Dakle, u mailu koji je Alice primila od napadača (iako ona misli da je mail poslan od strane banke) nalazi se slika koju će vrlo vjerojatno otvoriti ne znajući da upravo, ni kriva ni dužna, radi veliku grešku. Pritiskom na sliku, Alice poziva GET metodu koja joj oduzima novac.
Napad preko POST metode
Napad preko POST i GET metode vrlo su slični, jedina je razlika u tome kako se zahtjev izvršava. Neka POST zahtjev za prijenos novca izgleda ovako:
POST http://bank.com/transfer.do HTTP/1.1 acct=BOB&amount=100
POST metode može biti izvršena samo preko forma za unos korisničkih podataka. Stoga, da bi napadač Maria prisilio korisnika Alice da izvrši POST metodu, koristi sljedeću formu koju Alice ne vidi. Ovakva forma može biti izvršena i jednostavnim Javascript pozivom metode za submit forme.
<form action="http://bank.com/transfer.do" method="POST"> <input type="hidden" name="acct" value="MARIA"/> <input type="hidden" name="amount" value="100000"/> <input type="submit" value="View my pictures"/> </form>
Kod preuzet s: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
Cross-Site Scripting (XSS)
Još jedan vrlo poznati napad je Cross-Size Scripting. Ovaj napad izvršava se na klijentskoj strani gdje napadač ubacuje zlonamjerne skripte u web aplikacije. Moguće ga je izvršiti preko raznih skriptnih jezika, npr. ActiveX, VBScript i Flash, ali ipak se najčešće pojavljuje umetanje JavaScript koda u određenu web aplikaciju. Na taj način napadač potiče žrtvu na izvršenje neželjenih akcija. Može se reći da je XSS jedna od najpoznatijih ranjivosti web aplikacije, a pojavljuje se na web aplikacijama koje nemaju podešenu validaciju korisničkih unosa. Bitno je napomenuti da napadač ne napada žrtvu direktno, već koristi web aplikaciju koju bi žrtva mogla posjetiti te na taj način žrtvi prenosi svoj maliciozni kod.
Primjer XSS napada
Za početak, napadač treba "upoznati" žrtvu, odnosno poznavati navike žrtve, točnije web aplikacije koja žrtva posjećuje. Zatim među tim web aplikacijama pronalazi onu koja je ranjiva, odnosno koja nema podešenu validaciju korisničkog unosa. Nakon što napadač izvrši ove početne korake, spreman je za napad. Recimo da web aplikacija koristeći sljedeći kod, korisnicima omogućuje prikaz zadnjih komentara.
print "<html>" print "<h1>Most recent comment</h1>" print database.latestComment print "</html>"
Napadač koristi tih par linija koda kako bi izvršio svoj napad, na način da piše komentar na web aplikaciju koja nema podešenu validaciju za pisanje komentara. Maliciozni komentar izgleda ovako:
<script>doSomethingEvil();</script>
Tada se komentar već nalazi u bazi podataka od web aplikacije. Sada obični korisnik web aplikacije posjećuje sekciju s prikazom komentara te na taj način izvršava maliciozni kod.
<html> <h1>Most recent comment</h1> <script>doSomethingEvil();</script> </html>
Kod i slika preuzeta s: https://www.acunetix.com/websitesecurity/cross-site-scripting/
Denial Of Service
Denial of Service je napad koji se najviše izvodi nad web aplikacijama. Cilj ovog napada je učiniti neku uslugu nedostupnom za krajnjeg korisnika. Napadač izvodi napad na način da u kratkom vremenskom roku pošalje veliki broj zahtjeva, koji je toliko velik da ih server jednostavno ne može sve obraditi. Na taj način postiže nedostupnost web aplikacije. DOS napadi mogu ciljati serversku infrastrukturu, aplikacijske ranjivosti, ranjivosti u komunikacijskim protokolima i propuste u operacijskim sustavima. Postoje razni programski proizvodi i alati za prevenciju DOS napada.
Sensitive data exposure
Do Sensitive data exposure dolazi kada aplikacija neadekvatno zaštiti svoje osjetiljive podatke. Ti podatci mogu biti bilo što, kao što su lozinke, tokeni sesije, podatci o kreditnim karticama, te različiti privatni podatci koji se mogu izložiti. Savjeti za moguću prevenciju:
- Ne spremajte enkriptirane lozinke
- Koristite snažne hash funkcije za spremanje lozinki, kao što su PBKDF2, BCrypt ili SCrypt s najmanje 8000 iteracija.
- Potičite lozinke s minimalnom složenosti koje će preživjeti napad rjieči iz "riječnika", odnosno duže lozinke koje koriste cijeli skup znakova, brojeve, simbole i slova, za povećanje entropije.
- Koristite jake enkripcijske rutine, kao što su AES-512 gdje se osobni podatci moraju vratiti u izvorni oblik. Ne enkriptirajte lozinke. Zaštitite enkripcijske ključeve više nego i jednu imovinu.
- Koristite TLS 1.2 za cijeli site. Nabavite besplatni certifikat StartSSL.com ili LetsEncrypt.org. Ne dozvoljavajte SSL, koji je zastario. Imajte jaku TLS politiku, koristite TLS 1.2 gdje god je to moguće. Provjerite konfiguraciju pomoću SSL Testa.
- Provjerite da u zaglavljima nisu navedeni podatci o vašoj aplikaciji. Pogledajte HttpHeaders.cs ili Dionach StripHeaders za uklanjanje oznake Servera.
Projektni primjeri
Izradili smo Windows Form aplikaciju u alatu Visual Studio kako bismo prikazali neke ranjivosti i preventivne mjere. Dobra zaštita od raznih računalnih napada je enkripcija, stoga smo je prikazali u prvom primjeru u ovom projektu. Zatim smo praktično obradili i SQL Injection u Windows Form aplikacijama. Iako se SQL Injection najviše izvršava na web aplikacijama, ovdje ćemo pokazati da je on moguć i na desktop aplikacijama. Također smo isprobali tehnologiju pod nazivom ClickOnce Security and Deployment.
Enkripcija lozinke
SQL Injection
SQL Injection jedan je od najpoznatijih sigurnosnih prijetnji na web aplikacijama, no i desktop aplikacije vrlo lako mogu biti oštećene ovom vrstom napada. Mi ćemo u ovom primjeru prikazati SQL Injection u Windows Form aplikaciji. Za početak smo kreirali formu koja je prikazana na sljedećoj slici:
Na lijevoj strani smo napravili pretraživanje korisnika preko Entity Framework-a, koji je ujedno dobra prevencija za izvšenje SQL Injection napada. Kako bismo prikazali način na koji SQL Injection funkcionira, s desne strane smo napravili formu za pretraživanje koja podatke dohvaća direktno iz baze podataka bez parametriziranih upita koji također dobro služe kao zaštita od SQL Injection-a.
using (connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand("SELECT korisnickoIme, ime, prezime, mail FROM Korisnik WHERE korisnickoIme LIKE '" + textBox1.Text + "%'", connection); SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) { string korisnickoIme = reader["korisnickoIme"].ToString(); string ime = reader["ime"].ToString(); string prezime = reader["prezime"].ToString(); string mail = reader["mail"].ToString(); Korisnik1 korisnik = new Korisnik1(ime, prezime, korisnickoIme, mail); listaKorisnika.Add(korisnik); } dataGridView2.DataSource = dt; }
Kao što je vidljivo u kodu, ne postoje parametrizirani upiti, niti ORM alata, stoga je ovaj način pisanja koda otvoren za SQL Injection. Da ponovimo, SQL Injection je napad kojim se ubacuje SQL kod na mjesta koja nisu predviđena za to, a to su uglavnom razni inputi podataka. Gornji primjer pisanja koda je vjerojatno najgora moguća obrana protiv SQL Injection. Toplo se preporuča upotrebo nekog ORM alata, korištenje parametriziranih upita, pisanje dozvola baze podataka i korištenje uzoraka.
Ranjivi upit koji dohvaća korisnike iz baze podataka.
SELECT korisnickoIme, ime, prezime, mail FROM Korisnik WHERE korisnickoIme LIKE 'Korisnik%'
Umjesto paramatra "Korisničko ime", napadač će unijeti sljedeći kod, kako bi izbrisao korisnik s korisničkim imenom "Korisnik1"
Filipo'; DELETE FROM Korisnik WHERE korisnickoIme = 'Korisnik1' --%'
Tada cijeli upit izgleda ovako:
SELECT korisnickoIme, ime, prezime, mail FROM Korisnik WHERE korisnickoIme LIKE 'Filipo'; DELETE FROM Korisnik WHERE korisnickoIme = 'Korisnik1' --%'
Mogući su razni unosi koji mogu oštetiti i korisnika i aplikaciju, odnosno vlasnika aplikacije.
Filipo'; DROP TABLE Korisnik; Filipo'; UPDATE Korisnik SET lozinka='hack' WHERE korisnickoIme='Korisnik1' --
Prvi unos napadača izravno oštećuje bazu podataka na način da briše tablicu Korisnik. Drugi upit pak mijenja lozinku određenog korisnika, te na taj način napadač ima pristup njegovom profilu. Ipak, zadnja linija koda pokazuje koliko enkripcija pomaže pri zaštiti korisničkih podataka. Naime, zadnja linija koda ne bi izravno mogla naštetiti našoj aplikaciji s obzirom da je podešena enkripcija korisnika, odnosno korisničke lozinke. Stoga napadač izmjenjenu lozinku ne bi mogao iskoristiti kao lozinku za zlonamjernu prijavu na tuđi korisnički račun.
Sljedeća slika prikazuje istu Windows Formu nakon SQL Injection napada. Na lijevoj strani ispisa korisnika više ne postoji "Korisnik6", dakle, napadač je uspio izbrisati sve podatke za tog korisnika samo jednim unosom.
ClickOnce Security and Deployment
Prema savijetima i smjernicama Owasp.org-a za razvoj sigurnosti u Windows Forms aplikacijama, napravili smo ClickOnce Deplooyment, koji objavljuje gotovu aplikaciju, koja kod svakog pokretanja aplikacije provjerava postoje li promjene, odnosno update verzije naše aplikacije. Navedeni Deployment smo koristili kako bi naknadno mogli dodati mogućnosti u aplikaciju, te ostavili prostor, kako bi mogli ispraviti prije svega sigurnosne, tako i ostale propuste u našoj aplikaciji. Kroz ovakav način Deploymenta možemo dizati različite razine sigurnosti aplikacije.
Provjera i pohrana lozinke
Nakon pokretanja aplikacije korisnik mora unijeti svoje korisničko ime, te lozinku, u slučaju da korisnik nema potrebne podatke, odabire mogućnost registracije, te u njoj unosi svoje podatke, koji se dalje spremaju u našu bazu podataka. Budući da je lozinka osjetljiv podatak, pokušali smo korisnika natjerati da koristi složenu lozinku, te smo pomoću metode ValidatePasword, provjerili da li upisana lozinka sadrži barem jedan broj, te po jedno veliko i malo slovo.
var hasNumber = new Regex(@"[0-9]+"); var hasUpperChar = new Regex(@"[A-Z]+"); var hasLowerChar = new Regex(@"[a-z]+");
Nakon provjere unosa lozinke, ako je lozinka ispravna, spremamo ju kao hash, koristeći PBKDF2 funkciju, uz random salt, koju smo implementirali u CreateHash metodi, koja za argument uzima string, odnosno lozinku koju je korisnik uneo kod registracije.
public static string CreateHash(string password) { RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider(); byte[] salt = new byte[SaltByteSize]; csprng.GetBytes(salt); byte[] hash = PBKDF2(password, salt, PBKDF2Iterations, HashByteSize); return PBKDF2Iterations + ":" + Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash); }
Nakon uspješne registracije korisnik se može prijaviti u aplikaciju. Unosi svoje korisničko ime, te lozinku, koja se provjerava s hashom koji je spremljen u bazi, kroz metodu ValidatePassword, koja prima dva argumenta, jedan od njih je unesena lozinka, dok je drugi hash lozinke unesenog korisničkog imena. Metoda uspoređuje hash vrijednosti unesene lozinke sa hashom lozinke pohranjene u bazi.
public static bool ValidatePassword(string password, string correctHash) { char[] delimiter = { ':' }; string[] split = correctHash.Split(delimiter); int iterations = Int32.Parse(split[IterationIndex]); byte[] salt = Convert.FromBase64String(split[SaltIndex]); byte[] hash = Convert.FromBase64String(split[PBKDF2Index]); byte[] testHash = PBKDF2(password, salt, iterations, hash.Length); return SlowEquals(hash, testHash); }