# Co było nie tak z password.es, a już nie jest

> Strona, która całymi dniami tłumaczy, jak należy robić rzeczy, ma obowiązek opowiedzieć, kiedy sama ich tak nie robiła. Oto co znaleźliśmy u siebie, z liczbami.

2026-08-31 · David Carrero · password.es
Original: https://password.es/pl/blog/co-bylo-nie-tak-z-password-es/

---

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](https://github.com/dropbox/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](/pl/blog/dlaczego-nie-wysylamy-twojego-hasla/).
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](https://github.com/dropbox/zxcvbn), open
source.*
