O tom, že funkce jako MD5, SHA1 a další již nejsou bezpečné, a je vhodné použít novější funkce, je článek Jak správně ukládat hesla. Tento článek trochu naváže. Bude popsán jednoduchý postup, jak implementovat password_hash i do již zaběhnutých systémů.
Na svém blogu Michal Špaček jde ještě trochu dále a zabezpečuje také hesla zahashována starou metodou. Jednoduše proto, ať se vám nestane to co Mallu.
Jak na to
Mnoho lidí mohlo odradit, že je potřeba upravit databázi, ukládat typ hashe, jaký je použit apod. Poté to vše ještě implementovat v kódu a je to moc práce. Nic z toho ale nutné není, a i úpravy kódu mohou být minimální.
Úprava databáze
Pokud se heslo nyní ukládá jako VARCHAR(32) (pro MD5) nebo VARCHAR(40) (pro SHA1) apod., stačí zvětšit pole na VARCHAR(255). Ke změně ani ke ztrátě dat nedojde, a pro bcrypt to bude stačit.
Úprava kódu
V článku o bcryptu a PHP funkcích password_* bylo popsáno, že výstup z funkcí password_hash() začíná vždy speciální sekvencí $xx$yy$..., a toho se dá využít. Výstup funkce SHA1 případně MD5 nikdy znakem $ nezačne.
Proto stačí password_* funkce zaobalit do vlastních funkcí, aby fungovaly i se starou verzí hashování. Funkce password_hash slouží pouze ke generování hashe, a ten se vždy bude generovat již bezpečně pomocí bcryptu. Proto stačí napsat vlastní funkce pouze pro password_verify() a password_needs_rehash(). Pokud je potřeba, dopsat funkci password_get_info() už snad nebude problém.
// Kontrola správnosti hashe pro dané heslo // $saltedPass je volitelně použit jen pro starý způsob hashování function backward_password_verify($pass, $hash, $saltedPass = null) { if ($hash[0] == "$") { return password_verify($pass, $hash); }else{ if (empty($saltedPass)) { $saltedPass = $pass; } // Zde vložit starý způsob hashování $countedHash = md5($saltedPass); return $hash == $countedHash; } } // Kontrola, jestli je potřeba heslo přegenerovat // Pro starý způsob hashování vždy vrátí true function backward_password_needs_rehash($hash) { if ($hash[0] == "$") { return password_needs_rehash ($hash, PASSWORD_DEFAULT); }else{ return true; } }
Použití
Použití se nyní neliší od použití v předchozím článku, stačí pouze použít nové funkce.
// Vytvoření hash pomocí defaultního algoritmu, aktuálně Bcrypt // Hash nyní může být také MD5 nebo cokoli staršího, použitého // v backward_password_* funkcích $hash = password_hash("mojeTajnéHeslo", PASSWORD_DEFAULT); // Kontrola shodnosti hashe a zadaného hesla if(backward_password_verify ( "mojeTajnéHeslo" , $hash )){ // heslo odpovídá // Kontrola, jestli lze vytvořit kvalitnější hash if(backward_password_needs_rehash ( $hash )){ // Uložit do DB nový hash $hash = password_hash("mojeTajnéHeslo", PASSWORD_DEFAULT); } }
Podpora pro starší PHP
Funkce password_* jsou až od PHP verze 5.5, ani to ale nemusí odradit od aplikace bezpečných hashovacích funkcí. Stačí použít password_compat knihovnu napsanou jedním z vývojářů PHP. Ta lze použít již od v5.3.7, takže by již nic nemělo bránit použití. Instalovat lze jak pomocí composeru tak pomocí jednoduchého include, jedná se pouze o jedinný soubor.
Tak už jste přešli na bezpečnější způsob ukládání hesel? Podělte se v komentářích
K tomuto článku již není možné přidávat další komentáře