Sunteți pe pagina 1din 26

1

Laboratorul 4. Securitate n Java


Informaia schimbat prin reea este expus la o serie de riscuri, putnd fi
interceptat, alterat sau impersonificat. Criptarea informaiei utiliznd chei
simetrice sau asimetrice, calcularea digest-urilor mesajelor i semnarea lor, ofer
soluii pentru schimbul privat al informaiei (codificarea mesajelor astfel nct s
devin computational imposibil descifrarea acestora) i asigurarea integritii
informaiei (detectarea mesajelor corupte sau modificate). n cadrul acestui capitol
sunt prezentate soluiile de securizare a informaiei distribuite n cadrul reelelor de
calculatoare folosind tehnologii Java.
1. Suportul arhitectural al securitii oferit de Java
Modelul de securitate oferit de Java reprezint unul dintre punctele sale forte,
fiind ideal pentru dezvoltarea aplicaiilor ce ruleaz n medii distribuite. Modelul
de securitate Java permite protejarea utilizatorilor n faa unor situaii critice
precum rularea local a programelor descrcate din diverse surse. De exemplu,
dac ne gndim c applet-urile Java ruleaz local pe maina utilizatorului n
condiiile n care sursa de provenien a acestora ofer adesea prea puin ncredere,
modelul de securitate trebuie s fie capabil s protejeze utilizatorul n faa
posibilitii descrcrii i rulrii accidentale a unor virui.
Modelul de securitate oferit de Java se bazeaz pe conceptul de sandbox,
o definiie programabil a limitelor de securitate disponibile unui program. Altfel
spus, un program Java poate rula numai n interiorul propriului sandbox. El poate
face orice att timp ct se ncadreaz n limitele de securitate stabilite. De exemplu,
limitele appleturilor Java includ implicit activiti precum:

Citirea sau scrierea pe discul local;
Stabilirea unei conexiuni pe reea cu orice staie, cu excepia staiei de
provenien a respectivului applet;
Crearea de noi procese;
ncrcarea de noi biblioteci dinamice i apelarea direct de metode native.

Prin limitarea anumitor aciuni modelul de securitate Java protejeaz
utilizatorul n faa ostilitii codului rulat. Astfel, un applet ce se execut local i
2
care poate fi descrcat din diverse surse de nencredere ar putea transporta inclusiv
cod de tip virus, ns modelul de securitate face imposibil acest lucru.


Figura 1. Modelul de securitate oferit de Java.

Componentele arhitecturii modelului de securitate Java ce sunt
rspunztoare de limitarea aciunilor aplicaiilor sunt:

Elementele de securitate construite direct la nivel de main virtual (i de
limbaj);
Arhitectura de ncrcare a claselor;
Verificatorul de ncrcare a claselor;
Managerul de securitate i API-ul Java.

Dou dintre componentele arhitecturale Java deosebit de importante pentru
modelul de securitate oferit sunt class loader i security manager.
Accesul unei aplicaii Java la resursele sistemului cum ar fi ecranul, sistemul
de fiiere, procese, fire de execuie, reea sunt controlate de ctre managerul de
securitate. Limitele de securitate ale unei aplicaii Java pot fi controlate prin
specificarea de ctre utilizator a unor noi clase bazate pe managerul implicit
java.lang.SecurityManager. Definirea unui nou manager de securitate implic
suprascrierea de metode declarate n clasa superioar ce au rolul de a decide
permiterea efecturii unor operaii specifice (precum scrierea pe disc). n cadrul
mediului de execuie al aplicaiei un singur obiect de tip SecurityManager poate fi
specificat la un moment dat, accesul la toate resursele sistemului pentru respectiva
aplicaie fiind controlat de metodele respectivului obiect.
Managerul de securitate implicit se poate schimba folosind metoda static a
clasei System, setSecurityManager(). Se poate chiar s specificm c nu dorim s
utilizm deloc un manager prin apelul System.setSecurityManager(null) sau chiar
SECURITATE N JAVA


3
3
s utilizm propriul manager de securitate, apelnd
System.setSecurityManager(new MySecurityManager()), unde MySecurityManag
er reprezint o subclas a clasei SecurityManager.
Un exemplu de clas ce implementeaz un manager de securitate propriu
care nu permite citirea fiierelor cu extensia .java este urmtorul:

class MySecurityManager extends SecurityManager {

public void checkRead(String s) {

if (s.endsWith(".java"))
throw new SecurityException("Access to "+s+" file not allowed");
}
}

public class MyApplication{

public static void typeFile(String filename) throws Exception {

int b;
FileInputStream fin = new FileInputStream(filename);
while( (b = fin.read()) != -1 )
System.out.print( (char) b );
fin.close();
}

public static void main(String args[]) {

System.setSecurityManager(new MySecurityManager());
try{
typeFile(args[0]);
} catch(Exception e) {
System.out.println("Eroare citire fisier "+e );
}
}
}

O alt component important pentru modelul de securitate Java este class
loaderul. Mecanismul de ncrcare a claselor Java are i rolul de a verifica dac
clasele ncrcate ndeplinesc constrngeri de siguran la nivelul limbajului. O
verificare mai adecvat a securitii claselor ncrcate poate fi obinut prin
nlocuirea class loaderului oferit de sistem. De altfel acest mecanism este folosit de
exemplu n cazul ncrcrii appleturilor. Class loaderul pentru appleturi n Java tie
s ncarce clase de pe alte staii i tie s autentifice pachete jar semnate. Acest
class loader utilizeaz spaii de nume diferite pentru clasele locale i pentru clase
provenite de pe reea, pentru a evita conflictul acestora.
Java permite utilizarea unui class-loader definit de utilizator, ce ar putea
chiar fora i mai mult caracteristicile de securitate oferite implicit. Orice class-
loader definit de utilizator trebuie s extind clasa abstract java.lang.ClassLoader
i s redefineasc metoda abtract loadClass(). n general se recomand ca metoda
aceasta s implementeze cel puin urmtoarele aciuni:

4
1. Verific dac clasa indicat prin className este ncrcat. Pentru a putea face
acest lucru trebuie s se in evidena claselor anterior ncrcate.
2. Dac clasa nu este nc ncrcat, verific dac este clas sistem. n caz c nu
este, va ncrca codul octei (din sistemul local de fiiere de exemplu).
3. Apelezeaz metoda defineClass()pentru a prezenta codul octei mainii
virtuale.

Exemplul urmtor ilustreaz modalitatea de definire a unui nou class loader
de ctre utilizator:

public class MyClassLoader extends ClassLoader {
private Hashtable classes = new Hashtable();

protected synchronized Class loadClass( String name, boolean resolve )
throws ClassNotFoundException {

Class cl = (Class) classes.get( name );
if( cl == null ) {
// Se verifica daca este clasa sistem
return findSystemClass( name );
}

// se incarca codul octeti
byte classBytes[] = loadClassBytes( name );
if( classBytes == null ) throw new ClassNotFoundException( name );
cl = defineClass( name, classBytes, o, classBytes.length );
if( cl == null ) throw new ClassNotFoundException( name );
classes.put( name, cl );
if( resolve) resolveClass( cl );
}

private byte[] loadClassBytes( String name ) {

String cname =name.replace('.','/')+".class";
FileInputStream in = null;
try{
in = new FileInputStream( cname );
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int ch;
while( ( ch = in.read()) != -1 )
buffer.write( ch );
return buffer.toByteArray();
} catch( IOException e1) {
if( in != null )
try{
in.close();
} catch( IOException e2 ){}
return null;
}
}
}




