API password.es już odpowiada: jak z niego korzystać

Opublikowano autor David Carrero

Ten blog od miesięcy powtarza to samo: twoje hasło nie powinno opuszczać przeglądarki. Generator bierze losowość z crypto.getRandomValues() na twojej własnej maszynie, a sprawdzanie analizuje to, co wpisujesz, nie wysyłając tego nigdzie.

A dziś publikujemy API, które generuje hasła na serwerze.

Sprzeczność jest oczywista i nie zamierzamy jej zamazywać: każda odpowiedź API niesie ostrzeżenie, które mówi dokładnie to. Ale są miejsca, w których nie ma przeglądarki — skrypt zakładający sto kont, serwer tworzący tymczasowe poświadczenie, asystent, którego ktoś prosi o hasło, a on je zmyśla — i tam alternatywą nie jest „przeglądarka“: jest nią źle dobrany random() albo ciąg wpisany ręcznie. Po to jest to API.

Całe wywołanie

Bez klucza, bez rejestracji, bez nagłówków. To wszystko:

curl -X POST https://api.password.es/v1/generate

Zwraca hasło o długości 16 znaków i jego analizę. Wykonane w trakcie pisania tego akapitu: x*7$9,BUy9PPvOI?, wzięte z alfabetu 89 znaków, 103,6 bita entropii i czas łamania 2,5 × 10¹¹ lat. Poziom 4 na 4.

Żadna z tych liczb nie jest nowa. Pochodzą z tego samego silnika, który rysuje wskaźnik na stronie głównej: ten sam wzór na bity, ten sam model ataku — 10¹² prób na sekundę, offline, szybki hash — i ta sama skala poziomu co w sprawdzaniu. Gdyby strona i API podawały różne liczby dla tego samego hasła, jedno z dwojga kłamałoby.

Co zwraca, pole po polu

Odpowiedź zawiera passwords — zawsze tablicę, nawet gdy prosisz o jedno — i blok analysis z length, pool, bits, log10_guesses, crack_time_log10_seconds, crack_time, level, level_scale i ceiling.

Dwa z nich zasługują na akapit. level_scale mówi, skąd wziął się poziom (dziś zawsze "time"), żeby przyszła rozbieżność między stroną a API była widoczna w polu, zamiast trzeba ją było wywnioskować z porównywania liczb. A ceiling mówi, czy liczba jest dokładna, czy jest sufitem: w generate zawsze false, bo hasło zrobił serwer i wie, z jakiego alfabetu; w sprawdzaniu na stronie nie zawsze może tak być, bo tam hasło przynosisz ty.

Dalej jest notice, ostrzeżenie, i blok _meta z planem, zastosowanym językiem, limitami i odnośnikiem do dokumentacji.

Opcje

Wszystkie opcjonalne, z nazwami po angielsku, bo kto integruje API, przepisuje nazwy pól dosłownie: length (4–64, domyślnie 16), count (1–20), lower, upper, digits, symbols, exclude_ambiguous, no_repeats i lang.

curl -X POST https://api.password.es/v1/generate -H 'content-type: application/json' -d '{"length":20,"exclude_ambiguous":true}'

Dwa szczegóły, o których mówi dokumentacja i które warto znać przed integracją. exclude_ambiguous usuwa sześć znaków, nie siedem: odrzuca 0 O 1 I l | o, ale pionowej kreski i tak nie było w zestawie symboli, więc alfabet spada z 89 do 83, a nie do 82. Dlatego w odpowiedzi pool wynosi 83. I no_repeats nie jest absolutną gwarancją: ponawia próbę dziesięć razy, dokładnie jak generator na stronie, a przy 64 znakach sąsiadujące powtórzenie przechodzi w około 0,1 % przypadków. Powiedzenie tego jest bardziej użyteczne niż obiecywanie czegoś przeciwnego.

Język

Domyślnie odpowiada po angielsku, czego spodziewa się ten, kto integruje bez podania niczego. Zmienia się to przez ?lang= w URL, "lang" w treści albo nagłówek Accept-Language, a przy sprzeczności wygrywa pierwszy. Nieznany język nie jest błędem: schodzi do angielskiego.

Jest tu asymetria, której nie da się zgadnąć, i dlatego API ją deklaruje: komunikaty istnieją po angielsku i hiszpańsku; odnośniki — we wszystkich osiemnastu językach strony. Poproszenie o niemiecki daje niemieckie odnośniki i komunikaty wciąż po angielsku. Nie trzeba zgadywać: _meta.lang zawiera { "messages", "links" } z tym, co zastosowano do każdej połowy.

Serwer MCP

