Návrh pro PHP řeší zkracování dlouhých hesel novou variantou bcryptu
Sjoerd Langkemper navrhl pro PHP novou volbu PASSWORD_BCRYPT_SHA256, která má odstranit hranici 72 bajtů u bcryptu. Přebírá postup z pythonové knihovny Passlib a původní bcrypt ponechává beze změny. Návrh z počátku října je zatím v diskusi, schválené vydání nemá.

Delší heslo nemusí u bcryptu znamenat, že se při přihlášení ověřuje víc znaků. Algoritmus zpracuje jen prvních 72 bajtů; zbytek vstupu se při běžném použití v PHP zahodí. Sjoerd Langkemper proto 5. října předložil vývojářům PHP návrh nové volby PASSWORD_BCRYPT_SHA256. Ta by před bcrypt vložila další výpočet, do kterého vstoupí celé heslo.
Dokument návrhu má datum 4. října 2026 a stav „Under discussion“. Míří na některé příští vydání PHP 8, jako příklad uvádí PHP 8.7. Nejde tedy o funkci, kterou by dnes vývojář mohl zapnout v běžném vydání jen změnou jedné konstanty. Hlasování zatím nezačalo.
Hranice se počítá v bajtech
Hash je výsledek jednosměrného výpočtu z hesla. Aplikace ho uloží místo samotného hesla a při přihlášení ověřuje, zda zadané heslo odpovídá uloženému výsledku. Bcrypt tento výpočet záměrně prodražuje, aby zkoušení velkého množství hesel po úniku databáze stálo útočníka čas.
Jeho délkový limit se ale týká bajtů, ne počtu písmen. U textu v UTF-8 mohou některé znaky zabrat víc než jeden bajt. Dvě dlouhá hesla se stejnými prvními 72 bajty proto mohou při ověřování odpovídat témuž uloženému bcryptovému hashi, přestože se jejich konec liší. Přidávat znaky za tuto hranici ochranu uloženého hesla nezlepší.
Langkemper nejdřív navrhl, aby PHP příliš dlouhé heslo odmítlo chybou. V říjnovém oznámení píše, že od této cesty prozatím ustoupil kvůli námitkám proti změně chování existujících aplikací. Nová konstanta má dát vývojářům možnost přejít na jiný postup dobrovolně.
Bcrypt dostane vždy 44 bajtů
Předvýpočet používá HMAC SHA-256, tedy výpočet otisku zprávy s klíčem. Zprávou je celé heslo, klíčem náhodně vytvořená sůl pro daný hash. Sůl je hodnota uložená spolu s výsledkem; rozlišuje jednotlivá hashování a není tajným heslem aplikace. Návrh ji do HMAC předává jako řetězec 22 znaků.
Výsledkem je 32 bajtů. Převod do base64, zápisu binárních dat pomocí tisknutelných znaků, z nich udělá řetězec o 44 bajtech. Až ten dostane bcrypt. Pod jeho hranici se tak vejde výsledek z krátkého i dlouhého hesla a neobsahuje nulový bajt, který některým implementacím bcryptu působí další potíže.
Postup není novým vynálezem PHP. Dokumentace Passlib popisuje tutéž kombinaci HMAC, soli a base64 ve verzi 2 formátu bcrypt-sha256. Knihovna ji používá jako výchozí od Passlib 1.7.3. PHP má podle návrhu převzít i podobu uloženého řetězce, takže by obě prostředí dokázala ověřovat vzájemně vytvořené výsledky.
Staré hashe se samy nepřepočítají
Původní volba PASSWORD_BCRYPT by zůstala zachovaná, stejně jako PASSWORD_DEFAULT a volby pro Argon2. Nový algoritmus by se vybíral při volání password_hash(); samostatná nová funkce se nenavrhuje. Ověřovací funkce password_verify() by ho rozpoznala podle začátku uloženého řetězce $bcrypt-sha256$.
Jde o důležitou hranici změny: přidání nové volby nepřepíše již uložené výsledky ani neopraví přihlašování, které dál používá původní bcrypt. Návrh zachovává také parametr cost, jímž se určuje náročnost výpočtu, s výchozí hodnotou 12 a rozsahem 4 až 31. Uložený řetězec bude delší než běžný bcryptový hash, takže aplikace při přechodu může potřebovat širší databázový sloupec.
V diskusi se řeší i doporučení OWASP
Převzetí existujícího formátu samo o sobě neuzavírá debatu o jeho vhodnosti. Mirco Babin v diskusi namítl, že návrh neodpovídá doporučení OWASP pro předvýpočet před bcryptem, a ptal se na slučitelnost s dalšími jazyky mimo Python.
Doporučení OWASP pro ukládání hesel skutečně popisuje jiný postup: HMAC SHA-384 s tajnou hodnotou zvanou pepper, která se uchovává mimo databázi hesel. Návrh PHP používá HMAC SHA-256 s veřejně uloženou solí. Pepper a sůl tedy v těchto dvou postupech nemají stejnou roli.
OWASP zároveň pro nové systémy doporučuje především Argon2id a bcrypt ponechává pro starší systémy, kde Argon2 nebo scrypt nejsou dostupné. Langkemperův návrh řeší konkrétní omezení bcryptu a výměnu výsledků s Passlib. O přijetí do PHP teprve rozhodne hlasování; dokument zatím neuvádí vydání ani commit, ve kterém by byla změna začleněná.