SECURITATE N JAVA


5
5
Clasa descris se utilizeaz precum n urmtorul exemplu:

ClassLoader loader = new MyClassLoader();
Class c = loader.loadClass("OClasa");

Java pune la dispoziie i o serie de mecanisme predefinite de securitate ce
opereaz direct la nivelul mainii virtuale:

Type-safe reference casting
Structured memory access (no pointer arithmetic)
Automatic garbage collection (can't explicitly free allocated memory)
Array bounds checking
Checking references for null

Orice apel ctre o referin a unui obiect Java impune declanarea unor
mecanisme de verificare implicite. De exemplu, o referin la un tip de date diferit
rezult ntr-o serie de verificri implicite din partea Java asupra corectitudinii cast-
ului. Accesarea unui array implic verificarea implicit dac indicele cerut se
ncadreaz n limitele respectivului array. Orice astfel de ncercare greit rezult n
aruncarea unor excepii la nivelul mainii virtuale.


Figura 2. Maparea Clase -> Domenii -> Permisiuni.

Un alt concept al sistemului de securitate este reprezentat de domeniul de
protecie. Domeniu de protecie este un mecanism pentru gruparea i izolarea unui
set de clase ale cror instane au impuse anumite permisiuni. Un domeniu de
protecie poate fi limitat de ctre setul de obiecte ce sunt direct accesate de ctre un
principal, o entitate din program creia i se acord anumite drepturi. Astfel este
posibil chiar separarea domeniilor de protecie, a interaciunilor ntre ele, astfel
nct orice interaciune cu anumite rutine aparinnd de diverse domenii de
protecie s poat fi facut numai prin intermediul unor rutine sigure ale sistemului.
6
Domeniile de protecie se mpart n dou categorii: de sistem i de aplicaie. Orice
resurs extern protejat, precum sistemul de fiiere, interfeele de reea, tastatura
sau monitorul, poate fi accesat numai prin domenii de protecie ale sistemului.
Domeniile de protecie sunt determinate de ctre politica de securitate
folosit. Java menine ntotdeauna intern o mapare ntre cod (clase i instane) i
domeniile de protecie i permisiunile curent acordate unor entiti ale aplicaiei
executate.
Un fir de execuie poate executa aciuni doar n interiorul propriului domeniu
de protecie sau n interiorul domeniului de protecie al sistemului (de exemplu o
aplicaie poate afia un mesaj, aciune ce necesit accesarea domeniului de
protecie al sistemului). Ca regul, permisiunile sunt acordate astfel:

Setul de permisiuni acordate unui fir de execuie sunt considerate a fi
intersecia tuturor permisiunilor corespunztoare tuturor domeniilor de
protecie traversate de ctre execuia sa.
Atunci cnd este apelat metoda doPrivileged a clasei AccessController
setul de permisiuni acordate firului de execuie curent va include i o
permisiune acordat de domeniul de protecie al codului.

Metoda doPrivileged acord unei aplicaii drepturi temporare la mai multe
resurse dect sunt disponibile implicit acesteia. Acest aspect este necesar n cteva
situaii excepionale. De exemplu, o aplicaie poate s nu aib acces direct la
fiierele sistemului coninnd setul de fonturi folosite, dar ea trebuie s permit
utilizatorului s aleag dintre fonturile pe care acesta le poate folosi n scrierea unui
document. n acest moment poate fi folosit metoda doPrivileged a domeniului de
sistem. n timpul execuiei unei aplicaii Java, dac este apelat o operaie critic
asupra unei resurse a sistemului (operaie asupra unui fiier de exemplu),
transparent pentru utilizator este apelat n fundal i o metod a clasei
AccessControler ce evalueaz dreptul de execuie al respectivei operaii. n afara
acestui comportament implicit, orice aplicaie poate defini mecanisme suplimentare
de protecie a resurselor interne acesteia. De exemplu, o aplicaie bancar poate
implementa mecanisme interne de protecie a unor resurse precum conturi bancare,
depozite sau retrageri. Domeniul de protecie pentru astfel de aplicaii este
specificat de ctre dezvoltatorii acestora, prin intermediul unor resurse ajuttoare
puse la dispoziie de Java (ntr-o seciune ulterioar vom prezenta clasa
SignedObject de exemplu).
n Java accesul la resurse ale sistemului este specificat prin intermediul unor
clase speciale ce implementeaz java.security.Permission. Un exemplu de folosire
a clasei java.io.FilePermission n scopul acordrii dreptului de a citi fiierul de pe
disc /tmp/abc este urmtorul:

perm = new java.io.FilePermission("/tmp/abc", "read");

SECURITATE N JAVA


7
7
Dezvoltatorii de aplicaii pot specifica noi permisiuni prin extinderea clasei
abstracte de baz java.security.Permission sau extensii ale acesteia, precum
java.security.BasicPermission. O metod important ce trebuie implementat de
ctre noile extensii de clase este implies. Aceast metod este apelat pentru
verificri de tipul a implic b, adic dac a are o anumit permisiune acordat
atunci i b are acordat dreptul respectiv.
Pentru crearea unei noi permisiuni este recomandat parcugerea ctorva pai.
S presupunem c dorim crearea unei noi permisiuni n cadrul dezvoltrii unei
aplicaii Java pentru vizualizare TV. Primul pas va consta n crearea unei noi
clase com.abc.TVPermission, ce extinde clasa abstract java.security.Permission
(sau o subclas a acesteia).

public class TVPermission extends java.security.Permission

Clasa nou creat trebuie inclus n pachetul furnizat mpreun cu aplicaia
dezvoltat. Ulterior, fiecare utilizator ce dorete s adauge aceast permisiune
pentru anumite operaii va trebui s adauge o intrare corespunztoare n fiierul de
politici. Un exemplu de astfel de intrare ce acord dreptul codului provenind de la
http://java.sun.com de a vizualiza canalul 5 este urmtorul:

grant codeBase "http://java.sun.com/" {
permission com.abc.TVPermission "channel-5", "watch";
}

n cadrul aplicaiei, atunci cnd dorim s verificm valabilitatea unei
aplicaii de a executa un anumit cod folosim metoda checkPermission a clasei
AccessController furniznd ca parametru obiectul de tip com.abc.TVPermission,
precum n exemplul urmtor:

com.abc.TVPermission tvperm = new
com.abc.TVPermission("channel-5", "watch");
AccessController.checkPermission(tvperm);

Politica de securitate a sistemului n cadrul unei aplicaii Java, cuprinznd
permisiunile disponibile codului provenind din diverse surse externe, este
reprezentat de ctre o instan a clasei java.security.Policy. Mai exact, o subclas
a acestei clase abstracte. n cadrul unei aplicaii mai multe astfel de obiecte pot fi
definite, dar o singur instan poate fi n funcie n orice moment al ciclului de
via al aplicaiei. De altfel putem afla care este obiectul Policy curent activ prin
apelarea metodei getPolicy i putem oricnd s modificm politica prin apelarea
metodei setPolicy.
Locaia informaiei folosit de obiectul Policy este lsat la latitudinea
aplicaiei Java (pot fi folosite fiiere de configuraie a politicii de securitate de tip
text, fiiere binare serializate sau chiar baze de date). Implementarea de referin a
politicii (cea folosit implicit dac nu specificm nimic la rularea unei aplicaii
8
Java) folosete informaia definit n fiiere statice de configurare. Un astfel de
fiier de configurare a permisiunilor acordate entitilor aplicaiei este codat n
format UTF-8.
Un fiier de configurare conine n esen o list de intrri. El poate conine o
intrare de tip keystore i zero sau mai multe intrri de tip grant. Un keystore
reprezint o baz de date de chei private i de certificate digitale asociate acestora,
precum lanuri de certificate X.509 ce sunt folosite pentru autentificarea unor chei
publice corespondente (detalii despre certificate sunt prezentate n subcapitolul
urmtor). Keystore-ul specificat n fiierul de configurare este folosit pentru a
verifica cheile publice ale semnatarilor specificai n intrrile grant. O intrare
keystore trebuie specificat numai atunci cnd n intrrile grant sunt specificai
semnatari. Sintaxa unei astfel de intrri este urmtoarea:

keystore "some_keystore_url", "keystore_type";

n cadrul exemplului, some_keystore_url desemneaz locaia URL a
fiierului keystore, iar keystore_type specific tipul de keystore folosit (ultimul
argument fiind opional implicit JKS).
Fiecare intrare de tip grant are urmtorul format:

grant [SignedBy "signer_names"] [, CodeBase "URL"]
[, Principal [principal_class_name] "principal_name"]
[, Principal [principal_class_name] "principal_name"] ... {
permission permission_class_name [ "target_name" ]
[, "action"] [, SignedBy "signer_names"];
permission ...
};

De exemplu, urmtoarea politic acord permisiunea a.b.Foo codului semnat
de George:

grant signedBy "George" {
permission a.b.Foo;
};

Urmtorul exemplu specific acordarea permisiunii de citire fiierelor .tmp
ntregului cod (indiferent de semnatarul aplicaiei sau de sursa de provenien a
acesteia):

grant {
permission java.io.FilePermission ".tmp", "read";
};

Urmtorul exemplu specific acordarea a dou permisiuni codului ce este
semnat de Michel i care provine de la http://java.sun.com:

grant codeBase "http://java.sun.com/*", signedBy "Michel" {
SECURITATE N JAVA


9
9
permission java.io.FilePermission "/tmp/*", "read";
permission java.io.SocketPermission "*", "connect";
};

Java mai ofer cteva mecanisme suplimentare de protecie intern. S
presupunem de exemplu un scenariu n care un furnizor de obiecte ruleaz ntr-un
alt fir de execuie dect consumatorul respectivelor obiecte. Pentru astfel de
scenarii poate fi util folosirea unor obiecte de tip GuardedObject ce asigur
protecia accesului la resurse.
Furnizorul de resurse creaz obiectul ce trebuie transmis i creaz i un
obiect GuardedObject ce ncapsuleaz obiectul iniial mpreun cu un obiect Guard
i care este de fapt trimis consumatorului. Consumatorul nu poate obine ulterior
obiectul inclus n ceea ce primete dect dac anumite verificri de securitate sunt
satisfcute. Guard reprezint o interfa i practic orice obiect o poate implementa.
Singura metod a acestei interfee este checkGuard. Metoda primete un obiect i
execut anumite verificri de securitate. Clasa java.security.Permission
implementeaz aceast interfa.
De exemplu, s presupunem c dorim s putem cere unui fir de execuie s
deschid un fiier a/b/c.txt pentru citire, dar nu putem avea ncredere n cine
execut respectiva cerere sau n ce mprejurri (de exemplu, n cazul aplicaiilor
distribuite, putem pune la dispoziie o serie de operaii unor utilizatori...). ntr-un
astfel de context putem folosi un obiect GuardedObject pentru a fora verificri de
control al accesului, dup cum urmeaz:

FileInputStream f = new FileInputStream("/a/b/c.txt");
FilePermission p = new FilePermission("/a/b/c.txt", "read");
GuardedObject g = new GuardedObject(f, p);

n acest moment firul de execuie poate transmite g ctre firul de execuie
consumator, pentru obinerea accesului la f acesta fiind obligat s apeleze:

FileInputStream fis = (FileInputStream) g.getObject();

Metoda aceasta invoc metoda checkGuard a obiectului p, i, doarece p este
de tip Permission, apelul respectiv ajunge s execute:

SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkPermission(this);

Aceasta asigur efectuarea unui control al permisiunilor corespunztor. n
acest fel pot fi implementate diverse politici de control ce pot verifica informaii de
context, precum dreptul execuiei unor operaii n funcie de ora curent sau
identitatea apelantului.

10
2. Suportul pentru securitatea comunicaiilor n Java
2.1. Certificate
Funcia principal a unui certificat este aceea de a asocia unei identiti o
cheie public. Certificatele sunt publice i conin informaie referitoare la subiectul
certificatului (Entitatea care deine certificatul - numele, cu ce organizaie e asociat
acest nume, locaia i ara), cheia public a certificatului, entitatea care a emis acest
certificat i semnatura acesteia. Asocierea cheie-identitate (certificatul) este
recunoscut i garantat de un ter, entitatea care semneaz certificatul i care este
numit Autoritate de Certificare.
Un certificat poate fi obinut printr-o cerere fcut unei Autoriti de
Certificare. Cel care dorete s dein un astfel de certificat va genera local o
pereche de chei, public i privat i va arta cheia public Autoritii de
Certificare care i va creea i semna un certificat coninnd acea cheie public. n
principiu se creaz local o cerere de certificat, de fapt un certificat nesemnat, care
conine identitatea entitii i cheia public, certificat care este trimis Autoritii de
Certificare spre semnare. Autoritatea de Certificare este responsabil s verifice
dac identitatea din certificatul primit aparine celui care a trimis spre semnare
certificatul. De obicei acest proces se face offline, find implicate i chestiuni
legislative. Autoritatea de Certificare asigur integritatea datelor din certificat prin
calcularea unui hash peste ntregul certificat i semnarea hash-ului cu cheia privat
a Autoritii de Certificare (care deine i ea un certificat i o cheie privat asociat).
Dup cum se observ Autoritatea de Certificare trebuie s fie considerat de
ncredere pentru ca asocierea cheie publica - identitate prezent n certificat s fie
viabil. Este uor de imaginat c la nivel global nu se poate stabili o singur
Autoritate de Certificare, att din motive de ncredere ct i de scalabilitate. Astfel
exist un numar de Autoriti de Certificare considerate rdcin. Aceste autoriti
sunt cunoscute i considerate de ncredere, iar certificatele lor (deci i cheia
public) sunt de obicei ncorporate n aplicaiile care fac uz de autentificare prin
certificate. Un certificat semnat de o astfel de Autentificare de Certificare este
considerat (hardcodat) de ncredere, ns de cele mai multe ori Autoritile de
Certificare rdcin nu emit certificate direct utilizatorilor, ci altor Autoriti de
Certificare care pot fi responsabile cu anumite regiuni i care, la rndul lor, ar putea
emite certificate pentru alte Autoriti de Certificare, construindu-se astfel cteva
nivele pn la Autoritile care emit certificate utilizatorilor (a se vedea Figura 5.3).
Un certificat al unui client este verificat pe lanul de semnturi pn ce se
ajunge la o Autoritate de Certificare de ncredere sau se stabilete c un astfel de
lan nu exist, caz n care autentificarea euaz.
ntregul sistem cu entiti care dein/cer certificate i Autoriti de Certificare
poart numele de Infrastructur cu Chei Publice (Public Key Infrastructure - PKI).

SECURITATE N JAVA


11
11

Figura 3. Autoriti de Certificare.

Autentificarea poate fi cerut de ambele entiti care doresc s comunice sau
poate fi pretins numai de una dintre acestea. Principiul este urmtorul: entitatea
care trebuie s se autentifice (A) prezint certificatul deinut (de cele mai multe ori
va prezenta un lan de certificate pn la o Autoritate de Certificare posibil
cunoscut de cealalt parte), cealalt parte (B) verific dac certificatul este de
ncredere i, dac acesta este cazul, genereaz aleator un set de date i cere ca
acestea s fie semnate cu cheia privat pereche a cheii publice din certificatul
prezentat. Dup ce primete datele, B le decripteaz cu cheia public (dezvaluit n
certificatul artat anterior) i dac obine aceeai valoare entitatea A (care a
prezentat certificatul) este considerat deintoarea de drept a acestuia, deci avnd
identitatea din certificat.


Certificatele n formatul X.509 sunt un standard ITU-T pentru Infrastructura
cu Chei Publice. Un certificat X.509 conine cel puin urmtoarele date:

Versiunea. Exist trei versiuni de certificate X.509 v1, v2 i v3.
Numr Serial. Identific certificatul i trebuie s fie unic ntre certificatele
semnate de Autoritatea de Certificare care emite i certificatul curent
(numrul serial i numele emitentului identific unic un certificat).
Algoritm de Semnare.
Emitent. Numele emitentului n format X.500 (n general o Autoritate de
Certificare).
12
Perioada de Valabilitate. Data cnd certificatul devine valabil i data
cnd acesta expir.
Subiectul. Numele celui care deine certificatul (poate fi n format X.500
sau ntr-un alt format - ex. URL).
Cheia Publica.
Semnatura Emitentului.

Numele n format X.500 conin cteva cmpuri care ofer informaii
suplimentare despre entitatea respectiv. n format X.500 pot aprea urmtoarele
atribute:

Common Name CN Numele deintorului.
Organization O Organizaia cu care este asociat numele.
Organization Unit OU Unitatea din cadrul organizaiei.
Country C ara.

Certificatele X.509 v1 au aprut n 1988 i au utilizat formatul X.500 pentru
reprezentarea emitentului i subiectului unui certificat. X.509 v2 a introdus
conceptul de identificatori unici pentru subiect i emitent pentru a se putea reutiliza
aceste nume, ns aceast propunere a fost controversat i cele mai multe
recomandri referitoare la certificate sunt mpotriva refolosirii numelor.
Certificatele X.509 v2 au continuat s utilizeze formatul X.500 de reprezentare a
numelor. Certificatele X.509 v3 sunt cele mai recente, fcndu-i apariia n anul
1996. Noutatea adus este prezena extensiilor, care pot fi definite i incluse n
certificate (semnatura certificatului este calculat i peste aceste extensii).
Extensiile permit ca un certificat v3 s cuprind i alte informaii pe lng
identitatea deintorului (ex. atribute ale deintorului). O serie de extensii sunt deja
definite i acceptate ca atare (Utilizare Cheii KeyUsage specific scopul n care
poate fi utilizat cheia din certificat, Nume Alternative AlternativeNames
pentru a asocia i alte nume cu cheia public din certificat etc.) altele pot fi definite
de utilizatori. Aceste extensii pot fi marcate ca fiind critice sau necritice. O
extensie critic ar trebui verificat i utilizat/interpretat de aplicaia care primete
certificatul respectiv, ns aceasta depinde de conveniile i modul de funcionare al
aplicaiei. n plus certificatele n format v3 nu oblig reprezentarea n format X.500
a subiectului sau a emitentului putndu-se utiliza nume generice.

n Java mecanismele de securitate sunt legate de noiunea de keystore, fiiere
coninnd chei i certificate. Un keystore poate conine dou tipuri de intrri:
certificate de ncredere i mapri cheie/certificat, fiecare astfel de intrare coninnd
o cheie privat i certificatul corespunztor semnat cu cheia public. Fiecare intrare
din keystore este identificat printr-un un alias.
Certificatele care sunt folosite n cadrul setrii unor sesiuni de comunicaie
sigure sunt citite din keystore-ul furnizat la rularea aplicaiei, iar la recepie
SECURITATE N JAVA


13
13
certificatele sunt verificate contra certificatelor coninute n fiiere trustore.
Instrumentul pentru crearea de keystore-uri i trustore-uri este keytool. Paii pentru
crearea unui keystore i a unui trustore sunt urmtorii: se pornete cu crearea unui
keystore, din acest keystore se export un certificat ce este importat ntr-un trustore,
keystore-ul rmne folosit local iar trustore-ul este furnizat aplicaiei remote.
Crearea unei noi perechi de chei (public i privat) i a unui certificat
pentru un subiect Duke, folosind algoritmul DSA se poate face astfel:

> keytool -genkey -alias alias -keystore .keystore
Enter keystore password: password
What is your first and last name?
[Unknown]: Duke
What is the name of your organizational unit?
[Unknown]: JavaSoft
What is the name of your organization?
[Unknown]: Sun
What is the name of your City or Locality?
[Unknown]: Cupertino
What is the name of your State or Province?
[Unknown]: CA
What is the two-letter country code for this unit?
[Unknown]: US
Is <CN=Duke, OU=JavaSoft, O=Sun, L=Cupertino, ST=CA, C=US> correct?
[no]: yes

Dac se dorete folosirea algoritmului RSA pentru creare se poate folosi:

> keytool -genkey -keyalg RSA -keysize 1024 -alias alias -keystore .keystore

Exportarea unui certificat din keystore se poate face astfel:

> keytool -storepass my-keystore-password -alias myalias -export -file
outfilename.cer

Importarea unui certificat dintr-un fiier se poate realiza folosind:

> keytool -storepass my-keystore-password -alias myalias -import file
infilename.cer

Paii de creare a unei perechi keystore-trustore de certificate semnate de un
CA sunt astfel urmtorii:

Setarea CA-ului
-----------------------------------

Pasul 1. Se instaleaz openssl local (sursele sau binarele sunt disponibile
la www.openssl.org).

Pasul 3. Se genereaz o cheie privat (ca.key) i o cerere de certificat
(ca.csr) pentru CA:

openssl req -new -newkey rsa:1024 -nodes -out ca.csr keyout ca.key
14

Pasul 4. Se creaz certificatul semnat de propriul CA ca.pem (n exemplu
perioada de validitate a certificatului va fi de un an):

openssl x509 -trustout -signkey ca.key -days 365 -req in ca.csr -out ca.pem

Pasul 5. Se import certificatul CA-ului n keystore-ul coninnd
certificate autorizate JDK:

keytool -import -keystore $JAVA_JOME/jre/lib/security/cacerts -file
ca.pem -alias my_ca

Pasul 6. Se creaz un fiier ce va conine numerele seriale ale CA-ului
ca.srl, ca n exemplul:

echo "02" > ca.srl

Creare keystore i trustore
----------------------------------------------------

Pasul 7. Se creaz un keystore keystore.ks.

keytool -genkey -alias student -keyalg RSA -keysize 1024 -keystore
keystore.ks -storetype JKS

Pasul 8. Se creaz o cerere de certificat keystore.csr ce este trimis CA-
ului.

keytool -certreq -keyalg RSA -alias student file keystore.csr -keystore
keystore.ks

Fiierul keystore.csr trebuie modificat dintr-ul editor text. Se nlocuiete
textul NEW CERTIFICATE REQUEST cu CERTIFICATE REQUEST

Pasul 9. Semnarea cererii de ctre CA cu generarea fiierului keystore.crt:

openssl x509 -CA ca.pem -CAkey ca.key Caserial ca.srl -req -in keystore.csr
out keystore.crt -days 365

Pasul 10. Importarea certificatului semnat n keystore:

keytool -import -alias student keystore keystore.ks -trustcacerts -file
keystore.crt

Execuia comenzii va genera un mesaj Certificate reply was installed in
keystore.

Pasul 11. Importarea certificatului CA n keystore:

keytool -import -alias my_ca keystore keystore.ks -trustcacerts -file
ca.pem

Acest pas este necesar numai dac se dorete folosirea autentificrii din
partea clientului.

Pasul 12. Exportarea certificatului din keystore (opiunea rfc genereaz un
certificat printabil) n keystore.cer:

keytool -export -rfc -alias student -file keystore.cer -keystore keystore.ks
-storepass JKS
SECURITATE N JAVA


15
15

Pasul 13. Importarea certificatului ntr-un trustore:

keytool -import -alias student -file keystore.cer -keystore trustore.ks
2.2. SSL
De multe ori se pune problema realizrii unor comunicaii sigure,
confideniale, astfel nct mesajele schimbate s nu poat fi descifrate. SSL (Secure
Socket Layer) este un protocol de securitate care ofer aceste caliti. Prin
intermediul su se poate asigura confidenialitate, integritatea mesajelor i
autentificarea prilor. SSL acioneaz peste un flux TCP i ofer servicii nivelelor
superioare. Protocolul HTTP poate fi utilizat peste SSL i n acest caz este numit
HTTPS (Secure Hyper Text Transfer Protocol). HTTPS funcioneaz pe acelai
principiu cu HTTP, diferena constnd n criptarea mesajelor schimbate ntre un
server web i un browser i n posibilitatea autentificrii att a serverului ct i a
clientului. SSL este ns un protocol general care poate oferi servicii oricrui
protocol de nivel aplicaie.
Protocolul SSL este format din dou etape: handshake i transfer. n timpul
handshake-ului clientul i serverul stabilesc un set de algoritmi pentru realizarea
criptrii, stabilesc cheile care vor fi utilizate i se autentific. Doar autentificarea
serverului este obligatorie, cea a clientului fiind opional. Dup ncheierea
handshake-ului, n cea de-a doua faz, transferul, datele sunt sparte n blocuri de
dimensiuni mai mici (opional pot fi i compresate) protejate pentru garantarea
integritii i criptate dup care are loc transmisia propriu-zis pe reea.

EXEMPLUL 1. Pentru exemplificare, prezentm modul de construcie
a unei aplicaii client-server ce folosesc SSL pentru schimbul de
informaii.

Un server SSL necesit specificarea unor certificate ce sunt prezentate
clienilor n procesul de autentificare. n Java certificatele sunt citite din fiiere de
tip keystore ale cror locaii trebuie s fie explicit specificate (nu exist locaie
implicit).
Crearea unui server SSL este ilustrat n exemplul urmtor. Dup cum se
poate observa, Java uureaz sarcina dezvoltatorului prin furnizarea clasei
SSLServerSocketFactory. Crearea unui ServerSocket pregtit pentru comunicaia
folosind SSL se realizeaz apelnd metoda createServerSocket a acestei clase
ajuttoare. Modul de folosire a unui astfel de server este cel obinuit, prin folosirea
metodelor accept, getInputStream sau getOutputStream. Practic, n afar de modul
diferit de construcie a instanei, nimic nu trdeaz c vorbim de o comunicaie mai
special.

16
try {
int port = 443;
ServerSocketFactory ssocketFactory = SSLServerSocketFactory.getDefault();
ServerSocket ssocket = ssocketFactory.createServerSocket(port);

// acceptam noi conexiuni
Socket socket = ssocket.accept();

// crearea stream-urilor de date
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();

// diverse operaii de transfer...

// inchiderea conexiunii
in.close();
out.close();
} catch(IOException e) { }

La rularea aplicaiei server trebuie specificat i numele fiierului keystore
folosit. Specificarea fiierului keystore coninnd certificatele de folosit se poate
specifica folosind proprietatea javax.net.ssl.keyStore, rularea aplicaiei server fiind
efectuat astfel:

> java -Djavax.net.ssl.keyStore=mySrvKeystore -
Djavax.net.ssl.keyStorePassword=123456 MyServer

Codul corespunztor aplicaiei client ce folosete SSL este prezentat n
urmtorul exemplu. Din nou, folosim o clas ajuttoare, SSLSocketFactory, ce
ascunde detaliile de implementare ale unui socket ce vorbete protocolul SSL.
De aceast dat ns vedem o serie de metode noi. Dup stabilirea conexiunii
clientul trebuie s apeleze metoda startHandshake pentru a iniia primul pas n
stabilirea conectivitii. Fr apelarea aceastei metode o operaie de transfer ar
arunca exceptie. Operaia se termin odat cu finalizarea handshake-ului (dac
autentificarea nu reuete se arunc excepie). Ulterior se poate continua cu
transferul datelor n form sigur, precum este prezentat n exemplu.

try {
int port = 443;
String hostname = "hostname";
SocketFactory socketFactory = SSLSocketFactory.getDefault();
Socket socket = socketFactory.createSocket(hostname, port);

// conectarea la server declansarea handshakeului
socket.startHandshake();

// regasirea lantului de certificate prezentate de server
java.security.cert.Certificate[] serverCerts =
socket.getSession().getPeerCertificates();

// crearea streamurilor de comunicatie
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
SECURITATE N JAVA


17
17

// diverse operatii de citire/scriere...

// inchiderea socketilor
in.close();
out.close();
} catch(IOException e) { }

n cadrul exemplui se poate observa i modalitatea prin care clientul poate
obine informaii privind identitatea prezentat n certificatul folosit de server n
procesul de autentificare. Atunci cnd un client SSL se conecteaz la un server SSL
primete un certificat de autentificare din partea serverului. Clientul trebuie s
valideze certificatul prin compararea acestui cu un set de certificate coninute n
propriul trustore. Fiierul trustore implicit este <java-home>/lib/security/cacerts.
Dac certificatul prezentat de server nu poate fi validat contra certificatelor din
trustore, certificatul serverului trebuie s fie adugat n trustore nainte ca
conexiunea s poat fi stabilit. Un alt fiier trustore poate fi specificat folosit
proprietatea javax.net.ssl.trustStore , rularea aplicaiei anterior prezentate fcndu-
se astfel:

> java -Djavax.net.ssl.trustStore=truststore -
Djavax.net.ssl.trustStorePassword=123456 MyApp

n cadrul listingului example1 este prezentat un exemplu mai amplu de
aplicaie client/server ce folosete de aceast dat TLS ca protocol de autentificare.
n cadrul exemplului se demonstreaz i modalitatea de construcie a unui manager
de certificate propriu utilizatorului, manager ce este folosit n pasul de stabilire a
identitii celor dou entiti participante (server i client). Codul corespunztor
serverului responsabil de setarea corespunztoare a canalelor de comunicaie este
urmtorul:

public SSLServerSocket createServerSocket(int port, String keystore, String
password) throws IOException {

SSLServerSocketFactory ssf = null;
SSLServerSocket ss = null;
try {
SSLContext ctx = SSLContext.getInstance("TLS");
KeyManagerFactory kmf =
KeyManagerFactory.getInstance( KeyManagerFactory.
getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream is = new FileInputStream(keystore);
ks.load(is, password.toCharArray());
kmf.init(ks, password.toCharArray());
ctx.init(kmf.getKeyManagers(), null, new
java.security.SecureRandom());
ssf = ctx.getServerSocketFactory();
ss = (SSLServerSocket) ssf.createServerSocket();
ss.bind(new InetSocketAddress(port));
ss.setNeedClientAuth(false);
} catch (Throwable t) {
18
t.printStackTrace();
throw new IOException(t.getMessage());
}
return ss;
}

Exemplul demonstreaz o modalitate de ncrcare dinamic a certificatelor
ce sunt folosite n etapa de stabilire a identitilor participanilor la comunicaie.
Acest lucru se realizeaz folosind clasele KeyManagerFactory i KeyStore. Crearea
contextului de securitate se realizeaz n cadrul exemplului folosind clasa
SSLContext (ce poate fi instaniat, precum n cadrul exemplului, cu specificarea
folosirii protocolului TLS). Dup cum s-a prezentat i n exemplul anterior, un
SSLServerSocket se poate obine plecnd de la o instan SSLServerSocketFactory,
care poate fi cea implicit (SSLServerSocketFactory.getDefault) sau poate fi
obinut dintr-un context (ssf=ctx.getServerSocketFactory()). Metoda
setNeedClientAuth este important, ea specificnd dac n etapa de handshake este
necesar ca i clientul s prezinte sau nu propriul certificat.

Codul corespunztor clientului este urmtorul:

public void createSSLConnection (String address, int port) throws Exception{

String store=System.getProperty("KeyStore");
String passwd =System.getProperty("KeyStorePass");
char[] storepswd = passwd.toCharArray();
SSLContext ctx = SSLContext.getInstance("TLS");
KeyManagerFactory kmf =
KeyManagerFactory.getInstance( KeyManagerFactory.
getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(store), storepswd);
kmf.init(ks,storepswd);
ctx.init(kmf.getKeyManagers(), new TrustManager[] {new
CustomTrustManager()}, null);
SSLSocketFactory ssf = ctx.getSocketFactory();
s = (SSLSocket)ssf.createSocket();

s.connect(new InetSocketAddress(address, port));

pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}

Setarea contextului este similar celei prezentate n cazul serverului. O
construcie diferit este prezentat de iniializarea contextului (metoda init a clasei
SSLContext). n cadrul exemplului este folosit o clas CustomTrustManager ce
implementeaz interfaa X509TrustManager.
3. Criptare n Java
SECURITATE N JAVA


19
19
Pachetul Java Cryptography Extension (JCE) este inclus n JDK ncepnd de
la versiunea 1.4. Supportul JCE pentru criptare include:

Symmetric bulk encryption (DES, RC2, and IDEA)
Symmetric stream encryption (RC4)
Asymmetric encryption (RSA)
Password-based encryption (PBE)
Key Agreement
Message Authentication Codes (MAC)

Bouncy Castle (BC) este un toolkit care ofer o implementare lightweight
pentru JCE 1.2.1 i este compatibil cu Java Micro Edition (J2ME), astfel nct
reprezint soluia cea mai bun pentru un API cryptografic pentru dispozitive
mobile care ruleaz Java.

EXEMPLUL 2. Prezentm un exemplu de aplicaie pentru
criptarea/decriptarea unui ir de date folosind algoritmul DES (chei
simetrice).

Pentru exemplificarea modului de folosire a mecanismelor de criptografie
puse la dispoziie de Java prezentm urmtorul exemplu (a se vedea i listingul
example2):

Key key;
try {
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("SecretKey.ser"));
key = (Key)in.readObject();
in.close();
} catch (FileNotFoundException fnfe) {
KeyGenerator generator = KeyGenerator.getInstance("DES");
generator.init(new SecureRandom());
key = generator.generateKey();
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("SecretKey.ser"));
out.writeObject(key);
out.close();
}

