Naši partneři
BMI SYSTEM CZECH
Informační systémy budoucnosti

Šifrování dat v položce tabulky


Nejprve trocha teorie

MS SQL Server 2008 umí šifrovat celou databázi, a to velmi výkonným mechanismem, který si popíšeme někdy příště, ale verze 2005 nic podobného nemá. Přesto SQL Server 2005 umožňuje šifrovat data, a to například pomocí funkcí EncryptByAsymKey a DecryptByAsymKey.

MS SQL Server může sám fungovat jako certifikační autorita, poskytuje služby tvorby klíčů a certifikátů, a také umožňuje export certifikátů do souboru, a opačně import certifikátu získaného souborem zpět na SQL server. Certifikáty a klíče jsou ukládány jako objekty SQL serveru, takže pokud s nimi budeme pracovat, nevzniká nutnost zálohování dalších entit mimo SQL server.

Jedinou výjimku tvoří tzv. "service master key", který vzniká už při instalaci SQL Serveru. Tento asynchronní klíč, resp. jeho hodnota je použita při generování všech ostatních klíčů, a proto ve chvíli, kdy začneme s vyspělým šifrováním dat pracovat, a tedy generovat vlastní klíče, nezapomeňme service master key zálohovat. Kdybychom zálohu neprovedli, a z nějakého důvodu přišli o databázi master, novou instalací už nikdy nezískáme stejnou hodnotu klíče, takže všechny odvozené klíče by byly nepoužitelné, což je ještě malý problém, ale zašifrovaná data by byla nenávratně ztracena. Pro úplnost dodávám, že příkaz pro zálohu je BACKUP SERVICE MASTER KEY, a je snadno nalezení v SQL Server Books Online.

 
Tvoříme klíč

Když chceme šifrovat data, nejprve vytvoříme v dané databázi klíč, například:

CREATE ASYMMETRIC KEY Klic
WITH ALGORITHM = rsa_2048
ENCRYPTION BY PASSWORD = 'dropman'
go

Jak je vidět, pouze vybereme algoritmus (máme na výběr z RSA, 3Des, MD5 a SHA1), a zvolíme heslo. Heslo potom slouží k tomu, že klíč "vydá" svou hodnotu tomu, kdo heslo zná. Heslo by samozřejmě mělo být komplexnější než to, které jsem zvolil, ale reklama je reklama.

 
Použití klíče

K zašifrování dat slouží skalární funkce EncryptByAsymKey. Funkce na vstupu vyžaduje parametr ID vytvořeného klíče, ale toto ID je snadné získat pomocí funkce ASYMKEY_ID. Druhý parametr je potom samotná "čistá" podoba šifrované hodnoty. Funkce EncryptByAsymKey striktně vyžaduje, aby vstupující hodnota k zašifrování byla datového typu nvarchar, proto nesmíme zapomenout na písmenko N! Výstupem funkce je hodnota typu varbinary, a tak ji také musíme ukládat do tabulky.

Nejprve se podívejme na jednoduchý příklad volání funkce:

SELECT EncryptByAsymKey(AsymKey_ID('Klic'), N'nejaka hodnota')

A teď, pro jistotu zkusme hodnotu ještě uložit do tabulky:

CREATE TABLE Test
(
Id int not null identity,
sifra varbinary(255),
CONSTRAINT pk_Test PRIMARY KEY (Id)
)
GO

INSERT Test (Sifra) VALUES (EncryptByAsymKey(AsymKey_ID('Klic'), N'nejaka hodnota'))

SELECT * FROM Test
GO

Není to složité, viďte? A teď jsme o kus dál, a potřebujeme se k hodnotě, kterou jsme předtím zašifrovali, nějak dostat a přečíst ji. K tomu slouží funkce DecryptByAsymKey, která jako parametry potřebuje opět ID klíče, dále varbinary hodnotu, kterou chceme dešifrovat, a jako třetí parametr (opět striktně typu nvarchar!) heslo, které musíme znát, chceme-li získat hodnotu v její "čisté" podobě.

POZOR! Výsledek funkce DecryptByAsymKey je opět typu varbinary, a je tedy nutno jej konvertovat zpět na nvarchar.

Opravdu si dejte pozor, abyste někde nezapomněli, že všechny řetězce jsou v UNICODE formátu. Stačí se zapomenout na jediném místečku, a výsledek bude NULL.

Už jsem vás postrašil dost, takže pojďme z databáze přečíst šifrovanou hodnotu:


SELECT id, sifra, CAST(DecryptByAsymKey(AsymKey_ID('Klic'), sifra, N'dropman') AS nvarchar(50)) FROM test

Teď bych se měl zeptat jako ten kouzelník v hloupém TV pořadu, jestli je to ta karta, vlastně hodnota, kterou jsem měl na mysli, a určitě to bude ona. Takže zašifrovat konkrétní data, jak vidno, s trochou cviku není až tak veliký problém.

 
Kde je tedy háček?

Výkonnost. To je odpověď na otázku z nadpisu. Pokud si budeme hrát s naší tabulkou Test, do které vložíme (možná) i více, než jeden záznam, bude to všechno krásné. Ale představme si situaci, kdy máme tabulku s uživateli nějaké aplikace, a chceme zabezpečit jejich hesla. Uživatelů budou řádově tisíce i více, a když budeme při přihlašování ověřovat uživatelské jméno a heslo, se zlou se potážeme, protože se budeme pokoušet porovnávat složitá binární data! Jak z toho ven? Musíme zkusit porovnat něco jednoduššího. A co je jednoduššího (když pominu bit), než obyčejný integer?

Takže řešení je toto: Existuje funkce CHECKSUM. Jen pro úplnost - je to funkce, která vypočítá pro zadanou hodnotu její kontrolní součet, který má tyto vlastnosti:
- pro dva různé řetězce je různý (jinak by toho moc nezkontroloval)
- nemá reverzní mechanismus, takže nevíme, jakou hodnotu CHECKSUM kontroloval

Proto obohatíme tabulku Test o sloupec, do kterého uložíme CHECKSUM šifrované hodnoty:

ALTER TABLE Test ADD chkSum int NULL
GO

Do položky chkSum uložíme kontrolní součet zašifrované hodnoty:

UPDATE Test SET chkSum = CHECKSUM(N'nejaka hodnota')
GO

A když budeme potom ověřovat našeho imaginárního uživatele, zjistíme podle kontrolního součtu zadaného hesla, že heslo je správné. Také tím získáme záznam, který obsahuje i zašifrované heslo, a snadno otestujeme, šifrovanou hodnotu jednoho záznamu.

Možná, že to zní divoce, ale předpokládejme, že jedinečnost uživatelů je dána kromě Id záznamu v tabulce uživatelů také kombinací Jméno / Heslo, v tom případě mohou být v tabulce dva uživatelé s jedním jménem, ale různým heslel, a integerová položka chkSum je, narozdíl od položky typu varbinary, indexovatelná, takže můžeme vytvořit jedinečný index nebo constraint unique na jméno uživatele a checksum jeho hesla.

 
Závěrem

Závěrečný příklad s uživateli byl, pravda, poněkud samoúčelný, ale nechtěl jsem popisovat skutečnou situaci, ve které mi tato finta pomohla, a to kvůli zestručnění. Zároveň jsem načal sérii článků, kterou bych chtěl inspirovat ostatní kolegy, a mimořádně mě zajímají Vaše názory na to, zda jsem se vydal správnou cestou, případně co by vás zajímalo.

 
Sdílejte tuto položku se svými přáteli
 
Související články
TOPlist