Evo jedan primer koda za simetrično šifrovanje 3DES algoritmom. Ako si OOP puritanac možeš da zamotaš sve u neku klasu koja će mcrypt da inicijalizuje u konstruktoru ne zagađujući globalni prostor imena. Ako koristite kod, obratite pažanju na
uvodno upozorenje.
Code (php):$mcrypt_td = NULL;
function encrypt_tripledes
($data, $key) {
global $mcrypt_td;
if(!$mcrypt_td) $mcrypt_td = mcrypt_module_open('tripledes', '', 'ecb', '');
mcrypt_generic_init($mcrypt_td, $key, 0);
$data = base64_encode(mcrypt_generic($mcrypt_td, $data));
mcrypt_generic_deinit($mcrypt_td);
return $data;
}
function decrypt_tripledes
($data, $key) {
global $mcrypt_td;
if(!$mcrypt_td) $mcrypt_td = mcrypt_module_open('tripledes', '', 'ecb', '');
mcrypt_generic_init($mcrypt_td, $key, 0);
// brišemo krajnje \0 dodate u poravnanju
$data = rtrim(mdecrypt_generic($mcrypt_td, base64_decode($data)));
mcrypt_generic_deinit($mcrypt_td);
return $data;
}
Problem ostaje kako zaštititi ključ pošto se isti ključ koristi i za šifrovanje i za dešifrovanje. Džabe šifruješ podatke u bazi ako je dovoljno da napadač koji već nekako ima pristup tim podacima (recimo ukrao rezervnu kopiju od tvog pružaoca hosting) još:
1) uđe u veb aplikaciju i predstavi se kao tvoj klijent
2) uđe u veb server i pokupi ključ
Zato se koriste asimetrični algoritmi, kao što je RSA, koji radi sa parom ključeva. Javni ključ je na serveru i njime se šifruju podaci, ali tajni ključ kojim se oni dešifruju je kod klijenta. Sada napadč mora da uzme bazu sa servera i tajni ključ od klijenta, što je teže za izvesti. Dodatno, programeri koji održavaju aplikaciju i tehničari koji održavaju server sada nemaju pristup ključu, pa ne mogu oni da zloupotrebe podatke.
Generisanje para ključeva može da se uradi na klijentu (tako je po standardima, privatni ključ nikada ne treba da odlazi na server). Ako se odlučimo da je „dovoljno sigurno“ da par generišemo na serveru (pri tome nećemo da čuvamo privatni ključ na serveru) onda je OpenSSL kod:
Za generisanje na klijentu, jedna varijanta je generisanje ključeva iz JavaScripta. Druga varijanta je upotreba nekog posebnog programa ili Java aplet/ActiveX u IE, prednost je što onda oni mogu da koriste ključeve u pametnoj kartici ili ključeve koji postoje na sistemu, ne mora da generiše novi par ključeva.
HTML5 definiše <keygen> tag tako da klijent može da napravi par ključeva o direktno kroz preglednik i pošalje javni ključ serveru. Postoji
uputstvo kako generisati ključ i vratiti sertifikat koji se kasnije koristi za autentifikaciju. Ne znam da li postoji neki JavaScript omotač za šifrovanje privatnim ključem smeštenim u pregledniku i kako on može da se aktivira, to bi bio
nedostajući odgovor na ovo pitanje. Drugo, ne znam ni da li preglednici dopuštaju da se umesto generisanja novog odabere postojeći ključ?
RSA šifrovanje možemo da radimo sa
openssl_public_encrypt() i javnim ključem iz para, dešifrovanje sa
openssl_private_decrypt() i privatnim ključem iz para. Funkcija openssl_public_encrypt() ne vraća tekst, ako se smešta u bazu treba pisati u BLOB ili koristiti
base64_encode().
U jednom prolazu RSA algoritam može da šifruje samo podatke kraće od dužine ključa (u ovom primeru 1024 bitova). Zato se za šifrovanje koristi slučajno generisani ključ, na primer
$newkey = uniqid('tajnideo', true); ili
openssl_pkey_export(openssl_pkey_new()), $newkey); i onda kao ključ koristiš
sha1($newkey, true);. Ovim ključem se podaci šifruju recimo TripleDES-om, a ključ koji je kraći od 1024 bitova (sha1 vraća heš od 160 bita) šifruje RSA algoritmom.
Ako je privatni ključ kod klijenta, ostaje problem i kako dešifrovati podatke. Sigurna varijanta je poslati šifrovani ključ i šifrovane podatke u preglednik i onda JavaScriptom odraditi dešifrovanje, ali to može da bude sporo i malo je nezgodno za korišćenje jer JavaScript podrazumevano nema pristup lokalnim datotekama, pa ni datoteci u kojoj je ključ, a kopiraj-ubaci može da nervira klijenta. Postoje nestandardni načini kako da se
omogući pristup lokalnoj datoteci, pa ako se odlučiš za ovaj put to bi moglo da bude pravo rešenje. Bolja varijanta je da se koriste servisi operativnog sistema kroz pomenuto Java/ActiveX rešenje ili nekako da se kaže pregledniku da dešifruje podatke koristeći ključ u lokalnom skladištu, u čemu ja nemam iskustva
i voleo bih da čujem više.
Ono što sam ja koristio jeste da dodatno privatni ključ napravim na serveru opisanim putem i prethodno provrtim kroz TripleDES sa nekom slučajnom lozinkom (passphrase). Onda pri dešifrovanju podataka dozvolim klijentu da pošalje šifrovani privatni ključ na server zajedno sa passphraseom, dešifrujem privatni ključ i uklonim poslatu datoteku sa servera, dešifrujem slučajan ključ za svaki podatak i dešifrujem podatke.
Takav sistem je ranjiv jer privatni ključ može lako da iscuri ako server nije siguran, ali isto tako napadač koji ima pristup serveru može da presretne i sirove podatke koji stižu iz HTML formulara i potpuno preskoči bilo kakvu dalju zaštitu.
@jablan: Jesi li radio nešto slično? Imaš li savet, predlog, komentar?
Ne znam kako je tvoj klijent do sada pristupao e-pošti i da li je sanduče na istom serveru kao i PHP skripta, ali u opštem slučaju e-pošta je sigurna kao i dopisivanje razglednicama. Koristiti to za prikuplaljanje brojeva kreditne kartice je neodgovorno.
[Ovu poruku je menjao Goran Rakić dana 26.06.2010. u 13:03 GMT+1]
http://sr.libreoffice.org — slobodan kancelarijski paket, obrada teksta, tablice,
prezentacije, legalno bez troškova licenciranja