// Get a cipher object.
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

// Encrypt or decrypt the input string.
if (args[0].indexOf("e") != -1) {
cipher.init(Cipher.ENCRYPT_MODE, key);
String amalgam = args[1];
for (int i = 2; i < args.length; i++)
amalgam += " " + args[i];
byte[] stringBytes = amalgam.getBytes("UTF8");
byte[] raw = cipher.doFinal(stringBytes);
20
BASE64Encoder encoder = new BASE64Encoder();
String base64 = encoder.encode(raw);
System.out.println(base64);
}
else if (args[0].indexOf("d") != -1) {
cipher.init(Cipher.DECRYPT_MODE, key);
BASE64Decoder decoder = new BASE64Decoder();
byte[] raw = decoder.decodeBuffer(args[1]);
byte[] stringBytes = cipher.doFinal(raw);
String result = new String(stringBytes, "UTF8");
System.out.println(result);
}

Exemplul poate fi rulat folosind ant run sau folosind:

C:\java SecretWriting -e Hello, world!
Lc4WKHP/uCls8mFcyTw1pQ==
C:\java SecretWriting -d Lc4WKHP/uCls8mFcyTw1pQ==
Hello, world!

i are ca rezultat criptarea (dac se furnizeaz opiunea e) sau decriptarea (dac se
specific opiunea d) unui text de intrare.

