Přeskočit na hlavní obsah

Funkce pro hashování hesel

Jednocestných hashovacích funkcí existuje celá řada. Které z nich jsou pro účely ukládání hesel do databáze vhodné? A které jsou naopak nevhodné či dokonce nebezpečné? Jak se vypořádat se změnou použitého algoritmu za běhu aplikace?

Kolize vás neohrozí

Rozruch v posledních třech letech vyvolávají nové postupy, pomocí nichž lze pro některé tradiční hashovací funkce spočítat kolize. Neboli systematicky najít dva různé vstupní řetězce, které vedou na stejný otisk. Výpočetní náročnost pro některé algoritmy později ještě výrazně zkrátil český kryptolog Vlastilmil Klíma svou metodou tunelování. Možnost nalezení kolizí se týká celé řady algoritmů, zejména MD4, MD5, HAVAL-128, RIPEMD, SHA-0, SHA-1. V důsledku toho jsou tyto funkce zneužitelné pro falšování podpisů softwarových balíků nebo padělání certifikátů.

Pro účely hashování hesel do databáze však možnost nalezení kolizí nepředstavuje žádné riziko. Stále totiž platí, že pouze ze znalosti otisku není možné v rozumném čase spočítat jakýkoliv původní řetězec. Obecně je tedy v našem případě možné i nadále tyto funkce bez obav používat. Výjimkou ze zmíněných jsou funkce MD4 a SHA-0, které by se již neměly využívat vůbec na nic.

Jistota je jistota

Pokud i přesto ke zmíněným algoritmům cítíte nedůvěru, je nutné se poohlédnout jinam. Nejčastěji pak asi sáhnete po některé funkci z rodiny SHA-2. Pod tímto souhrnný označením se skrývají čtyři algoritmy – SHA-256, SHA-384, SHA-512 a SHA-224. Zpravidla si vystačíte s prvním z nich. Použití těchto funkcí je zcela bezpečné v tom smyslu, že u nich zatím neexistuje žádný způsob pro nalezení kolizí. Pro hashování hesel do databáze je SHA-256 v současné době i moje preferovaná volba.

Dále se nabízí například funkce Whirlpool, která je postavena na trošku jiných základech, než ostatní dosud jmenované algoritmy. Nemusela by být tedy teoreticky ani v budoucnu náchylná na principielně podobná oslabení. Problémem u ní je, že jsem zatím nenalezl žádnou její JavaScriptovou implementaci, takže v jejím případě pak není možné použít metodu Challenge/Response (o tom ale zase až někdy jindy).

Myslete na budoucnost

Občas nastane situace, kdy je potřeba v aplikaci změnit používanou hashovací funkci. To nelze udělat výměnou jednoho řádku kódu – všichni dosavadní uživatelé mají totiž svá hesla zahashovaná starým algoritmem. Hromadně přepočítat je nelze – není žádný způsob, jak se dostat k původní nezahashované podobě uchovaných hesel.

Při návrhu databázové tabulky s uživateli proto doporučuji vedle sloupce pro uživatelské jméno a zahashované heslo založit ještě jeden sloupec, kde se bude pro každého uživatele sledovat použitý hashovací algoritmus. V případě změny preferované funkce se i tak budou moci existující uživatelé přihlásit. Následně můžete například hned vynutit změnu hesla a nové již uložit s aktuálním algoritmem. Také pak není problém v paralelním souběhu několika různých algoritmů vedle sebe.

Hashovací funkce v PHP

Některé tradiční algoritmy mají v PHP definovány své vlastní funkce – například md5() nebo sha1(). Univerzální přístup nabízí funkce hash(), která je k dispozici standardně od PHP 5.1.2 (ve starších verzích je nabízena v rámci PECL balíčku). Seznam všech podporovaných algoritmů získáte pomocí hash_algos().

Credits

Děkuji Vlastimilu Klímovi za užitečnou konzultaci při psaní tohoto článku.

Komentáře

  1. o PHP toho moc nevim, mam za sebou jen par mensich projektiku bez ostryho nasazeni a bezpecnost je uz uplne spanelska vesnice, ale neco me napadlo ke zminene zmene hashovaci funkce na novsi. kdyz mam v databazi ktery algoritmus pouzivam a neznam uzivatelovo heslo, tak proc jednoduse nevyuziju toho, ze ho uzivatel zada pri prihlaseni? tj prihlasi se, k overeni dojde pomoci stareho algoritmu a najednou vim ze u uzivatele je pouzita stara funkce a znam jeho heslo. proc ho tedy jednoduse v tento moment nezmenit v databazi za nove zahashovane?
    prakticky by prechod na novy algoritmus byl otazkou jedineho prihlaseni uzivatele a zcela automaticky, bez nutnosti noveho hesla. v tabulce uzivatelu by pak i krasne vyplavali neaktivni uzivatele

  2. Tady je nějaká knihovna pro Whirlpool v js. Nezkoušel jsem. Každopádně díky za článek :)
    http://www.sunsean.com/Whirlpool.html