Ten blog ma dwanaście artykułów o tym, jak należy robić rzeczy: że długość liczy się bardziej niż symbole, że menedżer to nie wygoda, tylko jedyny sposób, by dotrzymać zasady, że procent nic nie mówi.
Napisać to jest łatwo. Niewygodnie robi się wtedy, gdy przykładasz tę samą miarę do własnej strony. Zrobiliśmy to i trzy rzeczy były nie tak. Są tu w całości, razem z liczbami, które je zdradziły, bo strona o bezpieczeństwie publikująca wyłącznie swoje sukcesy jest sporo mniej warta.
Sprawdzarka zawieszała się, kiedy pisałeś
Sprawdzarka analizuje twoje hasło za pomocą zxcvbn, biblioteki, która szuka wzorców zamiast liczyć wielkie litery. Działa bardzo dobrze i ma swoją cenę: wykonuje się w całości, naraz, na tym samym wątku, który rysuje stronę. Dopóki działa, przeglądarka nie może zrobić nic innego.
Ta cena rośnie szybko wraz z długością. Zmierzone tą samą paczką, którą serwuje
strona, i hasłami, jakie ludzie naprawdę wpisują — słowa, lata, @ zamiast a:
| długość | jedno wykonanie |
|---|---|
| 16 znaków | 45 ms |
| 20 znaków | 121 ms |
| 32 znaki | 273 ms |
| 64 znaki | 843 ms |
| 128 znaków | 3621 ms |
Na razie normalnie. Problemem było to, ile razy je uruchamialiśmy.
Do pola podpięte były dwa różne nasłuchy, input i keyup. Zwykły klawisz
wyzwala oba. Więc przy każdej literze pełna analiza szła dwa razy: 90 ms przy
haśle 16-znakowym, pół sekundy przy 32-znakowym.
I nic tego nie hamowało: ani licznik czasu, ani limit długości, ani osobny wątek. Powyżej mniej więcej dwudziestu znaków przeglądarka analizowała dłużej, niż ty naciskałeś kolejny klawisz. Uderzenia piętrzyły się w kolejce, która już nigdy się nie opróżniała, i strona przestawała odpowiadać w trakcie pisania. Wklejenie długiego hasła zawieszało ją na kilka sekund.
Naprawa to dwie małe zmiany. Usunęliśmy nasłuch keyup, bo input obejmuje już
pisanie, wklejanie, kasowanie i autouzupełnianie z menedżera: połowa pracy znika,
nie zmieniając absolutnie niczego z tego, co widzisz. I dodaliśmy 150 milisekund
oczekiwania: dopóki piszesz, nic nie jest analizowane, a analiza rusza, gdy
przestaniesz. Nikt nie pisze tak wolno, żeby to zauważyć.
Wynik jest identyczny. Barcelona1992$ nadal mówi to samo: że «barcelona» jest w
słowniku, że 1992 wygląda na rok i że pada w niecałą sekundę.
Opis był ucięty w połowie zdania w piętnastu językach
Ta rzecz jest głupsza i bardziej wstydliwa.
Zdanie, które pojawia się w wyszukiwarce pod tytułem — meta description — było ucięte w piętnastu z osiemnastu języków sprawdzarki. Ocalały tylko hiszpański, koreański i japoński. Ktoś kiedyś przyciął je na długość, uciął w połowie słowa, a potem nikt nie sprawdził.
W trzech językach cięcie wypadło dokładnie w środku znaku specjalnego, więc to, co publikowaliśmy w Google, wyglądało tak:
| język | co serwowaliśmy | co powinno być |
|---|---|---|
| portugalski | …datas e padr&o |
padrões |
| turecki | …arıyor ve ger&cced |
gerçekten |
| wietnamski | …chúng tôi tra mật kh&# |
mật khẩu |
Uderzające jest miejsce: najlepiej działająca strona w całym serwisie. Sprawdzarka konwertuje znacznie lepiej niż generator — i robiła to z zepsutym opisem. Wszystkie piętnaście jest uzupełnione.
Przy okazji w koreańskim, japońskim i wietnamskim marka przeniosła się z początku na koniec tytułu. W wynikach domena i tak widnieje osobno, więc zaczynanie od «password.es ·» marnowało tylko miejsce, które waży najwięcej.
Obciążenie jeden na sto milionów
Generator wybiera każdy znak przez crypto.getRandomValues(), dobre źródło
losowości w przeglądarce. Ale żeby zamienić tę ogromną liczbę na «pozycję w
alfabecie», braliśmy resztę z dzielenia, a tam czeka klasyczna pułapka: 2³² nie
jest wielokrotnością 83, więc pierwsze pozycje alfabetu wypadały odrobinę
częściej niż ostatnie.
Ile to «odrobinę»: przy alfabecie do 89 znaków rzędu jednej części na sto milionów. Nic to nie zmienia. Nie czyni twojego hasła mierzalnie słabszym, nawet w przybliżeniu.
Naprawiliśmy i tak, a to trzy linijki: odrzuca się 45 nadmiarowych wartości z 4 294 967 296 możliwych i losuje ponownie. Na stronie o hasłach «to pomijalne» nie jest dobrym powodem, by zostawiać obciążenie, skoro usunięcie kosztuje tyle.
Czego brakowało: żeby obietnicy pilnowała przeglądarka
Mamy cały artykuł o tym, że twoje hasło stąd nie wychodzi. To była prawda, a mimo to tylko nasze zdanie: technicznie nic nie powstrzymywało wstrzykniętego skryptu przed zrobieniem czegoś innego.
Teraz każda strona niesie politykę bezpieczeństwa treści. Dwie części, które mają znaczenie:
- Nie uruchomi się żaden skrypt, którego nie było na stronie w chwili budowania. Każdy prawowity skrypt jest podpisany swoim odciskiem; wstrzyknięty nie pasuje i przeglądarka odmawia wykonania.
connect-src 'none'. Strona nie wysyła ani jednego żądania sieciowego z JavaScriptu, a teraz pilnuje tego przeglądarka. Gdyby kiedyś coś próbowało wysłać gdzieś to, co wpisujesz, nie wyszłoby.
Obietnica przestała być deklaracją i stała się regułą.
Co nadal jest nie tak
Aktualizacja z 31 sierpnia. Wszystkie trzy rzeczy z tej sekcji naprawiono tego samego dnia, w którym ukazał się ten artykuł: piętnaście języków opisuje już prawdziwy silnik, dwie skale stały się jedną, a FAQ sprawdzarki tłumaczy sprawę symboli. Zostają zapisane, bo zapis tego, co było nie tak, jest wart więcej niż zdjęcie nieskazitelnej strony.
Tu ten artykuł zarabia na swoje miejsce.
Piętnaście języków wciąż opisuje sprawdzarkę jako stary silnik. Ich tekst mówi,
że odtwarza klasyczną logikę PasswordMeter. Już nie: tamten silnik wymieniono,
bo Haslo1! uznawał za bardzo silne, a pięciowyrazową frazę oblewał, czyli
dokładnie na odwrót. Hiszpański, koreański i japoński są zaktualizowane; pozostałe
piętnaście nie.
W tym samym domu są dwie różne skale. Strona główna decyduje o sile hasła po bitach; sprawdzarka po czasie, jaki zajęłoby złamanie. Różne kryteria, i nigdzie o tym nie uprzedzamy.
Generator i sprawdzarka nie liczą tych samych symboli: jeden używa 27, drugi zakłada 33. Różnica jest mała, ale jest.
Żadna z tych trzech rzeczy nie jest poważna. Wszystkie trzy to dług i wolą być zapisane tutaj, niż czekać, aż znajdzie je ktoś inny.
Dziennik zmian tej wersji
Ponieważ repozytorium nie jest publiczne, dziennik zmian idzie tu w całości. Wersja 0.2.0, 31 sierpnia 2026:
Dodane. Polityka bezpieczeństwa treści dla każdej strony, z odciskiem każdego skryptu. Artykuł o tym, gdzie są twoje zapisane hasła, w osiemnastu językach. Kolejka redakcyjna, która decyduje, co powstaje, i która nakazuje nie publikować niczego, gdy się opróżni.
Naprawione. Opis sprawdzarki, ucięty w połowie zdania w piętnastu językach, w trzech z nich z przepołowionym znakiem. Zawieszanie karty podczas pisania. Obciążenie losowania. I brakujące zdjęcie w poprzednim artykule.
Zmienione. Tytuł sprawdzarki po koreańsku, japońsku i wietnamsku. Wdrożenie, które teraz rusza, gdy zbudowana strona już istnieje, a nie minutę wcześniej. Oraz tłumaczenia na wietnamski, hindi i arabski, które przestają blokować publikację, choć pozostają najsłabsze.
Liczby w tym artykule są zmierzone, nie oszacowane: czasy zxcvbn tą samą paczką, którą serwuje strona, i hasłami ze słowami oraz podstawieniami; obciążenie losowania policzone na 4 294 967 296 wartościach 32-bitowej liczby całkowitej. Silnikiem sprawdzarki jest zxcvbn, open source.
Zdjęcie: Ernandes Alves · Pexels