n Java orice operaie de criptare/decriptare se folosete de un obiect Cipher.
Dup cum se poate observa n exemplul anterior, un astfel de obiect Cipher se
folosete n conjuncie cu o cheie. n cadrul exemplului se ncearc deserializarea
cheii dintr-un fiier sau, dac operaia eueaz, se ncearc generarea unei noi chei.
Un obiect KeyGenerator este folosit pentru generarea cheii. Un KeyGenerator se
obine prin folosirea unei metode adecvate, n funcie de tipul de algoritm de
criptare pe care dorim s l folosim: KeyGenerator generator =
KeyGenerator.getInstance("DES"); (aici se ncearc obinerea unei chei
corespunztoare algoritmului DES Data Encryption Standard). Un generator de
chei trebuie s fie iniializat n prealabil cu un numr aleator pentru a produce o
nou cheie: generator.init(new SecureRandom()). Dup obinerea cheii, se continu
cu obinerea unui cifru folosind un algoritm corespunztor: Cipher cipher =
Cipher.getInstance("DES/ECB/PKCS5Padding"). Apelul acesta specific c dorim
s folosim algoritmul DES i civa parametrii suplimentari necesari acestuia. n
finalul exemplului se poate observa modul n care se realizeaz criptarea sau
decriptarea datelor.
n Java toate operaiile criptografice sunt structurate conform diagramei
urmtoare:

