Hashing SQL Serverrel

Véletlen belefutottam egy T-SQL függvénybe, amit úgy hívnak, hogy HashBytes. Ez képes MD2, MD4, MD5, SHA és SHA1 hasht gyártani varchar, nvarchar és varbinary értékekből vagy változókból.

DECLARE @str varchar(10) = 'mintaminta'
SELECT HASHBYTES('MD5', @str)

Ez azt mondja, hogy 0x94B15DFD3AA83BBBB3B79DED6D57259F. Ráadásul a hashing algoritmus is paraméterezhető, azaz a rendszer megeszi ezt is:

DECLARE @str varchar(10) = 'mintaminta', @alg varchar(4) = 'SHA1'
SELECT HASHBYTES(@alg, @str)

De mire jó a hash? Ez egy egyirányú transzformációja értékeknek (pontosabban a transzformációnak, azaz hashelésnek az eredménye), ahol az eredménynek ránézésre semmi köze nincs a bemenethez. Két nagy halmazra lehet bontani a hash algoritmusokat: olyanokra, ahol nagy valószínűséggel vannak egyforma értékek különböző bemeneteknél, és olyanokra, ahol nagy valószínűséggel nincsenek. Előbbieket csoportok képzésére szokták használni, például keresést elősegítendő: az elemeket hasheljük, és a hashnek megfelelő dobozba tesszük. Ha valaki keres egy elemet, akkor csinál egy hasht, és megnézi az adott hash-sel rendelkező dobozban, hogy van-e olyan elem. Ez DBA-knak hatékonytalannak tűnhet, de nem lehet mindenkinek egy SQL Server a zsebében.

A második csoport egyik esete a “titkosítás”. Azért teszem idézőjelbe, mert a régi hashekre általában létezik “workaround”, azaz ki lehet trükközni őket. Itt az a lényeg, hogy két különböző bemenetnek tök különböző kimenete van, a legkisebb változtatás a bemeneten teljesen megváltoztatja a kimenetet, előre megjósolhatatlan módon. Például jelszavak helyett szokás a jelszavak hashét tárolni. Azonosításnál a szerver megint hashel, és ha stimmel a hash, akkor az azonosítást sikeresnek veszi. Ez jó, mert azok, akik hozzáférnek az adatbázishoz sem tudnak visszaélni a jelszóval. Baj akkor van, ha valaki képes egy hash alapján bemenetet gyártani, azaz a definíció szerint egyirányú függvényt kétirányúsítja. Ekkor ugyanis az egész módszer varázsát (és hasznát) veszíti. Ez a hash collision, azaz összekavarás ütközés magyarul.

Amúgy ezt nem a summiton tanultam, csak most van időm olvasni – azért jólesik rájönni, hogy mégiscsak töltök időt a családommal :)

UPDATE:
Ha valakinek a “klasszikus”, azaz nem bináris, hanem string hash kell, azt a következő módon tudja kicsiholni:

DECLARE @str varchar(10) = 'mintaminta', @alg varchar(4) = 'SHA1'
SELECT HASHBYTES(@alg, @str)
SELECT SUBSTRING(master.sys.fn_sqlvarbasetostr(HASHBYTES(@alg, @str)),3,128)

Tessék észrevenni, hogy a kettő ugyanaz szemmel olvasásra (leszámítva a hexa előtagot a binárisban, amit a substringgel vágtunk le).

Leave a comment