Cât costă o parolă pe hardware modest
Paginile de statistici de aici pot fi protejate cu o parolă. Calcularea hash-ului acestei parole este singura operație din acest serviciu care trebuie să fie lentă — tocmai asta face ca atacarea unui hash furat să fie costisitoare. Întrebarea este cât de lentă, pe acest hardware.
Măsurat pe mașina care rulează acest site, PHP 8:
PASSWORD_DEFAULT | 560 ms | (adică cost 12) |
| cost 12 | 595 ms | |
| cost 11 | 277 ms | |
| cost 10 | 138 ms |
Parametrul de cost al bcrypt este un exponent: fiecare treaptă dublează munca. Măsurătorile arată exact această dublare, ceea ce este un semn bun că nimic altceva nu interferează.
De ce valoarea implicită este alegerea greșită aici
PHP a ridicat costul implicit al bcrypt de la 10 la 12. Pe un server de clasă desktop, aceasta este o îmbunătățire rezonabilă — înseamnă câteva zeci de milisecunde. Pe hardware modest înseamnă peste o jumătate de secundă de CPU pur, pe o mașină care în același timp desenează și imaginile contoarelor pentru toți ceilalți.
O jumătate de secundă per autentificare este rău în sine. Este și mai rău ca invitație: oricine poate apela endpointul de autentificare, iar fiecare apel consumă 560 ms din CPU-ul care deservește întregul site. Asta transformă verificarea parolei în cea mai ieftină suprafață de atac denial-of-service disponibilă.
De aceea costul este fixat la 10, în loc să fie lăsat la valoarea implicită. Este în mod deliberat mai slab decât ce alege acum PHP, iar asta trebuie spus deschis, nu ascuns: un hash cu cost 10 este de patru ori mai ieftin de atacat decât unul cu cost 12. Ceea ce compensează este ce protejează de fapt parola — vizibilitatea unei pagini cu numere de vizite, nu un cont, nu bani, nu o identitate. În spatele ei nu există nimic care să poată fi preluat.
Partea ușor de trecut cu vederea
PASSWORD_DEFAULT este, prin design, o valoare care se schimbă. Codul scris acum ani care o folosește va deveni pe tăcute mai lent cu fiecare actualizare PHP — aceeași sursă, aceleași date de intrare, un timp de execuție de câteva ori mai mare. Acesta este comportamentul intenționat și este corect pentru majoritatea software-ului.
Este greșit doar atunci când mașina nu îl poate absorbi, iar nimic nu avertizează când nu poate. Actualizarea reușește, testele trec, pagina încă funcționează. Doar că durează cu o jumătate de secundă mai mult, iar nimeni nu se uită la acest număr decât dacă se apucă să îl măsoare.