SECURITATE N JAVA


21
21

Figura 4. Mecanismul criptografic folosit pentru criptare/decriptare.

n centrul arhitecturii st algoritmul criptografic folosit (engine). Algoritmul
primete un set de date de intrare i opional o cheie i produce un set de date de
ieire. Algoritmii criptografici existeni depind de providerii de securitate instalai
n sistem. JCE de exemplu vine cu un provider de securitate suplimentar fa de ce
exist instalat n JDK ce include implementrile algoritmilor criptografici suportai.
n Java se pot instala mai muli provideri de securitate n afar de cel instalat
implicit de catre JCE. Exemplul urmtor instaleaz provider-ul oferit de Bouncy
Castle care se numeste BC.

import java.security.Provider;
import java.security.Security;
import java.util.Set;
import java.util.Iterator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class ProviderInformation {

public static void main(String[] args) {
Security.addProvider(new BouncyCastleProvider());
Provider[] providers = Security.getProviders();
for (int i = 0; i < providers.length; i++) {
Provider provider = providers[i];
System.out.println("Provider name: " + provider.getName());
System.out.println("Provider information: " + provider.getInfo());
System.out.println("Provider version: " + provider.getVersion());
Set entries = provider.entrySet();
Iterator iterator = entries.iterator();
/*while (iterator.hasNext()) {
System.out.println("Property entry: " + iterator.next());
}*/
}
}
}