MCP to protokół, którym asystent — Claude, ChatGPT — korzysta z zewnętrznych narzędzi. https://api.password.es/mcp to serwer MCP bez rejestracji i bez klucza, publikujący jedno narzędzie: generate_password, z tymi samymi parametrami co wyżej.

To część, na której zależy nam najbardziej, i nie z powodów technicznych: asystent, który nie ma skąd wziąć hasła, zmyśla je, a to, co z tego wychodzi, nie jest losowe — jest tym, co model uważa za wyglądające jak hasło. Z podłączonym serwerem przestaje improwizować i zwraca hasło zrobione przez crypto.getRandomValues(), z analizą i z ostrzeżeniem zawartym w opisie narzędzia i w każdym wyniku. To ostrzeżenie jest właśnie tym, co asystent ostatecznie odczytuje temu, kto poprosił o hasło, i dlatego tam jest.

Jeśli przychodzisz z innych serwerów MCP, jedna rzecz: ten jest bezstanowy. POST dostaje odpowiedź JSON i nie otwiera żadnego strumienia, Mcp-Session-Id nie jest ani wystawiany, ani oczekiwany, powiadomienie dostaje 202 bez treści, a GET zwraca 405. Specyfikacja 2025-06-18 wprost na to pozwala, ale kto oczekuje sesji i SSE, będzie debugował po omacku, jeśli nikt mu tego nie powie.

Czego nie robi

/v1/check zwraca 501. To nie przeoczenie ani niedokończony endpoint: jest tak celowo, a sama odpowiedź tłumaczy dlaczego. Zwrócenie tych samych liczb co sprawdzanie wymaga tego samego silnika wzorców, który działa na stronie, a to kosztuje od 11 ms do 3,6 s CPU na żądanie, zależnie od tego, co się wyśle. W usłudze bez rejestracji i bez klucza ten rozrzut to decyzja produktowa — gdzie postawić limit długości — której jeszcze nie podjęto. Tymczasem 501 niesie checker_url wskazujący sprawdzanie na stronie w żądanym języku, które robi dokładnie to i nic nie wysyła.

Nie ma też kont, kluczy ani planów. A skoro nie istnieją, w całym API nie ma ani jednego odnośnika do rejestracji: nawet w błędzie przekroczonego limitu, gdzie wszyscy go umieszczają.

Limity

Jeden, i to ten faktycznie egzekwowany: 60 żądań na minutę na IP. Nie trzeba wierzyć tej stronie: liczba podróżuje w każdej odpowiedzi, w _meta.limits.burst. Po przekroczeniu przychodzi 429 z Retry-After i nagłówkami RateLimit-*.

W _meta zobaczysz też blok quota z wartościami null. To miejsce zarezerwowane na czas, gdy pojawią się konta, i jest puste celowo: limit ogłoszony i nieegzekwowany jest gorszy niż brak limitu, bo ten, kto integruje, przestrzega go i programuje wobec liczby, której nikt nie liczy.

A i tak — zastanów się dwa razy

API generujące hasła jest w gruncie rzeczy antywzorcem: hasło wędruje przez sieć i przechodzi przez maszynę, która nie jest twoja. To, że nic nie przechowujemy, nie zmienia kształtu problemu, tylko naszą jego część — a wiesz już, ile warta jest obietnica, której nie możesz sprawdzić.

Dlatego ostrzeżenie nie mieszka tylko na tej stronie: podróżuje w każdej odpowiedzi, w języku, o który poprosisz. I dlatego ten akapit jest tutaj, a nie schowany na końcu dokumentacji. Do hasła, którego użyjesz sam, generator tej strony działa w całości w twojej przeglądarce i nic nie wysyła. API jest do tego drugiego: do tego, co dzieje się, gdy nikogo nie ma przed ekranem.

Szczegóły są na dwóch stronach. Czym jest API mówi, dla kogo jest, co odpowiada dziś, a co nie. Dokumentacja ma dziewięć parametrów, wszystkie pola wyjaśnione jedno po drugim, kody błędów i limity; to ta, którą otwiera się obok edytora. A jeśli chcesz, żeby przeczytała to maszyna, jest openapi.json.


Źródła: samo API, zweryfikowane wobec produkcji 31 sierpnia 2026 — POST /v1/generate, POST /v1/check (501), POST /mcp i GET /openapi.json · liczby analizy pochodzą z tego samego silnika co generator i sprawdzanie na password.es · model ataku to 10¹² prób na sekundę, offline i z szybkim hashem, ten sam co w reszcie strony · serwer MCP implementuje specyfikację 2025-06-18 z bezstanowym transportem Streamable HTTP.

Zdjęcie: Stanislav Kondratiev · Pexels

← Wróć do bloga