Vedúci diplomovej práce: Ing. Peter Matuška
December
diplomová práca
Bc. Pavol Markovič
Fakulta elektrotechniky a informatiky
Slovenskej technickej univerzity v Bratislave
Prehlasujem a vlastnoručným podpisompotvrdzujem, že som túto diplomovú prácu
vypracoval samostatne.
ANOTÁCIA
Slovenská technická univerzita v Bratislave
Študijný odbor:
Autor: .
Diplomová práca:
Vedúci diplomovej práce: .
December,
Napriek tomu, že databázové systémy prešli dlhú cestu z výpočtových miestností
sálových počítačov do bežných domácností, bezpečnosť údajov zostáva jedným
z najviac skúmaných problémov. Dlhú dobu sa pozornosť vedcov sústreďovala na
problematiku riadenia prístupu k údajom, ale v súčasnosti sa s nástupom malých jed-
noužívateľských systémov objavuje potreba riešenia problémov, ktoré sa v minulosti
iba čiastočne vyriešili. Táto práca sa snaží nájsť jednoduchú, ale zároveň bezpečnú
metódu šifrovania údajov, ktorá by sa mala dať implementovať do systému
– jedného z malých databázových systémov postavených na jazyku Java. Za najvhod-
nejšiu metódu bolo vybrané šifrovanie jednotlivých polí, s ohľadom na ďalší možný
vývoj, najmä komponentového riešenia bezpečnosti. Zároveň je tento systém podro-
bený analýze z hľadiska výkonu a možných útokov na jeho bezpečnosť.
ANNOTATION
Slovenská University of Technology Bratislava
Degree Course:
Author: .
Th esis:
Supervisor: .
December,
Database systems have made a long journey from mainframe’s computing halls
towards commond households, still the data security is one of today’s most inves-
tigated problems. For a long time it was data access control which has taken much
of the researcher’s interest. But now with coming of small single-user systems we
need solution for problems which have been only partially solved in the past. Th is
work tries to fi nd simple but secure data encryption method which should be imple-
mented in one of the small Java-based database systems – . For this task, the
fi eld encryption was chosen with respect to further research of component-based
security. Both cryptoanalysis and performance of implemented system are discussed
here.
OBSAH
Úvod / Metódy ochrany databázových systémov / Analýza existujúcich databázových systémov / Návrh systému / Implementácia v systéme / Analýza riešenia / Zhodnotenie / : Náväznosť na diplomový projekt / : Podporné systémy a technológie / : Technická dokumentácia / : Elektronický nosič / Literatúra /
ZOZNAM OBRÁZKOV A TABULIEK
. .: Ukážka asociácie databázového pohľadu k tabuľke /. .: Schéma virtuálnych privátnych databáz /. .: Ukážka defi novania prístupových práv cez Oracle Label Security /. .: Schéma komponentového databázového systému /. .: Schéma návrhu komponentového riešenia /. .: Rozčlenenie obsahu databázy do súborov /. .: Začiatok každého záznamového súboru (s koncovkou script) /. .: Schéma šifrovania záznamového súboru /. .: Schéma dešifrovania záznamového súboru /. .: Schéma šifrovania samostatných objektov riadku tabuľky /. .: Schéma dešifrovania samostatných objektov riadku tabuľky /. .: Schéma generátora kľúčov pre jednotlivé polia tabuľky /
. .: Algoritmy pre šifrovanie a kontrolu integrity overené
v implementovanom systéme /
. .: Porovnanie upraveného systému .. s databázovým
systémom Cloudscape .. z hľadiska rýchlosti
a veľkosti ukladaných údajov /
Chcel by som sa poďakovaťsvojim rodičom a bratom za podporu a pochopenie,diplomovému vedúcemu Ing. Petrovi Matuškovi za trpezlivosť a pripomienky,prof. RNDr. Otokarovi Grošekovi, CSc. za dôležitú literatúru,celému osadenstvu katedry matematiky za pocit, že som asi naozaj študoval,doc. Ing. Margaréte Kotuliakovej, CSc. za pomoc na poslednú chvíľua nakoniec Asociácii autonómnych astronautov za nečakané povzbudenie.
Ťažké srdce mám na fi rmu Maxtor, ktorej nekvalitné výrobky ma pripravili minimálne o veľké množstvo prácea na zlodejov v mestkej hromadnej doprave, ktorí ma pripravili o testovací hardvér.
ÚVOD
Databázové systémy patria v súčasnosti medzi najdôležitejšie aplikácie výpočtovej
techniky. Čo sa týka internetových aplikácií – teda informačných systémov typu
klient-server, ktoré sa v posledných rokoch vyvíjajú najrýchlejšie – základom väčši-
ny z nich je spolu s web-serverom práve databázový systém. Podobne je to aj na poli
príručných počítačov (handheldov), ktoré vzhľadom na svoje parametre slúžia hlav-
ne ako zberače a zásobníky údajov. Častokrát sú údaje uložené v týchto systémoch
cennejšie než hardvérové a softvérové vybavenie.
Téma bezpečnosti databázových systémov je za posledných dvadsať rokov roz-
pracovávaná v rôznych oblastiach výskumu, teda nepredstavuje uzavretú skupinu.
Jej úlohou však stále zostáva vyvíjať nové metódy alebo vhodne využívať dostupné
prostriedky k zaručeniu ochrany údajov. Napriek tomu tu neexistujú jednoznačné
odporúčania alebo vzorové riešenia. Je to dané hlavne tým, že problematických
oblastí tejto témy je priveľa na to, aby sa dali zovšeobecniť. Zároveň si však dovolím
poznamenať, že niekedy ani vývoj nesmeruje k jeho praktickému využitiu, ako uka-
zuje nepatrné množstvo realizovaných riešení.
Jednou z najviac požadovaných vlastnosti softvérových produktov je znovupou-
žiteľnosť, mnoho technológií je vytváraných tak, aby sa dali bez problémov začleniť
do existujúceho prostredia. V budúcnosti bude tento trend len silnieť, čo bude mať
za následok narastajúcu technologickú štandardizáciu. Tomuto trendu sa nemôžu
vyhnúť ani databázové systémy. Komerčný databázový systém dnes napríklad nemô-
že uspieť na trhu bez podpory štandardov , alebo . Prototypy bezpeč-
ných databázových systémov však väčšinou pracujú bez podpory štandardov, čím sa
automaticky znižujú ich šance použitia v reálnych podmienkach.
Zadaním tejto diplomovej práce je implementácia vlastného systému ochrany
v databázovom systéme. Pri výbere vhodného implementačného jazyka a systému
som sa snažil zohľadniť práve praktické využitie riešenia, z čoho vyplynula potreba
nájsť vhodný pomer medzi funkčnosťou a bezpečnosťou. Ďalším dôležitým aspek-
tom bolo, aby si systém zachoval črtu univerzálnosti a neobmedzoval funkčnosť
ostatných použitých komponentov.
Prvú časť tejto práce tvorí prehľad existujúcich metód ochrany údajov a zhodno-
tenie možnosti ich použitia v reálnom prostredí. Na ňu nadväzuje analýza existujú-
cich databázových systémov, vrátane troch najvýznamnejších – Oraclei, IBM DB v. a Microsoft SQL Server .
Filozofi u systému ochrany údajov v databázovom systéme, postavenom na kom-
ponentovej architektúre, tvorí tretia časť, pričom jeho praktická implementácia
do malého databázového systému je popísaná v štvrtej časti. Bezpečnosť
navrhnutého a implementovaného systému a porovnanie jeho výkonu s referenčnou
databázou Cloudscape sú analyzované v piatej časti práce. Šiestu hlavnú časť tvorí
záverečné zhodnotenie diplomovej práce z pohľadu autora.
Nasledujú prílohy, v ktorých je postupne popísaný súvis s diplomovým projektom
vypracovaným v máji (príloha A), prehľad najdôležitejších podporných systé-
mov databázovej bezpečnosti (príloha B), technická dokumentácia so zdrojovými
textami najdôležitejších častí implementovaného systému (príloha C) a popis obsahu
elektronického nosiča (-), ktorý je súčasťou diplomovej práce (príloha D).
V prílohe D nájdete aj základné pokyny pre inštaláciu, spustenie a pripojenie k data-
bázovému systému.
Úvodom by som ešte chcel upozorniť, že vzhľadom na niektoré prekrývajúce sa
termíny v obore databázových systémov a kryptografi e, budú databázové kľúče tabu-
liek vždy označované ako primárne, sekundárne alebo cudzie kľúče. Skrátene sa budú
označovať iba kryptografi cké kľúče.
METÓDY OCHRANY DATABÁZOVÝCH SYSTÉMOV
Bezpečnosť databázových systémov je veľmi široký pojem, za ktorým sa skrýva
množstvo teoretických a technologických problémov i riešení. Výskum v tejto oblas-
ti začal v sedemdesiatych rokoch dvadsiateho storočia, pričom do dnešnej doby bolo
vypracovaných niekoľko bezpečnostných metód a procedúr. Niektoré z nich boli
štandardizované a tvoria základ vybraných certifi kačných politík, napr. []
alebo - []. V tomto ohľade je problematika bezpečnosti kategorizovateľná
[] a je možné ju rozdeliť do príbuzných skupín:
. Prístup k databáze
. Bezpečnostné fi ltre
. Šifrovacie metódy
. Databázové počítače a architektúry
. Databázové pohľady (views)
. Krycie scenáre (cover stories)
.
Na databázu sa môžeme pozerať ako na úložisko informácií, ktoré sú potrebné pre
existenciu a fungovanie organizácie. Táto organizácia chce mať istotu, že všetky úda-
je sú prístupné len tým osobám, ktoré na to majú právo (autorizovaným osobám) a že
údaje budú skutočne zodpovedať realite (aktualizácia a ochrana proti nepovolenej
modifi kácii). Pre vytvorenie prijateľnej bezpečnostnej politiky je potrebná detailná
analýza možných hrozieb a rizík. Túto politiku môžeme ďalej rozdeliť na:
• riadenie prístupu – defi nuje sa sada prístupových práv a pravidiel. Používateľ má
špecifi kované práva na vybrané prostriedky a na základe týchto kritérií je mu buď
povolený alebo zamietnutý prístup,
• inference policy – rozhoduje, ktoré údaje by mali byť chránené, aby sa zabránilo ich
strate alebo zverejneniu,
• identifi káciu používateľa – špecifi kuje potreby k jednoznačnej identifi kácii použí-
vateľa,
• správu a audit – predstavuje sada požiadaviek pre zaznamenávanie všetkých ope-
rácií a audit,
• správu súdržnosti – defi nuje význam operačnej, sémantickej a fyzickej integrity
databázy.
1
.
Nápad vytvoriť systém bezpečnostných fi ltrov pre databázové systémy patrí medzi
najstaršie možné riešenia bezpečnosti vzhľadom na svoju jednoduchosť. Vychádza
z idei medzičlánku, ktorý by vykonával funkciu prekladateľa medzi používateľom
a údajmi. Na základe práv používateľa a vlastností fi ltra sa bude zobrazovať len určitá
časť údajov a len v určitej forme.
Na tejto jednoduchej forme fi ltra boli postavené viaceré bezpečnostné mechaniz-
my avšak neskorší výskum ukázal niektoré nedostatky oddeleného zariadenia. Preto
je v súčasnosti takýto fi lter alebo tiež dôveryhodný (trusted) front-end poväčšinou
jednou z komponent bezpečného databázového systému.
Jedným z najstarších rozšírení fi ltra je vytvorenie tzv. zámku integrity (integrity lock). Na každý vložený záznam je aplikovaná funkcia na výpočet kontrolného súčtu
(checksum) a jej výsledok je uložený spolu s údajmi. Pri načítaní záznamu z databázy
sa porovná novovypočítaný výsledok s uloženým a ak sa nezhodujú, je zrejmé, že
údaje boli zmenené od poslednej autorizovanej modifi kácie. V ideálnom prípade
by kontrolný súčet mala vytvárať kryptografi cká hash funkcia alebo šifrovací algo-
ritmus, ktorý je odolný voči útokom na nezašifrovaný a zašifrovaný text (oba sú ulo-
žené v databáze). Údaje v záznamoch nie sú šifrované, aby bolo umožnené klasické
spracovanie databázovým systémom, pričom správne značenie má na starosti fi lter.
Je však potrebné poznamenať, že kontrolný súčet detekuje chyby, ale ich neo-
pravuje. V takom prípade je potrebné údaje zálohovať a po zistení neautorizovanej
modifi kácie obnoviť. Toto však nerieši nasledujúce problémy:
• Problém nezistených modifi kácií počas dlhšieho časového obdobia. Ak nelegál-
ne modifi kované údaje nie sú často používané, a teda nie je ani verifi kovaný kon-
trolný súčet, zostávajú v databáze a v každej zálohe od dátumu neregistrovanej
modifi kácie. V takom prípade je zálohovanie zbytočné. Riešením je verifi kácia
kontrolných súčtov všetkých údajov v databáze pred zálohovaním.
• Problém častého výskytu neautorizovaných modifi kácií. V prípade, že sa používa
zálohovanie ako ochrana, je potrebná v pravidelných intervaloch, resp. častejšie
než za bežných okolností, čím sa rapídne stráca výkon systému alebo sa dokonca
systém stáva nepoužiteľným. Aj keď sa zdá, že bezpečnostné fi ltre predstavujú
len veľmi jednoduché zabezpečenie ochrany údajov, v praxi sa dobre overili a sú
najčastejším vybavením komerčných databázových systémov, ktoré majú zabu-
dovanú poväčšinou veľmi slabú bezpečnostnú ochranu.
.
Využitie kryptografi ckých techník alebo šifrovania v databázových systémoch repre-
zentuje ďalší dôležitý bezpečnostný mechanizmus. Údaje sú uložené v databázovom
systéme v zašifrovanej forme, takže ich nepovolaní používatelia nemôžu čítať. Šifro-
vanie by malo byť uskutočňované v nižších úrovniach systémovej bezpečnosti, aby
mohlo byť aplikovateľné nezávisle od spôsobu využitia systému.
Aj keď sa šifrovanie považuje za veľmi bezpečnú metódu, nie je na mieste pova-
žovať systém, ktorý ho implementuje za dôveryhodný. Je to preto, že šifrovanie
neošetruje nedostatky, chyby a tzv. zadné vráta (backdoor, loophole), ktoré môže
obsahovať operačný alebo databázový systém. Z toho dôvodu by šifrovanie malo byť
použité spolu s inými bezpečnostnými komponentmi a taktiež by mala byť zvolená
najefektívnejšia metóda vzhľadom na architektúru alebo konfi guráciu použitého
databázového systému. Vo všeobecnosti má šifrovanie v databázových systémoch
niekoľko výhod, niektoré z nich sú:
• Šifrovanie predstavuje poslednú obrannú líniu proti útoku oponenta.
• Šifrovanie údajov v databáze odradzuje útočníkov. Je len veľmi malá pravdepo-
dobnosť, že by sa dostali k údajom bez znalosti vhodnej kryptografi ckej infor-
mácie. Bez tejto informácie je veľmi zložité alebo nemožné previesť kryptogra-
my na zrozumiteľný text.
Nevýhodou šifrovaných databáz je, že vyhľadávanie v záznamoch je veľmi nefl exi-
bilné. Vytvorenie indexov môže efektivitu zvýšiť, je však potrebné zvážiť, ktoré polia
môžu byť indexované, aby nedošlo k odtajneniu skrytých informácií.
Šifrovanie môže byť aplikované na tri úrovne rozdelenie údajov – na celé záznamy
(riadky tabuľky), na skupiny atribútov záznamov (stĺpce tabuľky) a na individuál-
ne polia. Šifrovanie skupiny atribútov si pre čítanie údajov vyžaduje rozšifrovanie
všetkých záznamov, aj keď bol požadovaný iba jeden. Pri šifrovaní celých záznamov,
musíme rozšifrovať celý záznam, aj keď potrebujeme iba jeden atribút. Preto ako
najlepšia alternatíva vychádza šifrovanie jednotlivých polí.
Čo sa týka vhodných metód šifrovania, bolo ich vytvorených niekoľko:
• šifrovanie a autentifi kácia polí blokovou šifrou,
• model šifrovacích podkľúčov,
• šifrovanie založené na reziduálnych kódoch.
.. Šifrovanie a autentifikácia polí blokovou šifrouV [] Dorothy E. Denning použila blokovú šifru DES pre šifrovanie a autentifi káciu
polí záznamov. Princíp je založený na ochrane zašifrovaných polí pred útokom pre-
hľadávaním zašifrovaných záznamov. Ak sú všetky otvorené texty v poliach zašifro-
vané rovnakým kľúčom, potom zhodné otvorené texty majú za následok vytvorenie
zhodných zašifrovaných textov.
Tento problém sa dá obísť ak každé pole tabuľke bude zašifrované jedinečným
kľúčom. Navrhnutá schéma predpokladá, že identifi kátor záznamu, napr. primárny
kľúč, má maximálne bajtov a nešifruje sa (aj kvôli vyhľadávaniu).
Potom je každé pole j záznamu i šifrované iným kľúčom Kij. Tento kľúč sa vytvára
z troch parametrov – jednoznačný identifi kátor záznamu i – Ri, identifi kátor poľa j – Fj a tajný databázový kľúč K. Potom kľúč poľa záznamu Kij = g(Ri, Fj, K), kde g je
funkcia generujúca kľúče. Bolo popísaných päť možných spôsobov generovania:
• Kij = EKj(Ri), kde Kj = EK(Fj)
• Kij = Ri ⊕ Kj, kde Kj = EK(Fj)
• Kij = EKi(Fj), kde Ki = EK(Ri)
• Kij = Fj ⊕ Ki, kde Ki = EK(Ri)
• Kij = EK(Ri ⊕ Fj)
Z týchto generátorov prvý a tretí poskytujú najvyššiu ochranu, ale vyžadujú
dvojnásobné šifrovanie, zvyšné vyžadujú iba jednoduché šifrovanie, avšak už nepo-
skytujú takú mieru ochrany. Piaty generátor môže navyše generovať slabé kľúče, ak
niektoré vyššie bity identifi kátora záznamu Ri zostanú nevyužité.
Šifrovanie a dešifrovanie poľa Mij používa blokovú šifru s dĺžkou bloku b. Ak sa
šifrujú údaje dĺžky menšej ako b, potom sa použije šifra v móde , inak sa použije
zreťazenie blokov s inicializačným blokom IV.
Rovnakým spôsobom sa generujú kľúče pre funkciu vytvárajúcu kontrolné súčty
pre kontrolu integrity údajov, ktoré sa potom pripájajú k údajom.
.. Model šifrovacích podkľúčovMetóda Davida, Wellsa a Kama [] je založená na čínskej zvyškovej vete. Táto veta
tvrdí, že ak máme r kladných celých čísiel m, m, …, mr, ktoré sú vzájomne nesúde-
liteľné a r kladných celých čisiel a, a, …, ar, potom kongruencia x ≡ ai mod mi (pre
i = , … r) má všeobecné riešenie. Nech Ci predstavuje zašifrované záznamy (riadky),
aj polia záznamu a dj dešifrovacie kľúče pre pole j. Potom platí
Ci ≡ aj mod dj.
V tomto prípade sú dj veľké prvočísla a aj ľubovoľné kladné celé čísla.
Šifrovanie záznamu Ci potom prebieha nasledovne:
Ci ≡ ∑n
j = ej (xj || fij) mod D,
kde
D = ∏n
j = dj
a fij je hodnota pre pole j záznamu i. Náhodné číslo xj je vygenerované pre pole j a je
pripojené k fij. Číslo, ktoré vznikne takýmto spojením však musí byť menšie ako dj.
Šifrovací kľúč ej potom vypočítame ako:
ej ≡ (D/dj) bj mod dj
kde
bj ≡ (D/dj)φ(dj) – mod dj
je inverziou (D/dj) mod dj a φ(dj) je hodnotou Eulerovej funkcie pre dj.
Dešifrovanie hodnoty v poli fij záznamu Ci vypočítame použitím kľúča dj:
Ci ≡ (xj || fij) mod dj.
Nakoniec odstránime náhodné bity xj a získame hodnotu fij.
Nevýhodou tejto metódy je to, že pri zmene obsahu jedného poľa, je potrebné
znovu zašifrovať celý záznam (riadok).
.. Šifrovanie založené na reziduálnych kódochV [] Nam a Rao prezentovali šifrovaciu metódu, ktorá umožňuje detekciu chýb v
databáze.
Nech M je pole záznamu a C je jeho zašifrovanou formou. C obsahuje n rezíduí,
vrátane (n – k) kontrolných na detekciu chýb.
C = C, …. Ck, Ck+, …. Cn,
kde C, …. Ck predstavujú informačné a Ck+, …. Cn kontrolné rezíduá.
Šifrovanie prebieha tak, že sa vyberie n šifrovacích kľúčov e, …, en, ktoré sú vzá-
jomne nesúdeliteľné a zároveň platí:
∏k
i= ei ≥ max(M).Zc ∧ ek+j > ei,
pre j = , …, n – k a i = , …, k, kde Zc je kladné celé číslo zvolené ako bezpečnostný
parameter a max(M) je maximálna hodnota, akú môže nadobudnúť M. Potom, n
častí C získame z konkruencie:
Ci ≡ (Z || M) mod ei,
pre i = , …, n, kde Z je náhodné číslo s fi xnou bitovou dĺžkou menšie ako Zc a spo-
jené s M.
Dešifrovanie prebieha tak, že vypočítame:
Z || M ≡ ∑k
i = (diCi) mod E,
kde
E = ∏k
i= ei
Dešifrovací kľúč di sa vypočíta ako:
di ≡ (E/ei) bi
bi ≡ (E/ei)φ(ei) – mod di.
Syndrómový vektor Si vypočítame ako:
Si ≡ (C – M_
) mod ei,
pre i = k + , …, n. M_
= Z || M. V prípade, že nenastali žiadne chyby, syndrómový
vektor je nulový.
.
Databázové počítače majú niekoľko výhod v bezpečnosti údajov, vždy však v náväz-
nosti od konfi gurácie a hostiteľského operačného systému. Vo všeobecnosti môžeme
tieto architektúry rozdeliť do štyroch kategórií:
• Inteligentný ovládač disku – v tomto prípade je databázový systém umiestnený
v hostiteľskom počítači, využíva jeho hlavnú pamäť, ale spolupracuje s inteli-
gentným ovládačom. Údaje v pôvodnej forme sa pred zápisom a po načítaní
z pamäti spracovávajú práve v tomto ovládači. Do tejto kategórie patria naprí-
klad šifrované súborové systémy [][].
• Hostiteľsky nezávislý hardvérový databázový backend – databáza je fyzicky
oddelená od hostiteľského (frontend) počítača
• Softvérový databázový backend – správa databázy a vstupno-výstupné rutiny
sú vykonávané softvérom, ktorý beží na hostiteľskom počítači. Z tohto pohľadu
sa nevyužívajú žiadne dodatočné prostriedky hostiteľského systému. Nastavenia
bezpečnosti sú úzko späté s bezpečnosťou operačného systému, z toho vyplýva
problém portovania databázového systému na inú platformu..
• Softvérová databáza s viacerými backendami – softvérový databázový backend
adaptovaný do viacprocesorového prostredia s riadiacim modulom.
. ()
Databázové pohľady predstavujú metódu ako dynamicky sprostredkovávať používa-
teľovi prístup k údajom uloženým v tabuľkách databázy. Defi nované sú ako podmno-
žina tabuľky alebo preddefi novaná virtuálna relácia nad databázovými reláciami.
Vytvára sa príkazom , ktorý je v súčasnosti implementovaný vo
väčšine databázových systémov.
K pohľadu sa potom pristupuje štandardnými príkazmi ako k pôvodnej
tabuľke. Využitie pohľadu je hlavne v možnosti obmedzenia prístupu k citlivým
údajom. V takom prípade sa vytvorí k tabuľke pohľad, v ktorom sa obmedzí prístup
k určitým stĺpcom. Potom sa používateľovi zakáže prístup k tabuľke a povolí sa iba
k pohľadu. Vzhľadom k tomu, že k tabuľke môže existovať viac než jeden pohľad, je
možné takýmto spôsobom implementovať hierarchickú aj nehierarchickú metódu
prístupu k údajom. Na základe informácii o používateľovi sa dynamicky vytvorí
pohľad k tabuľke, v ktorom sa podľa zvolenej prístupovej politiky sprístupnia určité
informácie.
. ( )
Ide o veľmi zaujímavý spôsob ochrany údajov. Vychádza z predpokladu, že už infor-
mácia o tom, že údaj je tajný, je prezradením tajomstva. V tomto prípade sa využívajú
krycie scenáre, čiže používateľovi s nižšími prístupovými právami ako vyžaduje údaj,
sa podhodí nepravá informácia. Používateľovi teda nie je zamietnutý prístup a má
prístup ku všetkým informáciám, hoci falošným. Tieto postupy sa používajú hlavne
vo vojenských databázových systémoch [].
EMPNO ENAME JOB
CLERKSALESMANSALESMANMANAGER
SMITHALLENWARDJONES
7329749975217566
MGR
7902769876987839
HIREDATE
17–DEC–8820–FEB–8822–FEB–8802–APR–88
SAL COMM
800.001600.001250.002975.00
300.00300.005.00
DEPTNO
20303020
EMPNO ENAME JOB
CLERKSALESMANSALESMANMANAGER
SMITHALLENWARDJONES
7329749975217566
MGR
7902769876987839
DEPTNO
20303020
EMP
STAFFView
BaseTable
. . .:Ukážka asociácie databázového pohľadu k tabuľke
ANALÝZA EXISTUJÚCICH DATABÁZOVÝCH SYSTÉMOV
V súčasnosti existuje na trhu veľké množstvo databázových systémov. Mnohí ana-
lytici sa zhodujú, že najväčší podiel na trhu majú a budú mať najdôležitejšie []:
Oracle, IBM DB a Microsoft SQL Server, z ktorých len prvé dva podporujú viac
než jeden operačný systém. Na druhej strane tu existujú open-source databázové
systémy, ktoré majú šancu vďaka tomu, že k ich používaniu nie sú potrebné žiadne
licenčné poplatky, ich zdrojové kódy sú voľne dostupné a teda je možné doplniť v prí-
pade potreby chýbajúcu funkcionalitu.
Každý zo systémov má implementovanú bezpečnosť s ohľadom na cieľový trh,
avšak všetky dostupné systémy majú nedostatky v prípade šifrovania údajov – buď
chýba úplne, alebo je šifrovanie použité v rozpore s analýzou možných útokov, t. j.
je použité konvenčné šifrovanie s jedným kľúčom miesto spomínaných metód šifro-
vania. Okrem toho na trhu existuje množstvo podporných systémov, ktoré dopĺňajú
konečné produkty (end-user) o chýbajúcu funkcionalitu. Tie najdôležitejšie z nich sú
spomínané v prílohe B.
. i
Oraclei je databázovým produktom fi rmy Oracle Corporation uvedeným na trh
v júni . Tento systém sa vyznačuje niektorými propietárnymi technológiami,
ktoré ju odlišujú od produktov ostatných fi riem, ako napríklad Virtual Private Data-
base alebo Oracle Label Security. Prídavný bezpečnostný modul Oracle Advanced
Security .. bol ohodnotený pod - [] ako produkt úrovne , čo je naj-
vyššia úroveň, ktorú môže získať softvér v Spojených Štátoch Amerických.
Zároveň bola databáza certifi kovaná podľa [] na úroveň C, v spojení
s Oracle Advanced Security na úroveň B.
AutentifikáciaPoužívatelia môžu byť autentifi kovaní rôznymi spôsobmi pred tým, než im je povo-
lené vytvoriť databázovú reláciu. Pri databázovej autentifi kácii sa defi nujú používa-
telia, pre ktorých databáza vykonáva aj identifi káciu aj autentifi káciu. Pri externej
autentifi kácii sa defi nujú používatelia, ktorých autentifi kuje operačný systém alebo
zvolená sieťová služba. Alternatívne sú používatelia autentifi kovaní prostredníctvom
protokolu alebo technológiou Single Sign-on.
Základnou autentifi káciou sú heslá, dá sa však použiť aj silná autentifi kácia zalo-
žená na existencii centrálnej autentifi kačnej služby vhodná pre distribuované systé-
my. Sem spadá Kerberos a CyberSafe, , , a . Zároveň je možné použiť
aj novšie autentifi kačné prostriedky – Token karty, Smart karty a Biometriky.
2
Virtuálna privátna databázaTáto technológia umožňuje spravovať databázový prístup na úrovni tabuľkových
riadkov. Ako voliteľná nadstavba sa môže použiť Oracle Label Security, ktorá je
alernatívnou náhradou pohľadov. Správa je postavená na prepojení zvolenej
bezpečnostnej politiky s tabuľkami a pohľadmi (views). Priamy alebo nepriamy prí-
stup k tabuľke je vyhodnocovaný a upravený podľa určených práv žiadateľa. V praxi
to znamená, že na koniec každej požiadavky sa pripojí prístupová podmienka,
predikát (klauzula ), čím sa dynamicky mení prístup užívateľa k údajom.
Napríklad, ak užívateľ John Doe, ktorý pracuje v oddelení , pošle požiadavku o vý-
pis všetkých zamestnancov v tvare požiadavky * emp, ku nej
pripojí podmienkovú klauzulu = a systém vráti výpis zamestnancov
len z oddelenia .
Tento spôsob je implementovaný pomocou tzv. uložených procedúr (stored pro-
cedures) na úrovni dizajnéra informačného systému. Výhodou je, že bezpečnostná
politika sa dá určiť presne podľa požiadaviek, pričom najdôležitejším aspektom je, že
každá požiadavka je vyhodnotená, nehľadiac na zdroj. Nevýhodou zostáva možnosť
výskytu chýb v implementácií procedúr.
Bezpečná aplikačná rola (Secure Application Role)Pretrvávajúcim bezpečnostným problémom je vytvorenie obmedzenia prístupu
k údajom tak, aby používatelia nemohli obchádzať aplikačnú logiku a pristupovať
priamo k údajom – napríklad v internetových aplikáciách. Potom by sa mohlo stať,
že používateľ omylom alebo vedome zmení údaje, ku ktorým mal v rámci svojich
práv prístup, avšak v rámci aplikačnej logiky mu mali byť skryté (napríklad počí-
tadlo).
Preto je v Oraclei vytvorená tzv. bezpečná aplikačná rola, implementovaná ako
procedurálny balík (package). Tento balík vykonáva ľubovoľnú požadovanú validáciu,
aby sa zaistili všetky požadované podmienky pred tým, ako užívateľ využije práva,
ktoré má povolené rolou defi novanou v databáze. Databáza pritom zaisťuje, že len
overené (trusted) balíky implementujúce bezpečné role môžu vykonávať validáciu
prístupových podmienok.
useruser
Database
SELECT * FROM ORDERS
SELECT * FROM ORDERS. .:
Schéma virtuálnych privátnych databáz
Vo viac-vrstvových systémoch, akými sú napríklad intranetové aplikácie, môže
balík (package) overiť platnosť používateľskej relácie (user session), ktorú vytvorila
stredná vrstva tejto aplikácie (middle-tier) a tak potvrdiť, že používateľ pristupuje
k databáze iba cez povolené rozhranie. Používateľovi, ktorý by chcel pristupovať
k databáze priamo, bude odmietnutý prístup k údajom. Takýmto spôsobom je mož-
né zaručiť ľubovoľné bezbečnostné podmienky, napríklad používateľ z vonkajšej
siete nemusí mať prístup k citlivým personálnym údajom.
Bezpečné aplikačné role rozširujú možnosti autentifi kácie a prístupových práv
o procedurálnu kontrolu podmienok, za ktorých budú používateľovi poskytnuté
alebo odmietnuté požadované privilégia.
Oracle Label SecurityTento produkt dáva správcom databázového systému možnosť rozšíriť štandardné
prístupové práva o kontrolu prístupu založenú na štítkoch (label) pre konkrétne
záznamy v databáze, teda nejde o riadenie prístupu k tabuľke. Každému záznamu
s citlivými informáciami sa priradí štítok s presne špecifi kovanou mierou citlivosti.
Oracle Label Security je postavený na metódach virtuálnych privátnych databáz,
teda nevyžaduje dodatočné programovanie. Pôsobí ako sprostredkovateľ prístupu
k záznamom v tabuľke databázy medzi štítkom záznamu, štítkom priradeným kaž-
dej databázovej relácii a privilégiami priradenými k danej relácii. Štítky Oracle Label
Security môžu obsahovať tieto komponenty:
• úroveň (level) – hierarchicky defi novaný údaj, ktorý zodpovedá citlivosti údajov
(napr. Confi dential, Top Secret),
• oddelenie (compartment) – nehierarchicky defi novaný údaj, niekedy označova-
ný ako kategória (podporovaných je jednoznačných hodnôt),
• skupina (group) – údaj označujúci vlastníka záznamu, môže byť hierarchický
(napr. manažér, riaditeľ).
Šifrovanie údajov v databázeDatabázový systém Oracle i poskytuje selektívne šifrovanie údajov. Konkrétna
metóda šifrovania nie je uverejnená, avšak z technickej dokumentácie [] vyplýva,
že nie je použitá žiadna z metód spomínaných v časti ., použité je iba konvenčné
šifrovanie polí záznamov.
Šifrovanie je zabezpečené / balíkom __ [],
ktorý podporuje blokové šifry a . Podpora šifry je plánovaná nasle-
GRADE 600
600
400
RATE
Manager
Senior
Director
600
450
UNCLASSIFIED
UNCLASSIFIED
SENSITIVE
SENSITIVE
Principal
Senior
ROW LABEL
750 HIGHLY_SENSITIVEUser session labelis UNCLASSIFIED
. .:Ukážka defi novania prístupových práv cez Oracle Label Security
dujúcej verzii databázového systému. Správu kľúčov však databáza nezabezpečuje,
teda problém bezpečného uloženia a získania kľúča zostáva na používateľovi, resp.
vývojárovi aplikácie. Bloková šifra je podporovaná ako bitový a bitový (pre
spätnú kompatibilitu) variant. Mód šifrovania nie je uvedený. Dĺžka požadovaného
kľúča je bitov. Bloková šifra je podporovaná v - a -kľúčovom variante
v móde. Požadovaná dĺžka kľúča je , resp. bitov.
Popri šifrovaní je možné použiť kryptografi ckú kontrolu integrity zabezpečenú
algoritmom . Rovnako ako pri šifrovaní je nutné použiť balík _-
_, takže používateľ, ktorý pristupuje priamo k databáze, obchádzajúc
aplikáciu využívajúcu tento balík, nemôže aktualizovať kontrolný súčet nového
záznamu.
Niektoré dátové typy vyžadujú netriviálne šifrovanie. Oraclei používa na ukla-
danie veľkých binárnych objektov dátový typ (binary large object), ktorý môže
mať veľkosť rádovo niekoľko gigabajtov. Tieto sú uložené buď vnútri v tabuľke alebo
v externom súbore. Pretože / podporuje maximálnu veľkosť údajov
bajtov, používateľ musí rozdeliť vkladaný objekt na bloky, každý z nich zašifrovať
a potom spojiť a uložiť ako . Podobne je to s vyberaním údajov z databázy, pou-
žívateľ musí postupne dešifrovať bloky a tie následne pospájať [].
Pre generovanie kľúčov je k dispozícii metóda GetKey, ktorá bola certifi kovaná
podľa štandardu . Vývojári aplikácií by nemali používať balík _-
, pretože ten generuje slabé pseudonáhodné čísla.
AuditOraclei audituje databázovú aktivitu na základe príkazov, využívania systémových
privilégií, objektov alebo používateľov. Napríklad je možné zaznamenávať všeobec-
ne všetky používateľské pripojenia na databázu alebo konkrétne žiadosti daného
používateľa o vytvorenie novej tabuľky. Rovnako sa dá rozlišovať medzi úspešnými
a neúspešnými operáciami. Auditné záznamy sa ukladajú do databázy, kde môžu byť
ďalej spracované automatizovaným riadením, čím sa v prípade nutnosti spustia zade-
fi nované bezpečnostné opatrenia.
Auditná kontrola je zabudovaná priamo v databázovom systéme a je vykonávaná
súbežne s požadovanou funkcionalitou. Tak je dosiahnuté to, že ľubovoľne nastavené
parametre auditu nemajú vplyv na degradáciu výkonu systému. Používateľsky defi -
nované auditné záznamy sa vytvárajú spúšťaním predkompilovaných / alebo
Java príkazov, pred alebo po vykonaní sledovanej akcie [].
Detailne štruktúrované auditné možnosti Oraclei tvoria základ auditnej politiky,
upravovateľnejpodľa aktuálnych potrieb. Týmto je zaručené, že sa budú vytvárať iba
tie záznamy, o ktoré je záujem. Napríklad má fi rma záujem auditovať všetky pokusy
o získanie záznamov o platoch zamestnancov spolu s ich menami. Ak však niekto
(napríklad štatistická aplikácia) potrebuje celkovú sumu platov, nemusí sa to zazna-
menávať do auditných záznamov.
Oraclei zaznamenáva zadávané príkazy v pôvodnej forme, takže je možné
použitím technológie Flashback Query zreprodukovať postupnosť krokov vybrané-
ho používateľa. Toto má veľký význam hlavne z právneho hľadiska, kedy je treba
dosvedčiť a právne doložiť presný postup úkonov daného používateľa.
. .
Universal Database je jedným z produktov fi rmy patriacich do rady ,
uvedený na trh v júni . Táto rada zahŕňa databázové systémy pre rôzne plat-
formy od príručných počítačov (handheldov) k sálovým architektúram (mainframe)
[]. Tento systém je navrhnutý ako súčasť väčšej výpočtovej infraštruktúry, ktorej
poskytuje služby a naopak od ktorej služby požaduje. To platí vo veľkej miere aj pre
bezpečnosť údajov.
AutentifikáciaAutentifi kácia používateľa je vykonávaná mimo systém , často službami ope-
račného systému alebo dedikovaným systémom, napr. . Akonáhle je používateľ
autentifi kovaný, systém zaznamená jeho identifi káciu a priradí privilégiá. defi -
nuje štyri kategórie autentifi kácie:
• na strane servera – autentifi káciu zabezpečuje operačný systém, ktorému
prenecháva funkciu validácie identifi kácie používateľa a hesla. Modifi káciou je
prenos zašifrovaného hesla medzi serverom a klientom. Heslo je zašifrované
-bitovou šifrou k prenosu kľúča je použitý Difi e-Hellmanov algoritmus.
Algoritmy sú poskytované knižnicou .
• na strane klienta – len v prípade existencie dôveryhodného klienta (bez Win-
dows a ).
• – získa od bezpečnostnej služby potvrdenie o autenticite použí-
vateľa s možnosťou šifrovania komunikácie.
• Kerberos – podobne ako , akonáhle je používateľ autentifi kovaný, platnosť
vytvoreného potvrdenia sa vzťahuje na všetky servery v okruhu pôsobnosti služ-
by Kerberos. Rovnako je k dispozícii možnosť šifrovania komunikácie.
Metódy riadenia prístupuRiadenie prístupu v je vykonávané prostredníctvom balíkov (packages), pohľad-
mi (views), spúšťami (triggers) a špeciálnymi registrami. Balíky sú základnou
metódou riadenia prístupu pre príkazy v . Používateľ, ktorý vytvára balík,
musí mať vykonávacie privilégiá ku všetkým statickým príkazom v balíku. Pou-
žívatelia, ktorí balík používajú, musia mať k nemu vykonávacie privilégiá, nemusia
však mať prístup k statickým metódam v ňom defi novaných.
Pohľady riešia prístup k jednotlivým záznamom v tabuľkách (row-level access).
Ich použitím je možné ukryť citlivé časti tabuliek. Spúšte pomáhajú defi novať kom-
plexné bezpečnostné mechanizmy, ktoré sa inicializujú akonáhle nastane určitá
sledovaná udalosť. Spustenie môže byť vykonané pred alebo po spracovaní špecifi -
kovanej udalosti, čím je možné zaručiť väčšie zabezpečenie. Špeciálny register
obsahuje používateľa v danej relácii. Táto hodnota môže byť využitá pre vytvára-
nie pohľadov pre konkrétneho používateľa. Takto každý používateľ môže mať prístup
prostredníctvom rovnakého pohľadu k rôznym dátam.
Šifrovanie údajov v databázeŠifrovanie údajov neprebieha automaticky, musí byť vyžiadané a implementované zo
strany používateľa. poskytuje štyri príkazy []:
• – šifruje údaje blokovou šifrou RC so -bitovým kľúčom, ktorý je
vytvorený z hesla (dĺžka až ) algoritmom MD. Voliteľným argumentom
je nápoveda (password-hint) v prípade, že používateľ heslo zabudol. Šifrovať je
možné iba dátové typy a s maximálnou dĺžkou bez nápo-
vedy alebo s nápovedou.
• _ a _ – slúžia na dešifrovanie.
• – vráti nápovedu k heslu, ak je v údajoch prítomné.
Spôsob použitia záleží od možností vývojára aplikácie, systém neposkytuje auto-
matické dešifrovanie, preto sa nesmú šifrovať primárne, sekundárne kľúče a položky,
ktoré sú indexované.
Audit poskytuje možnosť viesť auditné záznamy o všetkých subjektoch a objektoch,
ktoré sú obsiahnuté v databázovom systéme. Záznamy sa vytvárajú pre sériu predde-
fi novaných udalostí, pričom administrátor má na starosti ich konfi guráciu. Spolu so
systémom sú dodávané prostriedky pre analýzu týchto záznamov.
.
Microsoft SQL Server je databázovým systémom, ktorý na rozdiel od už
spomínaných produktov existuje iba pre platformu Windows. Jeho bezpečnostná
architektúra je založená bezpečnostných modeloch operačných systémov Microsoft
Windows NT . a Windows , čím sa zvýšila závislosť na hostiteľskom operač-
nom systéme. Bol certifi kovaný v rámci [] a získal certifi kát úrovne C.
AutentifikáciaAutentifi kácia je okrem prístupu cez heslá založená na systéme Kerberos, ktorého
podpora je vstavaná do hostiteľského operačného systému. Ak je žiadosť o auten-
tifi káciu používateľa vybavená kladne, systém získava potvrdenie o autentifi kácii,
ktoré je platné v celom okruhu pôsobnosti systému Kerberos. SQL Server môže toto
potvrdenie na požiadanie poslať inému žiadateľovi (systému).
Šifrovanie údajov v databázeŠifrovacie algoritmy nie sú implementované priamo v databáze, ale využívajú sa tie,
ktoré poskytuje knižnica Windows Crypto API. Crypto API je aplikačné rozhranie
unifi kujúce použitie šifrovacích algoritmov a komunikačných protokolov, podobne
ako []. Výhodou je, že používateľ si môže zvoliť ľubovoľný podporovaný šif-
rovací algoritmus bez zmeny implementácie. V dokumentácii sa nespomína použitá
metóda šifrovania, vzhľadom na to, že je šifrovanie ponechané na používateľovi,
závisí len na ňom, ktorú si zvolí a implementuje v aplikácii. SQL Server pod-
poruje šifrovaný súborový systém , ktorý je nadstavbou natívneho súborového
systému Windows NT – [].
AuditMechanizmus vytvárania auditných záznamov je založený na niekoľkých kompo-
nentoch []:
• SQL Trace – je udalostne založený auditný systém, postavený na systéme
kontroly výkonnosti v predchádzajúcej verzii databázového systému – SQL
Server . Keď sa v systéme vyskytne auditovateľná udalosť, SQL Trace je o tom
upovedomený a na základe defi novaných pravidiel rozhodne, či bude zapísaná
do auditného súboru (log).
• SQL Profi ler – je klientom SQL Trace. Predstavuje grafi cké rozhranie k audit-
ným záznamom, umožňuje ich fi ltrovať, triediť, exportovať a defi novať auditné
požiadavky.
Vzhľadom na certifi káciu C má SQL Server fi xne nastavené zaznamená-
vanie všetkých bezpečnostných udalostí, ďalej je možné presne špecifi kovať ďalšie
udalosti presne podľa potrieb.
. ..
Cloudscape je databázovým systémom postaveným na báze Javy, teda je použiteľný
vo všetkých prostrediach, kde existuje Java Runtime Environment – teda od sálových
serverov až po príručné počítače. Patrí do rodiny IBM DB Universal Database.
AutentifikáciaCloudscape podporuje autentifi káciu prostredníctvom , +, alebo hes-
lom.
ŠifrovanieAko u jediného analyzovaného systému je podporované automatické šifrovanie
údajov na disku. Metóda šifrovanie nie je publikovaná, známy je iba podporovaný
kryptografi cký systém Java Cryptographic Extension (). Štandardne sú podporo-
vané algoritmy , ede a Blowfi sh. Pri výbere alternatívnej šifry treba zohľadniť
tieto kritériá:
• musí byť symetrická,
• musí byť bloková s veľkosťou bloku bajtov,
• nepoužíva žiadnu výplňovú (padding) schému,
• tajný kľúč musí byť reprezentovateľný ako pole bajtov,
• vyžaduje iba jeden parameter, a to inicializačný vektor IV,• využíva triedu javax.crypto.spec.SecretKeySpec na reprezentáciu kľúčov.
Podporované operačné módy sú ECB, CBC, CFB a OCB.
Pri štarte systému sa žiada bootovacie heslo, ktoré musí mať dĺžku aspoň baj-
tov.
NÁVRH SYSTÉMU
Ako vyplýva z prehľadu bezpečnostných metód a analýzy existujúcich riešení, je
vytvorenie dokázateľne bezpečného databázového systému veľmi problematické.
Bezpečnosť celého systému závisí od zvolenej bezpečnostnej politiky, ktorá je kom-
promisom medzi želateľnými a realizovateľnými parametrami systému.
Vzhľadom na komplikovanosť databázových systémov a neustále zmeny požia-
daviek, nie je možné vytvoriť systém ochrany postavený na jedinej metóde alebo
technológii, nech by bola akokoľvek bezpečná. Rozumným riešením sa javí kom-
ponentový pohľad na databázový systém (. .). Každá časť systému môže byť
zabezpečená metódou, ktorá je pre ňu v danom okamihu najvhodnejšia. V prípade
potrebných zmien vyžiadaných novými okolnosťami, stačí zmeniť iba tú časť systé-
mu, ktorej sa to týka.
Analýza existujúcich systémov dokazuje, že väčšie systémy sústreďujú zabezpeče-
nie systému hlavne do riadenia prístupu, ďalej správy pravidiel, správy udalostí a až
nakoniec do správy údajov. Odôvodňujú to znížením výkonnosti systému. Naopak
menšie systémy, určené najmä pre jednoužívateľské aplikácie, alebo viacvrstvové
(multi-tier) aplikácie, sa začínajú viac sústreďovať na zabezpečenie správy údajov.
3
riadenieprístupu
správaudalostí
Správaúdajov
Vyhodnocovaniepodmienok
Správapravidiel
Správatranzakcií
aplikácia
Autorizačné rozhranieDBMS
. .:Schéma komponentového databázového systému.
.
Pri návrhu systému som vychádzal z názoru, že nie je možné vyriešiť zabezpečenie
správy údajov a riadenia prístupu k údajom jedinou metódou. Preto so sa rozhodol
začať riešiť problém ochrany na najnižšej úrovni s ohľadom na možné rozšírenie
smerom nahor. Prakticky to znamená navrhnúť systém šifrovania údajov v úložnom
priestore tak, aby ho bolo možné neskôr rozšíriť o riadenie prístupu. Z pohľadu
štruktúry údajov preto vzniká potreba pristupovať ku každému údaju v tabuľke nezá-
visle od ostatných. Tu sa ako jediný možný spôsob javí použitie podkľúčov (všetky tri
metódy popísané v časti . toto kritérium spĺňajú).
Ďalším dôležitým kritériom bola pre mňa použiteľnosť takéhoto systému v prak-
tických podmienkach, najlepšie implementovaním do existujúceho funkčného
systému bez zmeny jeho funkcionality a s minimálnym obmedzením jeho prístup-
nosti. To znamená hlavne podporu štandardu a všetkých údajových typov. Zo
všetkých popísaných metód však iba metóda šifrovania a autentifi kácie polí blokovou šifrou umožňuje šifrovať variabilné binárne polia. Navyše oproti metóde šifrovacích podkľúčov bola určená ako jednoznačne efektívnejšia [].
Hlavnou silou a zároveň slabinou tohto systému je výber vhodnej blokovej šifry.
Dnes sa už dá povedať, že , pre ktorý bola metóda navrhovaná, nie je bezpečná
šifra. Preto ako ďalšie kritérium som si stanovil možnosť použitia ľubovoľnej šifry,
ktorá je najvhodnejšia pre danú aplikáciu. Voľnosť výberu som sa rozhodol rozšíriť
aj pre autentifi kačnú funkciu, pre ktoré existujú vhodnejšie alternatívy ako bloková
šifra .
Aby bolo možné použiť systém aj v jednoduchších aplikáciách, bolo nutné zohľad-
niť možnosti daného prostredia. Ak bude systém použitý bez dodatočnej nadstavby
riadenia prístupu, čo je aj prípad implementácie v tejto diplomovej práci, potom
bude systém generovania kľúčov pre jednotlivé polia odvodený z metódy popísanej
v časti ... V prípade, že systém bude rozšírený o nadstavbu riadenia prístupu,
potom tento bude spravovať prístupové kľúče ku konkrétnym poliam. Tu sa už budú
môcť použiť vhodnejšie metódy popísané v častiach .. a ... Ale správa údajov,
a tým pádom aj šifrovanie a dešifrovanie, bude aj v tomto prípade stále prislúchať
najnižšej vrstve.
RIAdenieprístupu požiadavka
správaúdajov
dbMS
D
D
Kf(i,j)
Kuser
F(i,j) Ef(i,j)
Rf(i,j) Pf(i,j)
. .:Schéma návrhu
komponentového riešenia
Existuje však skutočný dôvod na vytvorenie nového systém ochrany, ak by úlohu
bezpečného úložiska na disku mohol zvládnuť napríklad šifrovaný súborový systém?
Predstavme si situáciu, keď chceme chrániť údaje v príručnom počítači (handheld-e).
Napríklad operačný systém Palm OS je založený na databázovom prístupe k údajom.
Potom by možno stačilo vytvoriť plošnú ochranu celej pamäti prístupovým heslom.
Aplikácie vytvorené pre tento systém by tak získali šifrovanú ochranu údajov bez
nutnosti zmeny implementácie. Problémom je však synchronizácia údajov so stol-
ným počítačom. Údaje sú chránené pred zlodejom alebo náhodným pozorovateľom
v príručnom počítači, ale pri synchronizácii sa prenášajú a ukladajú údaje na hosti-
teľskom počítači v nechránenej forme. Preto je potrebné, aby bol systém zabezpeče-
nia vstavaný priamo v aplikácii, samozrejme ak má o takúto ochranu záujem.
V prípade systému ochrany údajov som sa preto rozhodol implementovať spo-
mínanú najnižšiu úroveň (na . . je to časť systému v šedej ploche), ktorú je
možné samostatne použiť v jednoužívateľských systémoch (napr. aplikácie pre prí-
ručné počítače). Pre viacužívateľské systémy je potom možné tento systém neskôr
rozšíriť.
IMPLEMENTÁCIA V SYSTÉME HSQLDB
Databázový systém je vývojovým pokračovaním systému HypersonicSQL
Th omasa Muellera. V súčasnosti je správcom vývoja Hypersonic SQL Group, pričom
ide o open-source projekt, ktorý sídli na adrese http://hsqldb.sourceforge.net. Systém
bol spočiatku navrhovaný s ohľadom na čo najmenšiu veľkosť a rýchlosť, preto sa
komplexnosťou a výkonnosťou nevyrovná veľkým komerčným systémom. Do tejto
pozície ho stavia aj implementačný jazyk a prostredie Java, určené hlavne pre pro-
dukty prenositeľné medzi výpočtovými platformami. Za posledné tri roky sa však
pozícia produktov na báze Javy mení a smeruje viac do tzv. enterprise sféry, dôka-
zom je úspech platformy . Komunikačným protokolom pre spoluprácu aplikácie
a databázového systému v tomto prostredí je výhradne štandard .
Systém sa štandardne dodáva s aplikačným serverom JBoss ako perzis-
tentné úložisko objektov. Okrem serverového módu, môže pracovať aj samostatne
ako jednoduchý web kontajner alebo v čisto pamäťovom móde ako applet.
.
Každá databáza vytvorená v sa skladá z dvoch alebo štyroch súborov. Súbor
s príponou properties štandardne obsahuje informácie o vlastnostiach databázy,
napr. verzia systému v ktorom bola databáza vytvorená, s ktorým systémom je spät-
ne kompatibilná alebo informácie o sémantickej integrite údajov – integrita cudzích
kľúčov.
Súbor s príponou script obsahuje popis databázy v jazyku , ďalej sú tam defi -
nované tabuľky a ostatné databázové objekty (napr. používatelia) a nakoniec samot-
né údaje, ktoré nie sú uložené v dátovom súbore. Tento súbor slúži ako záznamník
(log), kde si systém zapisuje všetky dôležité udalosti – pripojenie používateľa, prida-
nie, úprava a zmazanie záznamov. Po prekročení určitej hranice veľkosti záznamu sa
všetky nepotrebné údaje odstránia a na koniec záznamu sa vloží značka (checkpoint), ktorá určuje miesto, po ktoré je záznam kompaktný. Ďalší zápis a triedenie sa potom
uskutočňuje až od tejto značky.
Databázový systém hsqldb bol použitý v ofi ciálnom hlasovacom systéme tohtoročných parlamentných volieb v Brazílii.
db.properties db.script db.data db.backup
databázadb
. .:Rozčlenenie obsahu databázy do súborov
4
Súbor s koncovkou data obsahuje iba samotné údaje uložené v binárnej forme.
Údaje sa ukladajú po riadkoch za sebou v poradí, ako sú nadefi nované v tabuľke.
Každému záznamu predchádza indentifi kátor, ktorým sa naň odkazuje v databáze,
prípadne ďalšie dodatočné informácie, ako napr. index. Posledná kompaktná záloha
údajov je komprimovaná metódou v súbore backup .
Pri štarte databázového systému, sa najprv načítajú a spracujú súbor predvolieb
properties a záznam script. Ďalej sa na základe požiadaviek načítavajú údaje zo súbo-
ru data. V prípade nečakaného ukončenia systému sa pri ďalšom štarte obnoví zane-
chaný stav spracovaním všetkých záznamov a súbor data sa nahradí zálohou backup.
Po obnovení stavu pred kolapsom sa všetky neuložené údaje zo záznamu zapíšu do
dátového súboru a vytvorí sa nová kompaktná záloha.
.
Ako je zrejmé na . ., záznamový súbor (script) obsahuje v otvorenej textovej
forme všetky údaje vrátane hesiel používateľov databázy. Je to veľmi nepríjemné, pre-
tože v prípade odcudzenia tohto súboru môže dôjsť okrem zverejnenia údajov aj ku
kompromitácii kľúčov k iným údajom (užívatelia väčšinou používajú rovnaké heslá).
Vzhľadom na to, že záznamový súbor sa sekvenčne zapisuje a zároveň aj sekvenčne
načítava, najvhodnejším a najefektívnejším spôsobom ochrany je šifrovanie bloko-
vou symetrickou šifrou. Kvalitná bloková šifra by mala teoreticky zaručiť vysokú
mieru bezpečnosti, pri šifrovaní sa však nesmie použiť základný mód [].
mód je vhodnejší, oproti módu má však tú nevýhodu, že údaje nezašif-
ruje skôr než sa mu zaplní n-bajtový vstupný zásobník alebo sa neukončí vstupná
postupnosť. To je veľmi dôležité v prípadoch, ako je sekvenčný zápis do súboru.
V prípade zrútenia systému (napr. kolísaním napätia) totiž zostane posledný blok
nezapísaný a záznam zostane neúplný. Preto sa mód dopĺňa vyplňovaním
posledného šifrovaného bloku podľa normy [].
Typ blokovej šifry, spôsob vyplňovania prázdnych miest aj operačný mód je mož-
né vybrať pri vytváraní novej databázy. Tajný kľúč sa potom automaticky vygeneruje
podľa parametrov zvolenej šifry. Podrobnejšie informácie o ukladaní kľúčov sú uve-
dené v časti ..
GRANT ALL ON CLASS "java.lang.Math" TO PUBLICGRANT ALL ON CLASS "org.hsqldb.Library" TO PUBLICCREATE USER SA PASSWORD "" ADMINCREATE ALIAS DAYNAME FOR "org.hsqldb.Library.dayname"CREATE ALIAS SPACE FOR "org.hsqldb.Library.space"CREATE ALIAS SUBSTRING FOR "org.hsqldb.Library.substring"CREATE ALIAS HEXTORAW FOR "org.hsqldb.Library.hexToRaw"CREATE ALIAS SQRT FOR "java.lang.Math.sqrt"CREATE ALIAS ABS FOR "org.hsqldb.Library.abs"CREATE ALIAS POWER FOR "java.lang.Math.pow"CREATE ALIAS CHAR FOR "org.hsqldb.Library.character"…
. .:Začiatok každého
záznamového súboru (s koncovkou script)
Pri operačných módoch a je potrebné okrem tajného kľúča K zadávať
aj inicializačný vektor, ktorý musí byť identický pri šifrovaní aj dešifrovaní (rov-
nako ako tajný kľúč K). To zvyšuje nároky na bezpečné uloženie kľúča, preto som
ako vhodnejšie riešenie zvolil predsunutie generovaných pseudonáhodných čísel
o veľkosti jedného bloku danej šifry (n) pred otvorený text. Až takáto kombinova-
ná postupnosť bajtov sa šifruje tajným kľúčom K a zapisuje do súboru (. .).
Inicializačný vektor potom môže zostať štandardne nastavený na nulové hodnoty.
Výhodou tohto prístupu je, že pri každom zápise záznamového súboru sa vygeneruje
nová postupnosť, takže ten istý šifrovaný súbor je po zašifrovaní identickým tajným
kľúčom K vždy iný.
Dešifrovanie potom prebieha ekvivalentným spôsobom. Šifrovaný text sa dešif-
ruje tajným kľúčom K a pri načítavaní do operačnej pamäti sa preskočí prvých
n dešifrovaných bajtov (. .).
Samotný zápis a načítavanie je realizované triedami Off setCipherOutputStream a Off setCipherInputStream, ktoré som odvodil od tried CipherOutputStream
a CipherInputStream. Objekty vytvorené z týchto tried pri inicializácii automaticky
zapíšu, resp. preskočia n bajtov generovaných . Zvolená šifra je poskytnutá
objektom triedy CipherCentral, ktorý slúži pre riadenie všetkých šifrovacích proce-
sov, vrátane initicializácie a správy kľúčov. Zdrojové kódy implementácie všetkých
tried sa nachádzajú v technickej dokumentácii (príloha C).
Otvorený TEXTRND(n) + Otvorený TEXTšifrovaný TEXT
tajný kľúč preskočenieN Bajtov
Dk
K
II
. .:Schéma dešifrovania záznamového súboru
Otvorený TEXT
tajný kľúč
pseudonáhodnáPostupnosťn bajtov
RND(n) + Otvorený TEXT šifrovaný TEXT
EkII
K
1.
2.
PRNG
. .:Schéma šifrovania záznamového súboru
.
Dátový súbor (data) obsahuje v otvorenej binárnej forme záznamy riadkov tabuliek
databázy. Každý riadok tabuľky má priradený identifi kátor, na ktorý sa odvoláva
databáza a ktorý zároveň určuje jeho presnú polohu v súbore. Ďalej nasleduje údaj
o veľkosti celého záznamu a za ním postupne typ a binárna reprezentácia údaja. Pre
typy s variabilnou dĺžkou, ako napr. , , , , predchádza
binárnemu poľu údaj o dĺžke poľa n.
V tomto prípade som na zabezpečenie použil metódu šifrovania a autentifi kácie
údajov v jednotlivých poliach popísanú v časti .. Údaje sú šifrované ľubovoľnou
blokovou šifrou v móde a autentifi kované ľubovoľnou kľúčovanou hashovacou
funkciou. Obidva kľúče – KDATA pre šifrovanie údajov a KMAC pre overenie integrity
– sa podobne ako v predchádzajúcom prípade generujú pri vytváraní novej databázy
podľa parametrov potrebných pre konkrétny algoritmus.
Na . . je schematicky znázornený postup šifrovania jednotlivých objektov,
ktoré predstavujú samostatné polia v riadku tabuľky. Objekt sa serializuje – prevedie
na binárnu postupnosť n bajtov – a takto sa zašifruje priradeným kľúčom KF(i,j) a zá-
roveň sa k nej vytvorí kontrolný súčet s kľúčom KMAC(i,j).
Objektpoľa f(i,j)
serializácia
BINÁRNA POSTUPNOSŤ
4 bajty
H
II
II
Kmac(i,j)
KDATA
Kf(i,j)
1.
1.
2.
2.
PRNG
generátorkľúčov
4 bajty
EG
NNNN
N
…
L M
…
L L L L … …
N
i,j
. .:Schéma šifrovania
samostatných objektov riadku tabuľky
V tejto fáze implementácie som narazil na problém – niektoré typy polí sú defi -
nované s pevnou dĺžkou, niektoré s variabilnou. Najvhodnejším riešením preto bolo
pred každú variabilnú binárnu postupnosť vložiť štvorbajtový identifi kátor dĺžky.
Ostatné mali zostať zašifrované bez dodatočnej informácie o dĺžke.
Vyriešenie tohto problému sa rozšírilo o problém s prázdnymi objektmi. Jazyk
totiž dovoľuje použiť hodnotu pre každý typ polí. Teda nie nulovú hod-
notu alebo reťazec nulovej dĺžky, ale informáciu o tom, že pre konkrétne pole nie
je defi novaná žiadna hodnota. Preto bolo potrebné štvorbajtovú informáciu o dĺžke
vkladať pred každú binárnu postupnosť pevnej aj variabilnej dĺžky. Aby však nebola
táto schéma ľahko napadnuteľná, pred každú takúto postupnosť a identifi kátor jej
dĺžky sa vsunú štyri bajty z . Tým sa čiastočne zabráni útokom pomocou otvo-
reného textu. Hodnoty v tomto prípade predstavujú postupnosť štyroch bajtov
z nasledované identifi kátorom dĺžky poľa s nulovou hodnotou.
Takto zašifrované polia sú poukladané za sebou v poradí, v akom sa nachádzajú
v riadku tabuľky. Pred každé pole sa vloží nezašifrovaná hodnota dĺžky zašifrované-
ho poľa l a za pole sa vloží kontrolný súčet s dĺžkou m.
Nakoniec sa pred všetky zašifrované záznamy vloží identifi kátor riadku tabuľky
a dĺžka celého záznamu riadku (aj s kontrolnými súčtami a hodnotami dĺžok). Všetky
tieto hodnoty sú v súbore nezašifrované.
Dešifrovanie jednotlivých polí riadku záznamu je schematicky znázornené na
. .. Na základe údaja o dĺžke šifrovaného textu l sa z určenej pozície v súbore
data načíta l bajtov zašifrovaných údajov a m bajtov kontrolného súčtu. Údaje sa
dešifrujú priradeným kľúčom poľa KF(i,j), pričom sa preskočia prvé štyri bajty.
. .:Schéma dešifrovaniasamostatných objektovriadku tabuľky
Objektpoľa f(i,j)
deserializácia
H
?
Kmac(i,j)
KDATA
Kf(i,j)
1.
generátorkľúčov
4 bajtypreskočiť
DG
N
L M
…
L L L L … …
N
i,j
NNNN
Textové reťazce v progra-movacom jazyku Pascal sú ukladané podobným spôsobom. Rozdielom je, že tam má identofi kátor dĺžky jeden bajt, takže reťazec môže byť dlhý maximálne znakov [].
Potom sa na základe informácie o dĺžke n určí, či bol zašifrovaný objekt
a nakoniec sa požadovaný objekt deserializuje. Kontrola integrity nad dešifrovanou
binárnou postupnosťou a následným porovnaním s načítaným kontrolným súčtom
nám potom overí správnosť dešifrovania.
V prípade šifrovania aj dešifrovania sa pre každé pole tabuľky používa iný kľúč
KF(i,j). Na . . je schéma generátora takéhoto kľúča, ktorý bol popísaný v časti
... Generátor používa šifrovaciu metódu ekvivalentnú metóde použitej pre šif-
rovanie údajov v poliach, avšak pracujúcej v jednoduchom operačnom móde .
Výstupný zašifrovaný blok v každom kroku je potom kľúčom pre krok šifrovania.
Je však možné, že jeho dĺžka b bude väčšia ako požadovaná dĺžka kľúča c. V takom
prípade sa nadbytočné bajty nepoužijú.
Šifrovanie a dešifrovanie riadkov tabuľky je realizované vo vstupno-výstupných
triedach EncryptedRowOutput a EncryptedRowInput. Tieto triedy implementujú
rozhranie EncryptedRowOutputInterface, resp. EncryptedRowInputInterface, odvo-
dené z rozhrania DatabaseRowOutputInterface, resp. DatabaseRowInputInterface.
.
Implementácia systému používa – kľúče (podľa toho, či je požadovaná kontrola
integrity), ktoré sú vygenerované podľa potrieb zvolených šifrovacích algoritmov pri
prvom štarte databázového systému. Kľúče sú následne uložené do objektu triedy
KeyStore. Táto trieda je štandardným doplnkom systému určená pre bezpečnú
a komfortnú správu kľúčov a certifi kátov. Objekt je uložený v súbore s príponou key-store v adresári ostatných súborov databázy.
V tomto konkrétnom prípade som zvolil bezpečnejšiu verziu úložiska , kto-
rú do svojho modulu implementoval poskytovateľ (provider) BouncyCastle [].
Táto verzia šifruje jednotlivé kľúče systémom [] šifrou Twofi sh a hashovacou
funkciou . Integrita celého súboru je kontrolovaná tou istou hashovacou funk-
ciou.
KDATA
Kj
E
G
j …
KF(i,j)Ei …C
C
C
C
c – dĺžka kľúča
. .:Schéma generátora
kľúčov pre jednotlivé polia tabuľky
Heslo, pomocou ktorého sú kryptografi cké kľúče zašifrované, sa zadáva pri štarte
systému, t. j. v serverovom móde na vyžiadanie cez príkazový riadok, v standalone móde sa použije heslo, ktorým sa vytvára spojenie. V prípade zadávania hesla
cez príkazový riadok som musel odstrániť nedostatok štandardnej knižnice Java, kto-
rý neobsahuje žiadny bezpečný nástroj zadávania hesla. Heslo zadané v príkazovom
riadku zostáva viditeľné, preto som použil špeciálnu triedu PasswordField, ktorá
v pravidelných intervaloch premazáva obsah aktuálneho príkazového riadku.
Všetky operácie spojené s generovaním, načítavaním a ukladaním kľúčov som
rovnako ako správu šifrátorov implementoval v triede CipherCentral.
.
Všetky šifrovacie algoritmy v implementácii a testovaní boli použité z zásuvného
modulu od poskytovateľa (providera) BouncyCastle. Vo verzii . však nefungovali
všetky algoritmy spôsobom uvedeným v špecifi kácii []. Všetky šifry overené v im-
plementovanom systéme sú v . ..
AES
Blowfi sh
CAST
CAST
DES
DESede (DES)
IDEA
RC
RC
RC
Skipjack
Twofi sh
Serpent
MD
MD
MD
RipeMD
RipeMD
SHA
. .:Algoritmy pre šifrovanie a kontrolu integrity overené v implementovanom systéme
Pozn.:Do príkazového riadku sa zadáva iba názov algoritmu presne v tvare uvedenom v prvom stĺpci.
ANALÝZA RIEŠENIA
.
Pri návrhu a implementácii som sa snažil, aby miera bezpečnosti systému bola čo
najviac závislá od miery bezpečnosti zvolených algoritmov. Bezpečnosť údajov ulo-
žených v implementovanom systéme teda závisí najmä od zvolenej šifry. Štandardne
je preto predvolená šifra , ktorá bola navrhnutá s ohľadom na všetky v súčasnosti
známe útoky.
V prípade šifrovania jednotlivých polí databázy však môžeme nájsť aj iné útoky.
Jeden z nich nie je vedený priamo na šifru. Databázy môžu a väčšinou aj obsahujú
množstvo rovnakých údajov. Na základe znalosti obsahu jedného poľa v otvorenom
texte a jeho zašifrovanej formy je možné, aby útočník odhadol obsah aj ostatných
zašifrovaných polí. Ani dokázateľne bezpečná šifra nemusí s tým istým kľúčom
transformovať otvorený text na vždy iný zašifrovaný text. Z toho vyplýva nutnosť
použiť pre každé pole unikátny kľúč.
Predpokladajme, že každé pole databázy je šifrované iným kľúčom (tak ako je
to aj navrhnuté a implementované). Potom útočník nemôže zozbierať dostatočné
množstvo párov otvorený-šifrovaný text, aby mohol uskutočniť útok diferenciálnou
kryptoanalýzou [][].
Ďalším možným útokom je prehľadávanie celého priestoru kľúčov. Je to však málo
pravdepodobné vzhľadom na to, že útočník by tak získal iba jeden z podkľúčov, od
ktorého nemôže odvodiť hlavný kľúč.
V prípade šifrovania záznamového súboru môže útočník predpokladať štandard-
ný obsah otvoreného textu, ako je znázornený na . .. Tento súbor je preto
šifrovaný blokovou šifrou v móde – síce s nulovým inicializačným vektorom,
ale s prvým blokom náhodných čísel, ktoré sú pri každom uložení iné. Útočník nemá
možnosť získať vhodný pár otvoreného-šifrovaného textu v prvom bloku, keďže ani
samotná databáza obsah prvého bloku nikde nearchivuje a pri načítavaní sa automa-
ticky preskakuje.
Z týchto hypotéz vyplýva, že najslabším článkom systému je úložisko kľúčov.
V ideálnom prípade by nemalo zdielať úložný priestor s databázovým systémom,
dokonca ani s operačným systémom. To však v bežných podmienkach zatiaľ nie je
možné. Útočník môže prehľadať celý priestor kľúčov a tak nájsť všetky kľúče, ktorý-
mi sú chránené údaje v databázových súboroch. V tomto prípade, pri šifre Twofi sh
a dĺžke kľúča bitov to znamená výpočtovú náročnosť ²⁵⁶. Existuje tu však ešte
hrozba útoku na slabé heslo pomocou slovníka alebo možnosť odpozorovania hesla
pomocou trójskeho koňa alebo skrytými kanálmi.
5
.
HSQL HSQL
AES
HSQL
AES
SHA1
HSQL
AES
MEM
HSQL
DES
HSQL
BLOW
CLSC CLSC
DES
CLSC
BLOW
100
Tn [ms] 287 334 345 281 319 323 450 436 438
Ts [ms] 549 1967 2117 763 1836 3188 179 175 181
Tc [ms] 287 1436 1592 195 1475 2864 677 626 679
Ts [ms] 662 719 709 768 552 489 134 153 134
Veľkosť [kB] 144 160 168 156 140 156 440 424 444
1000
Tn [ms] 2264 2769 3012 2523 2559 2535 4293 4531 4469
Ts [ms] 1064 9653 10249 1201 9246 23397 184 185 204
Tc [ms] 1035 9186 10087 225 9142 23290 710 676 700
Ts [ms] 492 863 937 1201 666 642 129 128 127
Veľkosť [kB] 312 416 512 396 260 396 648 660 684
10000
Tn [ms] 20244 24652 25571 24587 21609 22437 39851 39055 39101
Ts [ms] 5085 80267 88549 5156 80178 218552 198 205 211
Tc [ms] 4924 81886 89931 281 80502 219813 638 607 723
Ts [ms] 944 2021 2493 5651 1860 1747 117 133 119
Veľkosť [kB] 2004 3012 3923 2847 1435 2847 2156 2076 2097
Vysvetlivky:Tn – doba naplnenia databázy určeným počtom riadkov (, , )
Ts – doba uloženia stavu databázy po naplnení
Tc – doba spočítania riadkov (operácia (*)) po znovuotvorení
Ts – doba uloženia stavu databázy po vykonaní operácie sčítania
HSQL – .. (zľava: bez šifrovania; s použitím šifry ; s použitím šifry
a SHA; s použitím šifry , ale bez šifrovania polí – údaje sú zašif-
rované a uložené výhradne v súbore script; s použitím šifry ; s použitím
šifry Blowfi sh)
CLSC – Cloudscape .. (zľava: bez šifrovania; s použitím šifry ; s použitím šifry
Blowfi sh)
Na meranie výkonu databázových systémov boli vytvorené štandardné postupy [],
ktoré zohľadňujú najmä konkrétne využitie systému v reálnych situáciách. Nevýho-
dou je, že tieto testy nie je možné použiť so základným počítačovým vybavením.
Tieto testy bežia v špeciálnych laboratóriách minimálne hodín, čo nie je možné
. .:Porovnanie upraveného
systému .. s databázovým systémom
Cloudscape ..z hľadiska rýchlosti
a veľkosti ukladaných údajov
realizovať na produkte, ktorý je vo vývoji pod časovým tlakom a zároveň ani nespĺňa
všetky požiadavky, ktoré tieto testy majú. Preto som na porovnanie použil a upravil
jeden z testov z balíku na meranie prístupu k údajom uložených v súboroch.
Jeho cieľom je sledovať dobu, za ktorú systém dokáže spracovať a uložiť požadova-
ný počet údajov. Vzhľadom k tomu, že Java databázy nie sú dimenzované na veľké
množstvá údajov, zvolil som stupne: , a riadkov. Zdrojové kódy
k tomuto testu sa nachádzajú v technickej dokumentácii (príloha C).
Za referenčný systém som zvolil Cloudscape (vo verzii ..), pretože ako jediný
systém na trhu automaticky šifruje údaje. Má však svoje obmedzenia, ktoré vyplývajú
z analýzy v časti .. Výsledky porovnania oboch systémov sú v . .. Testy boli
vykonávané na rovnakom hardvérovom a softvérovom vybavení: Apple iMac DV,
procesor PowerPC G MHz, pamäť MB, operačný systém Mac OS X ..,
Java Runtime Environment .. s technológiou HotSpot, provider BouncyCastle
. pre ...
Z nameraných výsledkov je zrejmé, že Cloudscape vyniká nad najmä
dobou uloženia stavu údajov pred ukončením (shutdown). Je to preto, že údaje najprv ukladá do záznamového súboru a až neskôr ich ukladá so špeciálneho
údajového súboru. Dochádza tak k viacnásobnému šifrovaniu, ktorému by sa dalo
pri inej architektúre predísť. Na druhej strane systém rýchlejšie spracováva
požiadavky, takže kým nie je požiadaný o ukončenie, získava späť výkonnostnú stra-
tu bez ohrozenia bezpečnosti. Menším zadosťučinením je, že údaje, ktoré už raz boli
zašifrované, sa znovu šifrovať nemusia – o tom vypovedá parameter Ts.
Zaujímavé je však, že výsledky systému Cloudscape sú v príncípe rovnaké, či už sa
údaje šifrujú alebo nie. Keď si porovnáme s použitím šifry a Blowfi sh,
sú tu viditeľné výkonnostné rozdiely. Z popisu šifry Blowfi sh vyplýva, že jej návrh
je optimalizovaný pre bitové procesory a mal by byť rýchlejší ako []. To
platí však iba pre prostredia, kde sa nemenia často šifrovacie kľúče. Z toho vyplýva
predpoklad, že všetky údaje sú šifrované jediným kľúčom, čo nie je z hľadiska kryp-
toanalýzy bezpečný prístup.
Pri analýze súborov šifrovanej Cloudscape databázy som našiel ešte jeden vážny
nedostatok. V záznamovom súbore (log) sa nachádzali niektoré z posledných zazna-
menaných údajov vo forme otvoreného textu. Na základe týchto poznatkov sa otvára
otázka, či skutočne Cloudscape údaje v súboroch šifruje.
ZHODNOTENIE
Na základe dostupných informácií som vytvoril prehľad metód ochrany údajov a po-
rovnal existujúce databázové systémy. Tieto analýzy viedli k jednoznačnému záveru,
že v drvivej väčšine prípadov sa pod pojmom bezpečnosť údajov rozumie riadenie
prístupu k údajom. Tento trend je ľahko odôvodniteľný, pretože veľké databázové
systémy boli a budú navrhované do výpočtových prostredí s viacerými používateľ-
mi. O tom nakoniec vypovedá aj ich cena. V súčasnosti sa však dostávajú viac do
popredia malé výpočtové systémy, ktoré sú určené pre jediného používateľa. Vtedy
sa detailne prepracovaná metodika prístupu, autentifi kácie, autorizácie a udeľovania
privililégií ukazuje ako nadbytočná.
To, čo je dôležité chrániť a čo sa doteraz najviac prehliadalo, sú údaje uložené
na fyzickom médiu. Problematikou bezpečného ukladania údajov som sa zaoberal
v návrhu systému, ktorý som aj implementoval do funkčného databázového sys-
tému . Pri návrhu systému som však prihliadal aj k možnostiam ďalšieho
rozširovania. Ako už bolo spomínané na inom mieste tejto práce, šifrovanie údajov
by malo predstavovať až tú poslednú bariéru pred útočníkom. Preto som zvolil za
základ ochrany údajov šifrovanie jednotlivých polí databázy symetrickou šifrou, kto-
rá umožňuje veľmi fl exibilné použitie najmä pre údajové typy s variabilnou dĺžkou
(napr. znakové reťazce alebo binárne polia). Takýto systém predstavuje dostatočnú
ochranu pre jednoužívateľské systémy, pre viacužívateľské sa dá neskôr rozšíriť. Jed-
nou z možností by mohlo byť pridanie riadenia prístupu nie priamo k údajom, ale ku
kľúčom, bez ktorých sú údaje v systéme nedešifrovateľné. Ak by zostala zachovaná
podmienka, že každé pole v databáze je šifrované jedinečným kľúčom, potom sa môj
návrh systému javí ako veľmi vhodný do rizikového prostredia.
Problémom sa však ukázala ani nie tak bezpečnosť ako výkonnosť takéhoto sys-
tému. V porovnávacích testoch sa šifrovanie jednotlivých polí ukazuje ako veľmi
pomalé a teda nevhodné pre kritické systémy (systémy pracujúce v reálnom čase).
Neskôr, vo fáze implementácie sa aj ukázalo, že v existujúcom systéme nebolo potrebné šifrovať každý údaj samostatne, ale stačilo celý záznam naraz. Tým
by som však zabránil ďalšiemu možnému rozšíreniu bezpečnosti systému o prepra-
cované riadenie prístupu, ktoré tam takisto chýba.
V praktických podmienkach bez veľkých nárokov na výkon je však možné bez
problémov nahradiť pôvodný databázový systém mojou zabezpečenou
verziou. Cieľ, ktorým bolo vytvoriť systém ochrany implementovateľný do reálneho
prostredia bez toho, aby sa zásadne obmedzovala funkcionalita, som dosiahol. Určite
nie je bez chyby, to ani nebolo v mojich silách. Každopádne v budúcnosti by som sa
už vyvaroval bezpečnostných úprav existujúcich riešení, najmä ak už tie boli niekoľ-
kokrát prepracovávané. Je výhodnejšie stavať systém od základov, v dlhšom časovom
horizonte sa to javí ako lepšia investícia.
6
: NÁVÄZNOSŤ NA DIPLOMOVÝ PROJEKT
Diplomový projekt, ktorý som vypracoval v máji si kládol za cieľ poskytnúť
všeobecný pohľad na problematiku bezpečnosti databázových systémov a analyzo-
vať aktuálny stav na trhu týchto systémov. Tieto informácie mali poslúžiť k návrhu
vhodnej metódy na ochranu údajov vo zvolenom systéme.
V diplomovej práci som aktualizoval túto analytickú časť, pričom som hlavne
detailnejšie rozobral metódy šifrovania údajov. V závere diplomového projektu som
sa pokúsil v hrubých črtoch navrhnúť systém ochrany údajov pre dva databázové
systémy postavené na báze Javy – a McKoi SQL. Prvý systém som zvolil, pre-
tože bol najviac rozšírený a nemal zabudovaný žiadny systém ochrany (tento systém
bol v dobe návrhu iba pamätovo-orientovaný); druhý systém preto, že predstavoval
súborovo-orientovanú databázu, na ktorej som chcel otestovať efektivitu šifrovania
jednotlivých polí s údajmi.
Medzitým však do jeho tvorcovia vstavali podporu pre prácu so súbormi,
preto som v diplomovej práci od pôvodnej úpravy dvoch systémov upustil a sústredil
sa iba na jeden systém. Pri záverečnom výkonostnom testovaní som však nie jeden-
krát zapochyboval o voľbe vhodnejšieho systému, pretože veľa z deklarovaných vlast-
ností v systéme neboli a nie sú spracované v dostatočnej kvalite a nebolo
v mojich silách ani v zameraní tejto práce opodstatnenie ich opravovať.
A
: PODPORNÉ SYSTÉMY A TECHNOLÓGIE
Bezpečnosť v databázových systémoch zdiela mnoho podobných vlastností s bez-
pečnosťou v iných oblastiach výpočtovej techniky. Preto je možné, aby existujúce
funkčné riešenia, resp. technológie boli používané rovnakým spôsobom pre rôzne
systémy. Napríklad autentifi kácia používateľa môže byť implementovaná v autenti-
fi kačnom systéme a ďalej využívaná rôznymi systémami podľa ich potrieb. Takéto
podporné systémy zvyšujú účinnosť bezpečnostných opatrení, pretože vývoj sa
sústreďuje v malom množstve produktov, ktoré potom môžu defi novať štandard pre
danú oblasť použitia. Vývojár databázového systému sa potom nemusí sústrediť na
vývoj niečoho, čo už existuje.
Kerberos a CyberSafeKerberos je dôveryhodný autentifi kačný systém tretej strany, ktorý bol vytvorený na
Massachusetts Institute of Technology () a je k dispozícii bez licenčných poplat-
kov. V súčasnosti je štandardne implementovaný okrem open-source operačných
systémov aj v mnohých komerčných systémoch ako napr. Apple Mac OS X alebo
Microsoft Windows .
Kerberos je založený na zdieľaní tajomstva. Predpokladá, že tretia strana je bez-
pečná (dôveryhodná) a poskytuje jednoduché prihlasovacie možnosti, centralizova-
né skladovanie hesiel a rozšírenú bezpečnosť výpočtových systémov. To uľahčuje
celkovú správu systémov, a ovládanie o strany po užívateľa – stačí, že si pamätá iba
jedno heslo do systému Kerberos. Ďalej umožňuje kontrolovať dobu prístupu, resp.
jeho platnosť, zabraňuje neautorizovanému prístupu a snahe o zopakovanie odchy-
tenej komunikácie (packet replay). Taktiež podporuje preposielanie používateľovej
identifi kácie v databázach. Stačí, ak sa prihlási raz a môže byť obsluhovaný rôznymi
systémami po určitú stanovenú dobu bez potreby znovu zadávať heslo.
CyberSafe je komerčná verzia systému Kerberos, ktorá ho rozširuje o niektoré
silnejšie autentifi kačné mechanizmy v rámci podpory CyberSafe ActiveTrust
servera.
Protokol (Remote Authentication Dial-In User Service) je priemyselným
štandardom pre autentifi káciu používateľov vo vzdialenej sieti. poskytuje
autentifi káciu, autorizáciu a správu používateľských informácií.
B
Distributed Computing Environment () je produktom nadácie Open Software Foundation (), ktorý predstavuje
niekoľko integrovaných sieťových služieb spolupracujúcich v distribuovanom
sieťovom prostredí, medzi ktoré patrí vzdialené volanie procedúr (remote procedure calls – ), adresárové služby (directory services), bezpečnostné služby, vlákna
(threads), distribuované súborové služby a distribuované časové služby.
DCE je využívané aplikáciami, ktoré pracujú v distribuovanom prostredí (napr.
distribuované databázy).
PKI predstavuje štandardnú sadu procedúr a bezpečnostných politík pre prácu s di-
gitálnymi certifi kátmi, pomocou ktorých sa vykonáva autentifi kácia a autorizácia.
V súčasnosti sa vývojom pre použitie v Internete () zaoberá organizácia
.
Token Card a Smart CardKarty Token, spĺňajúce štandard alebo , poskytujú dvojfaktorovú
metódu autentifi kácie používateľa – používateľ musí fyzicky vlastniť kartu a musí
poznať heslo. Používa sa hneď niekoľko metód. Niektoré typy zobrazujú jednorazové
heslo (one-time password) a sú synchronizované s autenfi kačnou službou. Iné majú
klávesnicu a sú založené na systéme otázka-odpoveď (challenge-response).
Karty Smart, založené na štandarde sú hardvérové zariadenia veľkosti
kreditnej karty, ktoré majú pamäť a procesor. Používajú sa prostredníctvom čítačky,
ktorá je pripojená k pracovnej stanici používateľa. Ich hlavnou výhodou je, že kľúč
uložený v pamäti nemusí kartu opustiť, teda nie je možné ho získať sledovaním ope-
račnej pamäti pracovnej stanice.
BiometrikyBiometriky sú založené na fyzickej charakteristike používateľa – hlas, odtlačok prsta
(fi ngerprint), obrys ruky, chakteristika tváre, zafarbenie očí, predstavujú veľmi silnú
autentifi káciu, ktorá je však zatiaľ v procese štandardizácie [].
DbEncryptDbEncrypt je produktom fi rmy Application Security, ktorý rozširuje možnosti
databázových systémov o šifrovanie údajov. Predstavuje medzičlánok medzi pou-
žívateľom a databázou (fi lter), ktorý sprostredkováva komunikáciu, autentifi káciu,
vzájomnú výmenu a integritu údajov. Podporovanými databázovými systémami
sú Microsoft SQL Server a novšie pre platformu Microsoft Windows NT/
a Oraclei a novšie pre platformu Microsoft Windows NT/, HP-UX, Linux
a Sun Solaris. Pripravuje sa verzia pre IBM UDB DB.
Princíp spočíva v tom, že DbEncrypt vytvorí v aktívnej databáze tabuľku
_ s používateľmi, ktorá obsahuje identifi káciu každého používa-
teľa a jeho verejný kľúč (môže byť zašifrovaný heslom). Pre vybraný stĺpec tabuľky
s údajmi je vygenerovaný kľúč symetrickej šifry, ktorý je zašifrovaný verejným kľú-
čom používateľa a uložený do tabuľky _. Dokumentácia [] neuvá-
dza aká metóda je zvolená pre šifrovanie, dá sa však predpokladať, že je to šifrovanie
jednotlivých polí tabuľky uvedené v časti ...
Podporovanými operačnými módami sú a , podporovanými algoritmami
sú AES, DES, DESX, DES, Blowfi sh, Twofi sh, RC, Serpent, CAST, CAST,
SKIPJACK, RC, RSA, SHA-, MD, HMAC SHA-.
: TECHNICKÁ DOKUMENTÁCIA
Všetky implementácie sú vytvorené v programovacom jazyku Java, rovnako ako
pôvodný systém hsqldb .. zverejnený . októbra . Pretože som plánoval
zdrojové kódy poskytnúť tvorcom, ako je zvykom u open-source produktov, všetky
komentáre sú písané v anglickom jazyku.
.
Uvedené zdrojové kódy prezentujú implementácie najdôležitejšie tried, ktoré zabez-
pečujú šifrovanie údajov databázy v súboroch (časť ). Vynechané sú iba úpravy
pôvodných tried a pomocné triedy, ktoré som nepovažoval za prioritné. Pre záujem-
cu sú však dostupné na priloženom elektronickom nosiči.
OffsetCipherOutputStream
package org.hsqldb.crypto;import java.io.*;import java.security.*;import javax.crypto.*;
/** * Subclass of <code>CipherOutputStream</code> which provides same * funcionality - encrypting and writting to the underlying output stream. * After initialization it fills first offset bytes with random bytes. * This is done for stronger cleartext attack resistance. Note, that this * requires <code>Cipher</code> to work in some of the chaining modes. * <p>It should be used in pair with <code>OffsetCipherInputStream</code> * <p>Copyright: Copyright (c) The HSQL Development Group</p> * @author Pavol Markovič * @version ..e */
public class OffsetCipherOutputStream extends CipherOutputStream {
/** The default offset size. */ public static final long DEFAULT_OFFSET = ;
/** This is the actual offset size. */ protected long offset;
/** Shared PRNG generator. */ protected static SecureRandom random;
/** This constructor is for compatibility only. Do not use! * @param os <code>OutputStream</code> subclass object */ protected OffsetCipherOutputStream(OutputStream os) { this(os, new NullCipher()); }
/** * This constructor takes offset value from cipher. * @param os <code>InputStream</code> subclass object * @param c Cipher used for encryption, should be initialized
C
Off setCipher-OutputStream
* in Cipher.ENCRYPT_MODE */ public OffsetCipherOutputStream(OutputStream os, Cipher c) { this(os, c, (c.getBlockSize() > ) ? c.getBlockSize() : DEFAULT_OFFSET); }
/** * This constructor takes offset value from cipher. * @param os <code>InputStream</code> subclass object * @param c Cipher used for encryption, should be initialized * in Cipher.ENCRYPT_MODE * @param offset value which overrides cipher’s block size */ public OffsetCipherOutputStream(OutputStream os, Cipher c, long offset) { super(os, c); if (offset < ) this.offset = ; else this.offset = offset;
try { if (random == null) initGenerator();
skip(this.offset); } catch (Exception e) { e.printStackTrace(); } }
/** * This constructor takes offset value from cipher. * @throws NoSuchAlgorithmException if PRNG algorithm is not available */ private void initGenerator() throws NoSuchAlgorithmException { random = SecureRandom.getInstance(“SHAPRNG”); }
/** * This method skips long <code>n</code> bytes. As the maximal byte array * to write at once is indicated with int value, the final long skip is made * up of several small skips if needed. * @param n long value which indicates required bytes to skip * @returns actual skipped bytes * @throws IOException if some i/o error occured */ protected long skip(long n) throws IOException { if (n <= ) return n;
long sum = ; do { // divide long n into smaller pieces and then skip sum += skip((n > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) n); n -= Integer.MAX_VALUE; } while (n > );
return sum; }
/** * This method is used internally skips <code>n</code> bytes. * It fills the skipped space with random bytes generated from * PRNG generator. * @param n value which indicates required bytes to skip * @returns actual skipped bytes * @throws IOException if some i/o error occured */
private int skip(int n) throws IOException { if (n <= ) return n;
if (random == null) // PRNG not initialized return ;
byte[] randomBytes = new byte[n]; random.nextBytes(randomBytes); // generate random bytes
write(randomBytes); // write them
return randomBytes.length; }}
OffsetCipherInputStream
package org.hsqldb.crypto;import java.io.*;import javax.crypto.*;
/** * Subclass of <code>CipherInputStream</code> which provides same * funcionality - reading and decrypting of underlying input stream. * <p>It should be used in pair with <code>OffsetCipherOutputStream</code> * as it skips <code>offset</code> bytes at the beginning.<-p> * <p>Copyright: Copyright (c) The HSQL Development Group</p> * @author Pavol Markovič * @version ..e */
public class OffsetCipherInputStream extends CipherInputStream {
/** The default offset size. */ public static final long DEFAULT_OFFSET = ;
/** This is the actual offset size. */ protected long offset;
/** This constructor is for compatibility only. Do not use! * @param is <code>InputStream</code> subclass object */ protected OffsetCipherInputStream(InputStream is) { this(is, new NullCipher()); }
/** This constructor takes offset value from cipher. * @param is <code>InputStream</code> subclass object * @param c Cipher used for decryption, should be initialized * in Cipher.DECRYPT_MODE */ public OffsetCipherInputStream(InputStream is, Cipher c) { this(is, c, (c.getBlockSize() > ) ? c.getBlockSize() : DEFAULT_OFFSET); }
/** This constructor takes overrides cipher block size with * <code>offset value. * @param is <code>InputStream</code> subclass object * @param c Cipher used for decryption, should be initialized * in Cipher.DECRYPT_MODE * @param offset value which overrides cipher’s block size */ public OffsetCipherInputStream(InputStream is, Cipher c, long offset) {
Off setCipher-InputStream
super(is, c); if (offset < ) this.offset = ; else this.offset = offset; try { if (available() >= this.offset) // if buffered just skip skip(this.offset); else { // if not, read byte after byte long l= this.offset; while (l-- > ) read(); } } catch (IOException ioe) { ioe.printStackTrace(); } }}
CipherCentral
package org.hsqldb;
import java.io.*;import java.security.*;import java.sql.SQLException;import java.util.HashMap;import javax.crypto.*;import javax.crypto.spec.*;import org.hsqldb.crypto.PasswordField;
/** * The class <code>CipherCentral</code> represents encryption helper * for database encryption. It serves for key management, * cipher initialization, field encryption and integrity check. * <p>Copyright: Copyright (c) The HSQL Development Group</p> * @author Pavol Markovič * @version ..e */public class CipherCentral {
/** This string indicates script key indicator. */ public final static String SCRIPT_KEY_ID = “script_key”;
/** This string indicates cache key indicator. */ public final static String CACHE_KEY_ID = “cache_key”;
/** This string indicates MAC key indicator. */ public final static String MAC_KEY_ID = “mac_key”;
/** This is the default script encryption algorithm. */ public final static String DEFAULT_SCRIPT_ALG = “AES”;
/** This is the default cache encryption algorithm. */ public final static String DEFAULT_CACHE_ALG = “AES”;
/** This is the default MAC algorithm. */ public final static String DEFAULT_MAC_ALG = “HMac-SHA”;
/** This is the default script encryption mode. */ public final static String SCRIPT_CIPHER_MODE = “CBC”;
/** This is the default script encryption padding. */ public final static String SCRIPT_CIPHER_PADDING = “PKCSPadding”;
CipherCentral
/** This is the default cache encryption mode. */ public final static String CACHE_CIPHER_MODE = “CBC”;
/** This is the default cache encryption padding. */ public final static String CACHE_CIPHER_PADDING = “PKCSPadding”;
/** This special value passed to <code>CipherCentral</code> * constructor indicates that no integrity check is required */ public final static String NO_INTEGRITYCHECK_ID = “_NONE_”;
/** This is the keystore file representation */ protected File keyStoreFile = null;
/** This is internal key store hash table */ protected HashMap keys = new HashMap();
/** Cipher used for script encryption */ protected Cipher scriptEncipher;
/** Cipher used for script decryption */ protected Cipher scriptDecipher;
/** Cipher used for cache encryption and decryption */ protected Cipher cacheCipher;
/** Cipher used for field key generation */ protected Cipher keygenCipher;
/** MAC used for field checksum */ protected Mac checksumCipher;
// for better performance private IvParameterSpec cacheIv; private SecretKeySpec cacheKey;
private boolean fieldChecksum;
/** * Constructs a new Database object that mounts or creates the database * files specified by the supplied name and passes data encryption details * to newly created <code>CipherCentral</code>. * * @param database the path to and common name shared by the database files * this Database uses * @param password key encryption/decryption password, if <code>null</code>, * it will be asked later from command-line (only in Server mode) * @param scriptAlg script-file encryption algorithm, if <code>null</code>, * default algorithm will be used * @param cacheAlg data-file encryption algorithm, if <code>null</code>, * default algorithm will be used * @param macAlg data-file integrity-check algorithm, if <code>null</code>, * default algorithm will be used * @throws SQLException if the specified path and common name * combination is illegal or password or algorithms are not correct */ public CipherCentral(String database, char[] password, String scriptAlg, String cacheAlg, String macAlg) throws SQLException { // no password and not In-Memory operation mode if (database.equalsIgnoreCase(“.”)) throw Trace.error(Trace.DATABASE_IN_ENCRYPTED_MODE, “Could not init CipherCentral in In-Memory mode”);
// add BouncyCastle provider (our cryptographic provider) Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
keyStoreFile = new File(database + “.keystore”);
try {
// if keystore file exists load keys if (keyStoreFile.exists()) { loadKeys(password, keyStoreFile); Trace.printSystemOut(“Keys loaded.”); } // generate and store to new keystore file otherwise else { // mac cipher are specified as HMac-CIPHER // example HMac-RipeMD if (macAlg != null && !macAlg.equalsIgnoreCase(NO_INTEGRITYCHECK_ID)) macAlg = “HMac-” + macAlg;
generateKeys(scriptAlg, cacheAlg, macAlg); Trace.printSystemOut(“Keys generated.”); storeKeys(password, keyStoreFile); Trace.printSystemOut(“Keys stored.”); }
initCiphers(); // finally init ciphers with given keys } catch (IOException ioe) { throw new SQLException(ioe.getMessage()); }
}
/** * Load encryption keys from keystore saved in <code>file</code>. * Keys are then accessible from hashtable <code>keys</code>. * * @param password key encryption/decryption password, if <code>null</code>, * it will be asked from command-line (only in Server mode) * @param file keystore’s file * @throws IOException if it’s not possible to load keys from keystore */ protected void loadKeys(char[] password, File file) throws IOException { // open keyStore file FileInputStream in = new FileInputStream(file); // BouncyCastle secure key store KeyStore store; try { store = KeyStore.getInstance(“UBER”, “BC”);
if (password == null) password = readPassword();
store.load(in, password); } catch (Exception e) { throw new IOException(e.getMessage()); }
try { // load keys into hashtable keys.put(SCRIPT_KEY_ID, (SecretKeySpec) store.getKey(SCRIPT_KEY_ID, password));
keys.put(CACHE_KEY_ID, (SecretKeySpec) store.getKey(CACHE_KEY_ID, password));
// if mac key exist, than field checksum is enabled if (store.isKeyEntry(MAC_KEY_ID)) { setFieldChecksum(true); keys.put(MAC_KEY_ID, (SecretKeySpec) store.getKey(MAC_KEY_ID, password)); } else setFieldChecksum(false); } catch (Exception e) { throw new IOException(e.getMessage()); }
}
/** * Generate keys for encryption and if needed for integrity check. * Keys are then accessible from hashtable <code>keys</code>. * * @param scriptAlg script-file encryption algorithm, if <code>null</code>, * default algorithm will be used * @param cacheAlg data-file encryption algorithm, if <code>null</code>, * default algorithm will be used * @param macAlg data-file integrity-check algorithm, if <code>null</code>, * default algorithm will be used, if <code>NO_INTEGRITY_CHECK_ID</code> * is passed, than no integrity check is used * @throws SQLException if it’s not possible to generate keys */ protected void generateKeys(String scriptAlg, String cacheAlg, String macAlg) throws SQLException { KeyGenerator kg; SecretKeySpec key; String alg;
try { // generate script_key alg = (scriptAlg == null) ? DEFAULT_SCRIPT_ALG : scriptAlg; // if not specified, then use default kg = KeyGenerator.getInstance(alg); kg.init(new SecureRandom()); key = (SecretKeySpec) kg.generateKey(); keys.put(SCRIPT_KEY_ID, key); // set key
// generate cache_key alg = (cacheAlg == null) ? DEFAULT_CACHE_ALG : cacheAlg; // if not specified, then use default kg = KeyGenerator.getInstance(alg); kg.init(new SecureRandom()); key = (SecretKeySpec) kg.generateKey(); keys.put(CACHE_KEY_ID, key); // set key } catch (NoSuchAlgorithmException nsae) { throw new SQLException(nsae.getMessage()); }
// is integrity check needed? if (macAlg != null && macAlg.equalsIgnoreCase(NO_INTEGRITYCHECK_ID)) { setFieldChecksum(false); } else { setFieldChecksum(true); // generate mac_key - different approach for MAC keys - bug in JCE? alg = (macAlg == null) ? DEFAULT_MAC_ALG : macAlg; // if not specified, then use default key = (SecretKeySpec) kg.generateKey(); key = new SecretKeySpec(key.getEncoded(), alg); keys.put(MAC_KEY_ID, key); // set key } }
/** * Store encryption keys into keystore saved in <code>file</code>. * * @param password key encryption/decryption password, if <code>null</code>, * it will be asked from command-line (only in Server mode) * @param file keystore’s file * @throws IOException if it’s not possible to store keys in keystore */ protected void storeKeys(char[] password, File file) throws IOException { // open keyStore file FileOutputStream out;
// BouncyCastle secure key store KeyStore store;
try { store = KeyStore.getInstance(“UBER”, “BC”); store.load(null, null); // init empty KeyStore
if (password == null) password = readPassword();
// store keys store.setKeyEntry(SCRIPT_KEY_ID, (SecretKeySpec) keys.get(SCRIPT_KEY_ID), password, null); store.setKeyEntry(CACHE_KEY_ID, (SecretKeySpec) keys.get(CACHE_KEY_ID), password, null); if (isFieldChecksum()) store.setKeyEntry(MAC_KEY_ID, (SecretKeySpec) keys.get(MAC_KEY_ID), password, null);
// save keystore file out = new FileOutputStream(file); store.store(out, password); out.close(); } catch (Exception e) { throw new IOException(e.getMessage()); }
}
/** * Securely read password from standard input. * * @return password typed by user * * @throws IOException if password cannot be taken */ public char[] readPassword() throws IOException { // this object will read user’s keystrokes without displaying PasswordField field = new PasswordField(); return field.getPassword(“Please enter password:”).toCharArray(); }
/** * Initialize ciphers for encryption/decryption/integrity checking. * * @throws SQLException if it’s not possible to init ciphers */ protected void initCiphers() throws SQLException { String alg; SecretKeySpec key; IvParameterSpec iV;
// cipher algorithm is specified in form ALGORITHM/MODE/PADDING // example: DES/ECB/NoPadding
try { // init script ciphers key = (SecretKeySpec) keys.get(SCRIPT_KEY_ID); alg = key.getAlgorithm() + “/” + SCRIPT_CIPHER_MODE + “/” + SCRIPT_CIPHER_PADDING; // get instances scriptEncipher = Cipher.getInstance(alg); scriptDecipher = Cipher.getInstance(alg); // create null initialization vector iV = new IvParameterSpec(new byte[scriptEncipher.getBlockSize()]); // init scriptEncipher.init(Cipher.ENCRYPT_MODE, key, iV); scriptDecipher.init(Cipher.DECRYPT_MODE, key, iV); Trace.printSystemOut(“Script algorithm: “ + scriptEncipher.getAlgorithm() + “ Block size: “ + scriptEncipher.getBlockSize());
// init cache cipher key = (SecretKeySpec) keys.get(CACHE_KEY_ID);
alg = key.getAlgorithm() + “/” + CACHE_CIPHER_MODE + “/” + CACHE_CIPHER_PADDING; // get instances cacheCipher = Cipher.getInstance(alg); // these instances are requested frequently, so here’s shotcut cacheIv = new IvParameterSpec(new byte[cacheCipher.getBlockSize()]); cacheKey = key; cacheCipher.init(Cipher.ENCRYPT_MODE, cacheKey, cacheIv);
Trace.printSystemOut(“Cache algorithm: “ + cacheCipher.getAlgorithm() + “ Block size: “ + cache-Cipher.getBlockSize());
// init key generator cipher // it uses the same algorithm as cache cipher, but works in simple mode alg = key.getAlgorithm(); keygenCipher = Cipher.getInstance(alg); // key generator cipher is initialized just before key generation, not here
Trace.printSystemOut(“Key generator algorithm: “ + keygenCipher.getAlgorithm() + “ Block size: “ + keygenCipher.getBlockSize());
// if integrity check is required, init checksum cipher if (isFieldChecksum()) { key = (SecretKeySpec) keys.get(MAC_KEY_ID); alg = key.getAlgorithm(); checksumCipher = Mac.getInstance(alg); checksumCipher.init(key);
Trace.printSystemOut(“MAC algorithm: “ + checksumCipher.getAlgorithm() + “ MAC size: “ + checksumCipher.getMacLength()); } } catch (Exception e) { throw new SQLException(e.getMessage()); } }
/** * This method returns key for requested field indicated by row and column id. * In this implementation it generates subkey’s subkey using key generator cipher * and master secret key. * * @param row row identificator (same as record identificator) * @param column column identificator (same as field identificator) * @return requested subkey * @throws SQLException if it’s not possible to return subkey */ public SecretKey getFieldKey(int row, int column) throws SQLException { return generateSubkey(keygenCipher, generateSubkey(keygenCipher, cacheKey, column), row); }
/** * This method generates subkey for given <code>Key</code> using modificator * and <code>Cipher</code>. It encrypts modificator using Cipher and Key as secret key. * Then it adjusts size to match requested key length. * * @param cipher cipher used to generate subkeys, should use tha same algorithm * as for ecrypting/decrypting fields (but in ECB mode without padding) * @param key secret key * @param modificator key modificator, usually field or record id * @return generated subkey * @throws SQLException if it’s not possible to generate subkey */ public SecretKey generateSubkey(Cipher cipher, Key key, int modificator) throws SQLException { SecretKeySpec newKey = null;
try { // init cipher with basic key
cipher.init(Cipher.ENCRYPT_MODE, key); int keyLength = key.getEncoded().length;
// convert modificator to byte array byte[] modBytes = Integer.toBinaryString(modificator).getBytes(); // encrypt byte[] newKeyBase = cipher.doFinal(modBytes); //resize and create new key newKey = new SecretKeySpec(resizeArray(newKeyBase, keyLength), cipher.getAlgorithm()); } catch (Exception e) { throw new SQLException(e.getMessage()); }
return newKey; }
/** * Returns given array resized for requested length. If the array is longer * than length, than it will be cut. If it’s shorten, it will be copied * multiple times to fit length. * * @param array source array * @param length requested length * @return generated subkey */ private byte[] resizeArray(byte[] array, int length) { byte[] newArray = new byte[length]; int copied = ; // already copied bytes
while (copied < length) { // compute byte chunk length to be copied at once int copylength = (array.length > length - copied) ? length - copied : array.length; System.arraycopy(array, , newArray, copied, copylength); copied += copylength; // increase }
return newArray; }
/** * Returns cipher used for encrypting .script files * * @return initialized cipher */ public Cipher getScriptEncipher() { return scriptEncipher; }
/** * Returns cipher used for decrypting .script files * * @return initialized cipher */ public Cipher getScriptDecipher() { return scriptDecipher; }
/** * Returns calculated byte array size for <code>inputBytes</code> * for actual cache cipher (also checksum cipher if field checksum * is requested). * * @param inputBytes no of bytes of storage used * @return no of calculated storage bytes */ public int calculateCacheSize(int inputBytes) { int size = ;
size = cacheCipher.getOutputSize(inputBytes);
// include integrity checksum size size += getFieldChecksumSize(); return size; }
/** * Returns actual checksum size in bytes. * * @return no of checksum bytes */ public int getFieldChecksumSize() { if (isFieldChecksum()) return checksumCipher.getMacLength(); else return ; }
/** * Encrypts fieldBytes for given row and column identificators and returns result. * Encryption will be made using chosen key for given field. * * @param fieldBytes bytes to be encrypted * @param row row identificator (same as record identificator) * @param column column identificator (same as field identificator) * @return encrypted bytes * @throws SQLException if encryption fails */ public byte[] encryptField(byte[] fieldBytes, int row, int column) throws SQLException { byte[] encryptedBytes = null; try { cacheCipher.init(Cipher.ENCRYPT_MODE, getFieldKey(row, column), cacheIv); encryptedBytes = cacheCipher.doFinal(fieldBytes); } catch (Exception e) { throw new SQLException(e.getMessage()); } return encryptedBytes; }
/** * Decrypts fieldBytes for given row and column identificators and returns result. * Decryption will be made using chosen key for given field. * * @param fieldBytes bytes to be decrypted * @param row row identificator (same as record identificator) * @param column column identificator (same as field identificator) * @return decrypted bytes * @throws SQLException if decryption fails */ public byte[] decryptField(byte[] fieldBytes, int row, int column) throws SQLException { byte[] decryptedBytes = null; try { cacheCipher.init(Cipher.DECRYPT_MODE, getFieldKey(row, column), cacheIv); decryptedBytes = cacheCipher.doFinal(fieldBytes); } catch (Exception e) { throw new SQLException(e.getMessage()); } return decryptedBytes; }
/** * Computes checksum of fieldBytes row and column identificators and returns result. * * @param fieldBytes input bytes for checksum computation * @param row row identificator (same as record identificator)
* @param column column identificator (same as field identificator) * @return computed checksum */ public byte[] createChecksum(byte[] fieldBytes, int row, int column) { return checksumCipher.doFinal(fieldBytes); }
/** * Set integrity check indicator for value <code>check</code> * * @param check integrity check indicator */ public void setFieldChecksum(boolean check) { fieldChecksum = check; }
/** * Returns <code>true</code> if integrity check of row fields in cache files * is on, <code>false</code> otherwise * * @return integrity check indicator */ public boolean isFieldChecksum() { return fieldChecksum; }}
EncryptedRowOutputpackage org.hsqldb;
import java.io.*;import java.math.*;import java.security.SecureRandom;import java.sql.*;
/** * Provides methods for encrypting and writting data for a row to a * byte array. * <p>Copyright: Copyright (c) The HSQL Development Group</p> * @author Pavol Markovič * @version ..e */public class EncryptedRowOutput extends BinaryServerRowOutput implements EncryptedRowOutputIn-terface { protected CipherCentral cCentral; protected static SecureRandom prng;
private ByteArrayOutputStream byteOut; private DataOutputStream dataOut;
public final static int DEFAULT_CHAR_SIZE = ; public final static int DEFAULT_BINARY_SIZE = ; public final static int DEFAULT_NUMERIC_SIZE = ; public final static int DEFAULT_OBJECT_SIZE = ;
/** * Constructor used for a Result row * * @param row <code>CachedRow</code> to be written encrypted * @exception IOException when an IO error is encountered */ public EncryptedRowOutput(CachedRow row) throws IOException { super(row.storageSize); cCentral = row.getTable().dDatabase.getCipherCentral();
EncryptedRowOutput
// init static random generator (for all instances) if (prng == null) { try { prng = SecureRandom.getInstance(“SHAPRNG”); } catch (java.security.NoSuchAlgorithmException nsae) { throw new IOException(nsae.getMessage()); } }
byteOut = new ByteArrayOutputStream(); dataOut = new DataOutputStream(byteOut); }
/** * This method is called to write data for a table * * @param data * @param t * @param pos * @throws IOException * @throws SQLException */ public void writeData(Object data[], Table t, int pos) throws IOException, SQLException {
int[] types = t.getColumnTypes(); int l = types.length;
if (skipSystemId) { l--; }
writeData(l, types, data, pos); }
/** * This method is called to write data for a Result * * @param l * @param types * @param data * @param pos * @throws IOException * @throws SQLException */ public void writeData(int l, int types[], Object data[], int pos) throws IOException, SQLException {
for (int i = ; i < l; i++) { Object o = data[i]; int t = types[i];
byteOut.reset(); // reset to start point
writeRandomBytes(, dataOut); // write random bytes at the beginning
if (o == null) { writeNullData(t, dataOut); } else { switch (t) {
case Types.CHAR: case Types.VARCHAR: case Column.VARCHAR_IGNORECASE: case Types.LONGVARCHAR: byte[] _bytes = ((String) o).getBytes(“utf-”); dataOut.writeInt(_bytes.length); dataOut.write(_bytes);
break;
case Types.TINYINT: case Types.SMALLINT: dataOut.writeInt(getDefaultSize(t)); dataOut.writeShort(((Number) o).intValue()); break;
case Types.INTEGER: dataOut.writeInt(getDefaultSize(t)); dataOut.writeInt(((Number) o).intValue()); break;
case Types.BIGINT: dataOut.writeInt(getDefaultSize(t)); dataOut.writeLong(((Number) o).longValue()); break;
case Types.REAL: case Types.FLOAT: case Types.DOUBLE: dataOut.writeInt(getDefaultSize(t)); dataOut.writeLong(Double.doubleToLongBits((((Double) o).doubleValue()))); break;
case Types.NUMERIC: case Types.DECIMAL: BigDecimal _bigdec = (BigDecimal) o; int _scale = _bigdec.scale(); BigInteger _bigint = _bigdec.unscaledValue(); byte[] _bytearr = _bigint.toByteArray(); dataOut.writeInt(_bytearr.length + ); // add scale number length to byte array length dataOut.write(_bytearr); dataOut.writeInt(_scale); break;
case Types.BIT: dataOut.writeInt(getDefaultSize(t)); dataOut.writeBoolean(((Boolean) o).booleanValue()); break;
case Types.DATE: dataOut.writeInt(getDefaultSize(t)); dataOut.writeLong(((java.sql.Date) o).getTime()); break;
case Types.TIME : dataOut.writeInt(getDefaultSize(t)); dataOut.writeLong(((java.sql.Time) o).getTime()); break;
case Types.TIMESTAMP: dataOut.writeInt(getDefaultSize(t)); dataOut.writeLong(((java.sql.Timestamp) o).getTime()); dataOut.writeInt(((java.sql.Timestamp) o).getNanos()); break;
case Types.OTHER: byte[] _ba = ByteArray.serialize(o); dataOut.writeInt(_ba.length); dataOut.write(_ba); break;
case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: dataOut.writeInt(((byte[]) o).length); dataOut.write((byte[]) o); break;
default: throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, t); } }
dataOut.flush(); //flush all unwritten bytes
byte[] bytes = byteOut.toByteArray(); // get data to encrypt byte[] encryptedBytes = cCentral.encryptField(bytes, pos, i); // encrypt data byte array writeInt(encryptedBytes.length); // write encrypted blocks length in bytes write(encryptedBytes); // write encrypted data if (cCentral.isFieldChecksum()) { int clearDataLength = bytes.length - ; // length - random bytes - length indicator bytes byte[] objectData = new byte[clearDataLength]; System.arraycopy(bytes, , objectData, , clearDataLength); // copy clear data byte array write(cCentral.createChecksum(objectData, pos, i)); // and write checksum }
} }
/** * Calculate the size of byte array required to store a row. * * @param row a database row * @return size of byte array * @throws SQLException When data is inconsistent */ public static int getSize(CachedRow row) throws SQLException {
Object data[] = row.getData(); int type[] = row.getTable().getColumnTypes();
return getSize(data, data.length, type, row.getTable().dDatabase.getCipherCentral()); }
/** * Private method to calculate the size of byte array required to store a row. * * @param data the row data * @param l number of data[] elements to include in calculation * @param type array of java.sql.Types values * @param central current CipherCentral object * @return size of byte array * @throws SQLException when data is inconsistent */ private static int getSize(Object data[], int l, int type[], CipherCentral central) throws SQLException {
int s = ;
for (int i = ; i < l; i++) { Object o = data[i]; int t = type[i]; int csum = ; //cleartext sum
csum += ; // add random bytes + byte encrypted block length
switch (t) {
case Types.CHAR: case Types.VARCHAR: case Column.VARCHAR_IGNORECASE: case Types.LONGVARCHAR: csum += ((o == null) ? getDefaultSize(t) : getUTFSize((String) o)); break;
case Types.NUMERIC:
case Types.DECIMAL: csum += ((o == null) ? getDefaultSize(t) : (((BigDecimal) o).unscaledValue().toByteArray().length + )); // unscaled value length + bytes scale integer break;
case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: csum += ((o == null) ? getDefaultSize(t) : ((byte[]) o).length); break;
case Types.OTHER: csum += ((o == null) ? getDefaultSize(t) : ByteArray.serialize(o).length); break;
default: csum += getDefaultSize(t); //for all other types (fixed length), get default value break; }
s += ; // add bytes encrypted block length indicator s += central.calculateCacheSize(csum); // encrypted block length }
return s; }
/** * Writes desired random bytes to <code>DataOutputStream</code> * * @param byteCount - numer of random bytes to write * @param out - DataOutputStream object to write bytes * @throws IOException * @since ..e */ private void writeRandomBytes(int byteCount, DataOutputStream out) throws IOException { byte[] randomBytes = new byte[byteCount]; prng.nextBytes(randomBytes); out.write(randomBytes); }
/** * Writes null object - random bytes with zero size indicator * * @param type - SQL type * @param out - DataOutputStream object to write bytes * @returns number of written bytes * @throws IOException * @throws SQLException * @since ..e */ private int writeNullData(int type, DataOutputStream out) throws IOException, SQLException { int size = getDefaultSize(type); out.writeInt(); // this indicates NULL object writeRandomBytes(size, out); return (size + ); // random bytes + bytes size indicator }
/** * Returns default size for chosen SQL Type * * @param type - SQL type * @returns number of written bytes * @throws SQLException * @since ..e */ private static int getDefaultSize(int type) throws SQLException {
int size = ;
switch (type) {
case Types.CHAR: case Types.VARCHAR: case Column.VARCHAR_IGNORECASE: case Types.LONGVARCHAR: size = DEFAULT_CHAR_SIZE; break;
case Types.TINYINT: case Types.SMALLINT: size = ; break;
case Types.INTEGER: size = ; break;
case Types.BIGINT: case Types.REAL: case Types.FLOAT: case Types.DOUBLE: size = ; break;
case Types.NUMERIC: case Types.DECIMAL: size = DEFAULT_NUMERIC_SIZE; break;
case Types.BIT: size = ; break;
case Types.DATE: case Types.TIME: size = ; break;
case Types.TIMESTAMP: size = ; break;
case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: size = DEFAULT_BINARY_SIZE; break;
case Types.OTHER: size = DEFAULT_OBJECT_SIZE; break;
default: throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, type); } return size; }
/** * Calculate the size of byte array required to store a string in utf. * * @param s - string to convert * @return size of the utf string */ private static int getUTFSize(String s) {
// a bit bigger is not really a problem, but never smaller! int len = (s == null) ? : s.length(); int l = ; // length
for (int i = ; i < len; i++) { int c = s.charAt(i);
if ((c >= x) && (c <= xF)) { l++; } else if (c > xFF) { l += ; } else { l += ; } }
return l; }}
EncryptedRowInputpackage org.hsqldb;
import java.io.*;import java.math.*;import java.sql.*;import java.util.Arrays;
/** * Provides methods for reading and decrypting data for a row from a * byte array. * <p>Copyright: Copyright (c) The HSQL Development Group</p> * @author Pavol Markovič * @version ..e */public class EncryptedRowInput extends BinaryServerRowInput implements EncryptedRowInputInterface {
public EncryptedRowInput(byte bin[], int pos) throws IOException { super(bin, pos); }
/** * Reads encrypted row data from a file stream * * @param t Current record <code>Table</code> * @param pos position in file and unique identificator * @return decrypted data for current Table row * @throws IOException When data is inconsistent * @throws SQLException When data is inconsistent */ public Object[] readData(Table t, int pos) throws IOException, SQLException { CipherCentral central = t.dDatabase.getCipherCentral();
int[] colTypes = t.getColumnTypes(); int l = colTypes.length; Object data[] = new Object[l];
if (makeSystemId) { l--; }
for (int i = ; i < l; i++) { Object o = null;
EncryptedRowInput
int type = colTypes[i]; int length; byte[] decrypted = getDecryptedData(central, pos, i); // read and decrypt data
if (central.isFieldChecksum()) { byte[] checksum = new byte[central.getFieldChecksumSize()]; // create empty byte array for checksum readFully(checksum); // read checksum
int clearDataLength = decrypted.length - ; // length - random bytes - length indicator bytes byte[] objectData = new byte[clearDataLength]; System.arraycopy(decrypted, , objectData, , clearDataLength); // copy clear data byte array
if (!compareChecksums(checksum, central.createChecksum(objectData, pos, i))) throw new IOException(“Checksum not valid at row “ + pos + “ and field “ + i + “!”); // possible place to create cover stories }
DataInputStream dataIn = new DataInputStream(new ByteArrayInputStream(decrypted)); dataIn.skipBytes(); // skip random bytes length = dataIn.readInt(); // read data length
if (length == ) { // object is null o = null; } else { // read object from byte array
switch (type) {
case Types.CHAR: case Types.VARCHAR: case Column.VARCHAR_IGNORECASE: case Types.LONGVARCHAR: o = new String(readByteArray(dataIn, length), “UTF-”); break;
case Types.TINYINT: case Types.SMALLINT: o = new Integer(dataIn.readShort()); break;
case Types.INTEGER: o = new Integer(dataIn.readInt()); break;
case Types.BIGINT: o = new Long(dataIn.readLong()); break;
case Types.REAL: case Types.FLOAT: case Types.DOUBLE: o = new Double(Double.longBitsToDouble(dataIn.readLong())); break;
case Types.NUMERIC: case Types.DECIMAL: BigInteger _bigInt = new BigInteger(readByteArray(dataIn, length)); o = new BigDecimal(_bigInt, dataIn.readInt()); break;
case Types.DATE: o = new Date(dataIn.readLong()); break;
case Types.TIME: o = new Time(dataIn.readLong());
break;
case Types.TIMESTAMP: Timestamp _ts = new Timestamp(dataIn.readLong()); _ts.setNanos(dataIn.readInt()); o = _ts; break;
case Types.BIT: o = new Boolean(dataIn.readBoolean()); break;
case Types.OTHER: o = ByteArray.deserialize(readByteArray(dataIn, length)); break;
case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY : o = readByteArray(dataIn, length); break;
default : throw Trace.error(Trace.FUNCTION_NOT_SUPPORTED, type); } }
data[i] = o; }
if (makeSystemId) { data[l] = new Integer(getPos()); }
return data; }
/** * Reads encrypted data blocks for specified record and field * and returns decrypted byte array * * @param central Current <code>CipherCentral</code> * @param pos record position in file * @param field field index * @return decrypted byte array * @throws SQLException When data is inconsistent */ protected byte[] getDecryptedData(CipherCentral central, int pos, int field) throws SQLException { byte[] decrypted = null; try { byte[] bytes = new byte[readInt()]; // read encrypted blocks length and create empty byte array readFully(bytes); // read encrypted blocks into array
decrypted = central.decryptField(bytes, pos, field); // decrypt byte array } catch (IOException ioe) { throw new SQLException(ioe.getMessage()); }
return decrypted; }
/** * Reads and returns byte array from specified <code>DataInputStream</code> * * @param in Current <code>CipherCentral</code> * @param length record position in file * @return byte array * @throws IOException When data is inconsistent
*/ protected byte[] readByteArray(DataInputStream in, int length) throws IOException { byte[] bytes = new byte[length]; in.readFully(bytes); return bytes; }
/** * Reads encrypted data blocks for specified record and field * and returns decrypted byte array * * @param ch first checksum * @param ch second checksum * @return <code>true</code> if checksums are equal, <code>false</code> otherwise */ protected boolean compareChecksums(byte[] ch, byte[] ch) { return Arrays.equals(ch, ch); }}
.
CompareTestpackage org.hsqldb.test;
import java.io.*;import java.sql.*;
/** * Test large cached tables by setting up a cached table of records * or more and a much smaller memory table with about /th rows used. * Populate both tables so that an indexed column of the cached table has a * foreign key reference to the main table. * * This database can be used to demonstrate efficient queries to retrieve * the data from the cached table. * */public class CompareTest { protected String url = “jdbc:hsqldb:”; protected String filepath = “hsql://localhost”; String user; String password; Statement sStatement; Connection cConnection; boolean indexZip = true; boolean indexLastName = false; boolean addForeignKey = false; boolean refIntegrity = false; boolean createTempTable = false;
protected void setUp() { user = “sa”; password = “”; }
/** * Fill up the cache * * */ public void testFillUp(int number) { int bigrows = number;
CompareTest
int smallrows = xfff; double value = ;
System.out.println(“Run test with: “ + number + “ items”); String ddl = “DROP TABLE test IF EXISTS;” + “DROP TABLE zip IF EXISTS;”; String ddl = “CREATE TABLE zip( zip INT IDENTITY );”; String ddl = “CREATE “/* +”CACHED “*/ + “TABLE test( id INT IDENTITY,” + “ firstname VARCHAR, “ + “ lastname VARCHAR, “ + “ zip INTEGER, “ + “ filler VARCHAR); “;
// adding extra index will slow down inserts a bit String ddl = “CREATE INDEX idx ON TEST (lastname);”;
// adding this index will slow down inserts a lot String ddl = “CREATE INDEX idx ON TEST (zip);”;
// referential integrity checks will slow down inserts a bit String ddl = “ALTER TABLE test add constraint c FOREIGN KEY (zip) REFERENCES zip(zip);”; String ddl = “CREATE TEMP TABLE temptest( id INT,” + “ firstname VARCHAR, “ + “ lastname VARCHAR, “ + “ zip INTEGER, “ + “ filler VARCHAR); “; String filler = “ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ” + “ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ”;
try { System.out.println(“connect”); System.out.println( new java.util.Date(System.currentTimeMillis()));
cConnection = null; sStatement = null; cConnection = DriverManager.getConnection(url + filepath, user, password);
System.out.println(“connected”); System.out.println( new java.util.Date(System.currentTimeMillis()));
sStatement = cConnection.createStatement();
java.util.Random randomgen = new java.util.Random();
sStatement.execute(ddl); sStatement.execute(ddl); sStatement.execute(ddl); System.out.println(“test table with no index”);
if (indexLastName) { sStatement.execute(ddl); System.out.println(“create index on lastname”); }
if (indexZip) { sStatement.execute(ddl); System.out.println(“create index on zip”); }
if (addForeignKey) { sStatement.execute(ddl); System.out.println(“add foreign key”); }
if (createTempTable) { sStatement.execute(ddl); System.out.println(“temp table”); }
int i;
for (i = ; i <= smallrows; i++) { sStatement.execute(“INSERT INTO zip VALUES(null);”); }
sStatement.execute(“SET REFERENTIAL_INTEGRITY “ + this.refIntegrity + “;”);
PreparedStatement ps = cConnection.prepareStatement( “INSERT INTO test (firstname,lastname,zip,filler) VALUES (?,?,?,?)”);
ps.setString(, “Julia”); ps.setString(, “Clancy”);
long startTime = System.currentTimeMillis();
for (i = ; i < bigrows; i++) { ps.setInt(, randomgen.nextInt() & smallrows);
long nextrandom = randomgen.nextLong(); int randomlength = (int) nextrandom & xf;
if (randomlength > filler.length()) { randomlength = filler.length(); }
String varfiller = filler.substring(, randomlength);
ps.setString(, nextrandom + varfiller); ps.execute(); }
long endTime = System.currentTimeMillis();
System.out.println(i); System.out.println(new java.util.Date(endTime)); System.out.println(“Insert Time:” + (endTime - startTime)); try { sStatement.execute(“SHUTDOWN;”); cConnection.close(); } catch (SQLException e) { ; } finally { System.out.println(“Shutdown Time:” + (System.currentTimeMillis() - endTime)); } } catch (SQLException e) { System.out.println(e.getMessage()); } }
protected void checkResults() {
try { long startTime = System.currentTimeMillis(); cConnection = DriverManager.getConnection(url + filepath, user, password); sStatement = cConnection.createStatement();
sStatement.execute(“SELECT count(*) from TEST”); long endTime = System.currentTimeMillis(); System.out.println(“Checked results:” + (endTime - startTime)); try { sStatement.execute(“SHUTDOWN;”); cConnection.close(); }
catch (SQLException e) { ; } finally { System.out.println(“Shutdown Time:” + (System.currentTimeMillis() - endTime)); } } catch (SQLException e) { System.out.println(e.getMessage()); } }
public static void main(String argv[]) { try { Class.forName(“org.hsqldb.jdbcDriver”); } catch (ClassNotFoundException e) { e.printStackTrace(); } CompareTest test = new CompareTest();
test.setUp(); if (argv.length > ) { if (argv[].equalsIgnoreCase(“-fill”)) test.testFillUp(Integer.parseInt(argv[])); else if (argv[].equalsIgnoreCase(“-check”)) test.checkResults(); else System.out.println(“use -fill or -check”); } else System.out.println(“use -fill or -check”); }}
: ELEKTRONICKÝ NOSIČ
. (-)
OchranaDBUdajov/
DOC/
Anotacia.pdf – anotácia v slovenskom a anglickom jazyku
diplomovapraca.pdf – textová časť diplomovej práce
javadoc/ – dokumentácia k implementácii
LIB/
hsqlcryptodb.jar – výsledný produkt diplomovej práce
jce-jdk13-115.jar – kryptografi cký modul poskytovateľa BouncyCastle optional/
hsqldb_1_7_1.zip – kompletná inštalácia pôvodné systému
j2sdk-1_4_1_01-linux-i586-rpm.bin – .. pre Linux
j2sdk-1_4_1_01-windows-i586.exe – .. pre Windows
jakarta-ant-1.5.1-bin.zip – .. – Java alternatíva k systému make jce-1_2_2.zip – .. pre .. a nižšie
junit3.8.1.zip – JUnit .. – šablóny pre testovanie
src/ – kompletné zdrojové texty
.
Implementový systém sa nachádza v balíku hsqlcryptodb.jar. Tento balík je naj-
vhodnejšie prekopírovať medzi externé knižnice Javy (<java-home>/lib/ext/) spolu
s kryptografi ckým modulom jce-jdk-.jar. Ak to nie je možné alebo žiadúce,
potom je potrebné pred spustením systému uviesť cestu k týmto balíkom cez prepí-
nač -classpath.
Žiadna inštalácia nie je potrebná, ak máte v operačnom systéme nainštalovanú
podporu pre Javu ( alebo ) verzie . a vyššie. V adresári optional sa nachá-
dzajú inštalačné balíky verzie .. pre Linux a Windows.
Ak máte staršiu verziu podpory Javy (verzia .. a nižšie), potom musíte nainšta-
lovať .. a vyššie (v adresári optional je verzia ..) podľa pokynov priložených
pokynov.
Ak chcete kompilovať zdrojové súbory, je možné, že budete potrebovať Ant alebo
JUnit, tiež sú priložené v adresári optional.
D
.
Systém sa spúšta pri odporúčanej inštalácii z príkazového riadku:
java org.hsqldb.Server -database <názov>
kde <názov> predstavuje názov databázy, prípadne spolu s cestou k nej.
Šifrovacie algoritmy sa vyberajú prepínačmi:
-sc <šifra> pre šifrovanie záznamového (script) súboru
-cc <šifra> pre šifrovanie údajového (cache/data) súboru
-mc <šifra> pre kontrolu integrity údajového (cache/data) súboru
Možnosti výberu <šifra> sú uvedené v . ..
Kontroly integrity sa zapína prepínačom:
-checksum <true/false> štandardne je false
Nápoveda sa zobrazí po zadaní prepínača -?
Systém sa zastavuje/ukončuje príkazom .
.
K databázovému systému sa pristupuje štandardným spôsobom cez rozhranie.
driver je implementovaný v triede:
org.hsqldb.jdbcDriver
pre pripojenie je potom:
jdbc:hsqldb:hsql://<adresa_servera>
Ak sa pripájate na systém spustený na rovnakom počítači, potom <adresa_servera>
je buď localhost alebo ....
Alternatívne je možné systém spustiť v standalone móde cez :
jdbc:hsqldb:<názov>
Systém sa vtedy zastaví po zrušení spojenia.
Pozn.: V standalone móde nie je možné vyberať šifrovacie algoritmy.
LITERATÚRA
[] C, G. et al.: Th e Design and Implementation of a Transparent
Cryptographic Filesystem for UNIX. Universit di Salerno, .
[] Cloudscape Developer‘s Guide Version .. IBM Corporation, .
[] Common Security: CDSA and CSSM, Version .. Open Group, .
[] D, G. I., W, D. L., K, J. B.: A database encryption systems with
subkeys. ACM Transactions on Database systems, (). , s. – .
[] D, M. A.: Database Encryption in Oraclei. Oracle Corporation,
.
[] DbEncrypt for Microsoft SQL Server User Guide. Application Security, .
[] D, D. E.: Field Encryption and Authentication. Advances in
Cryptology: Proceedings of CRYPTO . Springer-Verlag, .
[] Encrypting File System for Windows . Microsoft Corporation, .
[] FIPS - – Security Requirements for Cryptographic Modules. National
Institute of Standards and Technology, .
[] IBM DB UDB v. and Oraclei – A Technical Comparison. PASS
Consulting Group, .
[] IBM DB Universal Database Version – Administration Guide:
Implementation. IBM Corporation, .
[] IBM DB Universal Database Version – SQL Reference. IBM Corporation,
.
[] Inside Carbon: Carbon Porting Guide for Mac OS X. Apple Computer, .
[] M, U., V, R., S, W.: How to Build a Trusted
Database System on Untrusted Storage. STAR Lab, Intertrust Technologies
Corporation, .
[] M, A., V O, P., V, S.: Handbook of Applied
Cryptography. CRC Press, Inc., .
[] M, R.: Oraclei Security Overview, Release (..). Oracle
Corporation, .
[] N, K., R, T. R. N.: Cryptographic models for DBMS Communications.
In K. H. Kim, K. Chom and C. V. Ramamoorthy, editors, Proceedings of
Pacifi c Computer Communications ‘. North-Holland, , s. – .
[] --: Th e Trusted Database Management System Interpretation.
National Computer Security Center, .
[] O, K. A., W, D. L.: Modifi ed architecture for the subkeys model. In:
Proceedings of the Symposium on Security and Privacy, Oakland,
CA. Computer Society, Apríl , s. -
[] Oraclei Database Security for eBusiness. Oracle Corporation, .
[] P, J.: Cryptology. Preprint.
[] , v., Password-Based Cryptography Standard. RSA Laboratories,
.
[] R, N. K., S, A., B, R. M.: Automated Biometrics. IBM
Corporation, .
[] Waymire, R., Th omas, B.: Microsoft SQL Server Security. Microsoft
Corporation, .
[] S, A.: Applied Cryptology. J. Wiley, .
[] W, S. R.: Using for the Military Airlift Command Example
Database. In: B. M. Th uraisingham and C. E. Landwehr, Database Security
VI.: Status and Prospects (A-), IFIP, North-Holland, , s. – ,
---.
[] Th e Bouncy Castle Crypto Package Specifi cations, version ..
http://www.bouncycastle.org (. . ).
[] TPC Benchmark™ H Standard Specifi cation, Revision ... Transaction
Processing Performance Council, .
[] Z, P.: Th e Database Security Blanket. DB Magazine, Spring .