Implicit pentru toi algoritmii criptografici se folosete primul provider care
apare n outputul programului de mai sus. Dac se dorete folosirea unui anumit
provider se specific explicit numele acestuia, de exemplu BC pentru Bouncy
Castle, precum n exemplul urmtor:

Signature sign = Siganture.getInstance("SHA1WithDSA", "BC");
22

n Java conceptul de cheie este modelat de interfaa java.security.Key. O
implementare de cheie depinde de tipul de algoritm de criptare folosit. Exist de
altfel dou interfee adiionale ce sunt folosite pentru specificarea cheilor n cazul
algoritmilor asimetrici: PublicKey i PrivateKey. Poate prea suprinztor, ns n
JDK nu exist mai departe nici o clas care s implementeze oricare dintre aceste
interfee (din raiuni de securitate). JCE furnizeaz un concept suplimentar fa de
JDK, noiunea de cheie secrete. O cheie secret reprezint o cheie ce este partajat
ntre dou entiti n timpul unei operaii criptografice. Cheile secrete pot fi fie
simetrice, fie asimetrice. Cheile asimetrice se folosesc de cele dou interfee
anterior prezentate, n timp ce cheile simetrice implementeaz interfaa
javax.crypto.SecretKey.
O clas ce este folosit pentru gestiunea cheilor asimetrice este
java.security.KeyPair. Clasa reprezint o structur de date simpl ce conine dou
informaii importante: o cheie public i o cheie privat. Clasa poate fi folosit att
pentru ncapsularea unor chei, ct deopotriv ea este folosit de ctre generatorul
de chei Java. Generarea cheilor asimetrice se face folosind clasa
java.security.KeyPairGenerator. Clasa, abstract de altfel, este apelabil prin
metodele statice getInstance puse la dispoziie, metode ce primesc ca argumente
cel puin un algoritm de folosit. Dup iniializare i nainte de generearea perechii
de chei este recomandat folosirea metodei initialize pentru iniializarea
corespunztoare a generatorului de numere aleatoare. n final generarea cheilor se
realizeaz prin metoda generateKeyPair, precum n exemplul urmtor:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair();

Pentru cheile simetrice JCE introduce mecanisme suplimentare de generare a
acestora: clasele KeyGenerator i SecretKeyFactory. Clasa KeyGenerator, folosit
pentru generarea cheilor secrete simetrice, are o funcionalitate similar celei a
clasei KeyPairGenerator. Diferena major const n apelarea metodei
generateKey ce rezult n returnarea unui obiect de tip SecretKey. A doua clas,
SecretKeyFactory, convertete o specificaie de cheie algoritmic sau codat n
obiecte cheie concrete. Clasa aceasta are un omolog pentru chei asimetrice n clasa
KeyFactory. Un exemplu de folosire a acestei clase pentru exportarea pe disc a
unei chei si, respectiv, importarea de pe disc a unei chei, este prezentat n listingul
example3.
n plus utilizatorul are posibilitatea de a defini proprii mecanisme de
criptografie. De exemplu, utilizatorul poate implementa o cheie secret proprie
bazat pe operaia XOR precum n exemplul urmtor:

public class XORKey implements SecretKey {

byte value;
SECURITATE N JAVA


23
23

public XORKey(byte b) {
value = b;
}

public String getAlgorithm() {
return "XOR";
}

public String getFormat() {
return "XOR Special Format";
}

public byte[] getEncoded() {
byte b[] = new byte[1];
b[0] = value;
return b;
}
}

O astfel de clas poate fi folosit n conjuncie cu un generator de chei
propriu utilizatorului ce poate fi definit conform exemplului urmtor (pentru
exemplul complet se poate consulta listingul example5):

public class XORKeyGenerator extends KeyGeneratorSpi {

SecureRandom sr;

public void engineInit(SecureRandom sr) {
this.sr = sr;
}

public void engineInit(AlgorithmParameterSpec ap, SecureRandom sr)
throws InvalidAlgorithmParameterException {
throw new InvalidAlgorithmParameterException(
"No parameters supported in this class");
}

public SecretKey engineGenerateKey() {
if (sr == null)
sr = new SecureRandom();
byte b[] = new byte[1];
sr.nextBytes(b);
return new XORKey(b[0]);
}
}

Algoritmul de criptografie este implementat prin intermediul clasei
javax.crypto.Cipher. Clasa furnizeaz o interfa pentru criptarea sau decriptarea
att a unor iruri de date locale, ct i pentru obinerea unor streamuri de date de
criptare/decriptare. Numele algoritmilor funizai la iniializarea acestei clase difer
de cei folosii la generarea cheilor de criptografie n sensul c se specific, pe lng
numele algoritmului folosit, i o serie de parametrii specifici funcionrii
respectivului algoritm: padding la nivelul acestei clase se lucreaz numai cu
valori multipli de 8 octei i modul de operare (pentru mai multe detalii legate de
24
diferitele moduri de operare a se vedea documentaia oficial JCE). Un exemplu de
folosire a acestei clase cu iruri de date locale am vzut anterior. De asemenea, n
cap5/example4 este prezentat un exemplu de folosire a PBE. Password-Based
Encryption (PBE) creaz o cheie de criptare dintr-o parol. Pentru a minimaliza
ansele ca un atacator s ghiceasc parola prin for brut, implementrile de PBE
folosesc n plus un numar aleator (salt) pentru a crea cheia. Ca exemplu, pe orice
sistem Unix care are pachetul openssl instalat se pot realiza scripturi care s
realizeze PBE:

Pentru criptare folosind idea-cbc:
>openssl enc -idea-cbc -e -in plaintext_filename -out ciphertext_filename

Pentru decriptare:
>openssl enc -idea-cbc -d -in ciphertext_filename

n exemplul prezentat la nceputul subcapitolului se poate observa
modalitatea de folosire a clasei Cipher pentru criptarea unor variabile locale.
Acelai aspect este reliefat i n exemplul de criptare folosind parol (algoritmul
PBE). O alt modalitate de folosire a clasei Cipher este legat de contruirea unor
stream-uri de date ce automatizeaz criptarea/decriptarea datelor pe msur ce
acestea sunt scrise n fiier, respectiv citite din fiier. Un exemplu de criptare a
datelor folosind clasa CipherOutputStream, clas ajuttoare pentru criptarea datelor
ntr-un stream de comunicaie, este prezentat n continuare:

public class Send {

public static void main(String args[]) {
try {
KeyGenerator kg = KeyGenerator.getInstance("DES");
kg.init(new SecureRandom());
SecretKey key = kg.generateKey();

Cipher c = Cipher.getInstance("DES/CFB8/NoPadding");
c.init(Cipher.ENCRYPT_MODE, key);
CipherOutputStream cos = new CipherOutputStream( new
FileOutputStream("ciphertext"), c);
PrintWriter pw = new PrintWriter( new OutputStreamWriter(cos));
pw.println("Stand and unfold yourself");
pw.close();

SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
Class spec = Class.forName("javax.crypto.spec.DESKeySpec");
DESKeySpec ks = (DESKeySpec) skf.getKeySpec(key, spec);
ObjectOutputStream oos = new ObjectOutputStream( new
FileOutputStream("keyfile"));
oos.writeObject(ks.getKey());
oos.writeObject(c.getIV());
oos.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
SECURITATE N JAVA


25
25

n cadrul exemplului se ncepe prin crearea unei chei secrete, folosind
algoritmul DES i clasa KeyGenerator. Ulterior este instaniat clasa Cipher cu
specificarea comportrii algoritmului DES i este iniializat cu modul de lucru
(criptare n acest caz, specificat prin parametrul Cipher.ENCRYPT_MODE) i
cheia de folosit. Clasa CipherOutputStream este apoi iniializat peste un alt stream
de ieire i pe baza obiectului Cipher anterior creat. Astfel, intern, orice dat ce va
fi trimis a fi scris pe streamul de ieire va fi trecut prin Cipher, deci prin
algoritmul de criptare. Ultimul pas, scrierea n fiierul keyfile, demonstreaz o
modalitate prin care putem transmite cheia de criptografie destinaturului, persoanei
ce va realiza decriptarea, prin intermediul unui fiier. Acest pas este necesar n
cazul unor algoritmi, cum este i cazul algoritmului DES, unde nu putem genera o
aceeai cheie pentru decriptare n mod automat, decriptarea necesitnd existena
informaiei legat de cheia de criptare.
n listingul example4 se poate consulta un exemplu n care criptm un text
pornind de la o parol text, caz n care nu aveam nevoie de cheie, aceasta putnd fi
ntotdeauna unic generat pornind de la textul parol cunoscut.
Funcionalitatea invers, decriptarea datelor pe care le-am scris n fiier
folosind tot un stream de date, de data aceasta de intrare, se realizeaz precum n
exemplul urmtor:

public class Receive {

public static void main(String args[]) {
try {
ObjectInputStream ois = new ObjectInputStream( new
FileInputStream("keyfile"));
DESKeySpec ks = new DESKeySpec((byte[]) ois.readObject());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey key = skf.generateSecret(ks);
Cipher c = Cipher.getInstance("DES/CFB8/NoPadding");
c.init(Cipher.DECRYPT_MODE, key,
newIvParameterSpec((byte[]) ois.readObject());
CipherInputStream cis = new CipherInputStream( new
FileInputStream("ciphertext"), c);
cis.read(new byte[8]);
BufferedReader br = new BufferedReader( new
InputStreamReader(cis));
System.out.println("Got message: "+br.readLine());
ois.close();
br.close();
} catch (Exception e) {
System.out.println(e);
}
}
}

Ca o regul de securizare a aplicaiilor, n general este indicat ca parolele s
fie inute n memorie nu ca String, ci ca array de caractere, i trebuie suprascrise cu
zero imediat dup folosire pentru a preveni memory sau disk snooping. De
26
exemplu, informaia ar putea s fie citit uor atunci cnd maina este obligat s
fac swapping. De asemenea, atunci cnd se serializeaz obiecte este indicat
folosirea cuvntului cheie transient pentru ca informaia de pe aceste canale s nu
fie trimis n streamul de date.
4. Aplicaie practic
V propunem scrierea unei aplicaii client-server n care clientul
decripteaz dintr-un fiier un text, realizeaz o conexiune SSL cu
serverul i i trimite acestuia irul anterior citit din fiier. Pentru
realizarea acestei aplicaii parcurgei paii:

Task1.
Porninnd de la listingul example4 i explicaiile prezentate n subcapitolul 3,
realizai un program care citete parola de la tastatur i realizeaz decriptarea unui
text dintr-un fiier. Pentru crearea fiierului coninnd textul criptat folosii
exemplul prezentat n cadrul clasei PBEnc.

Task2.
Creai un keystore coninnd un certificat propriu semnat de ctre un CA.
Realizai crearea unui trustore pe baza fiierului keystore obinut anterior. Pentru
mai multe informaii consultai subcapitolul 2.

Task3.
Realizai o aplicaie client-server ce comunic folosind un canal de
comunicaie securizat cu protocolul SSL (lsai setNeedClientAuth(false)). Folosii
n acest scop fiierele keystore i trustore create n task-ul anterior. Consultai
detaliile certificatelor primite n procesul de handshake. Trimitei din partea
clientului mesajul decriptat din fiier i afiai-l la recepie pe partea serverului.
Pentru detalii de implementare consultai subcapitolul 2.

S-ar putea să vă placă și