L'API de password.es ja respon: com es fa servir

Publicat el per David Carrero

Aquest blog fa mesos que repeteix el mateix: la teva contrasenya no hauria de sortir del navegador. El generador treu l’atzar de crypto.getRandomValues() a la teva pròpia màquina i el comprovador analitza el que escrius sense enviar-ho enlloc.

I avui publiquem una API que genera contrasenyes en un servidor.

La contradicció és evident i no la dissimularem: cada resposta de l’API porta un avís que diu exactament això. Però hi ha llocs on no hi ha navegador —un script que dóna d’alta cent comptes, un servidor que fabrica una credencial temporal, un assistent a qui algú demana una contrasenya i se la inventa— i allà l’alternativa no és «el navegador»: és un random() mal triat o una cadena escrita a mà. Per això existeix això.

La crida sencera

Sense clau, sense registre, sense capçaleres. Això és tot:

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

Retorna una contrasenya de 16 caràcters i la seva anàlisi. Executada mentre s’escrivia aquest paràgraf: x*7$9,BUy9PPvOI?, treta d’un alfabet de 89 caràcters, 103,6 bits d’entropia i un temps de trencament de 2,5 × 10¹¹ anys. Nivell 4 de 4.

Cap d’aquests números és nou. Surten del mateix motor que dibuixa el mesurador de la portada: la mateixa fórmula de bits, el mateix model d’atac —10¹² intents per segon, sense connexió, hash ràpid— i la mateixa escala de nivell del comprovador. Si el web i l’API donessin números diferents per a la mateixa contrasenya, un dels dos estaria mentint.

Què retorna, camp a camp

La resposta porta passwords —sempre un array, encara que en demanis una sola— i un bloc analysis amb length, pool, bits, log10_guesses, crack_time_log10_seconds, crack_time, level, level_scale i ceiling.

Dos mereixen un paràgraf. level_scale diu d’on ha sortit el nivell (avui sempre "time"), perquè una divergència futura entre el web i l’API es vegi al camp en comptes d’haver-la de deduir comparant números. I ceiling diu si la xifra és exacta o un sostre: a generate sempre és false, perquè la contrasenya l’ha feta el servidor i sap amb quin alfabet; al comprovador del web no sempre pot ser-ho, perquè allà la contrasenya la portes tu.

Després ve notice, l’avís, i un bloc _meta amb el pla, l’idioma aplicat, els límits i un enllaç a la documentació.

Les opcions

Totes opcionals, i amb els noms en anglès perquè qui integra una API escriu els camps tal qual: length (4–64, per defecte 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}'

Dos detalls que la documentació explica i que convé saber abans d’integrar-ho. exclude_ambiguous treu sis caràcters, no set: descarta 0 O 1 I l | o, però la barra vertical no era al joc de símbols d’entrada, així que l’alfabet baixa de 89 a 83 i no a 82. Per això la resposta diu pool 83. I no_repeats no és una garantia absoluta: torna a provar deu vegades, exactament com el generador del web, i a 64 caràcters s’hi cola una repetició contigua al voltant del 0,1 % de les vegades. Dir-ho és més útil que prometre el contrari.

L’idioma

Per defecte respon en anglès, que és el que espera qui integra sense dir res. Es canvia amb ?lang= a l’URL, amb "lang" al cos o amb la capçalera Accept-Language, i si es contradiuen guanya el primer. Un idioma que no existeix no és un error: cau a l’anglès.

Aquí hi ha una asimetria que no s’endevina, i per això l’API la declara: els missatges existeixen en anglès i castellà; els enllaços, en els divuit idiomes del lloc. Demanar alemany et dóna els enllaços en alemany i els missatges encara en anglès. No cal suposar-ho: _meta.lang porta { "messages", "links" } amb el que s’ha aplicat a cada meitat.

El servidor MCP

MCP és el protocol amb què un assistent —Claude, ChatGPT— fa servir eines externes. https://api.password.es/mcp és un servidor MCP sense registre i sense clau, i publica una sola eina: generate_password, amb els mateixos paràmetres de dalt.

És la part que més ens importa, i no pel costat tècnic: un assistent que no té d’on treure una contrasenya se la inventa, i el que en surt no és aleatori, és el que el model considera que té forma de contrasenya. Amb el servidor connectat deixa d’improvisar i en retorna una feta amb crypto.getRandomValues(), amb la seva anàlisi i amb l’avís inclòs a la descripció de l’eina i a cada resultat. Aquest avís és justament el que l’assistent acaba llegint a qui li ha demanat la contrasenya, i per això hi és.

Si véns d’altres servidors MCP, una sola dada: aquest no té estat. El POST es respon amb JSON i no obre cap stream, Mcp-Session-Id ni s’emet ni s’espera, una notificació es respon amb 202 sense cos i el GET retorna 405. L’especificació 2025-06-18 ho permet explícitament, però qui espera sessions i SSE depurarà a cegues si ningú l’hi diu.

El que no fa

/v1/check retorna 501. No és un descuit ni un endpoint a mig fer: està així a propòsit, i la mateixa resposta explica per què. Retornar els mateixos números que el comprovador exigeix el mateix motor de patrons que corre al web, i això costa entre 11 ms i 3,6 s de CPU per petició segons què li enviïs. En un servei sense registre i sense clau, aquesta forquilla és una decisió de producte —on es posa el sostre de longitud— que encara no s’ha pres. Mentrestant, el 501 porta un checker_url que apunta al comprovador del web en l’idioma que hagis demanat, que fa exactament això sense enviar res.

Tampoc existeixen els comptes, ni les claus, ni els plans. I com que no existeixen, no hi ha ni un sol enllaç a un registre a tota l’API: ni tan sols a l’error de límit superat, que és on tothom el posa.

Els límits

Un, i és el que s’aplica de veritat: 60 peticions per minut i per IP. No cal creure’s aquesta pàgina: el número viatja dins de cada resposta, a _meta.limits.burst. Si te’l passes surt un 429 amb Retry-After i capçaleres RateLimit-*.

A _meta hi veuràs a més un bloc quota amb els valors a null. És el forat reservat per quan hi hagi comptes, i va buit a propòsit: un límit anunciat i no aplicat és pitjor que no anunciar-ne cap, perquè qui integra el respecta i programa contra un número que ningú està comptant.

I tot i així, pensa-t’ho dues vegades

Una API que genera contrasenyes és, al capdavall, un antipatró: la contrasenya viatja per la xarxa i passa per una màquina que no és la teva. Que nosaltres no guardem res no canvia la forma del problema, només la nostra part —i ja saps què val una promesa que no pots comprovar.

Per això l’avís no viu només en aquesta pàgina: viatja a cada resposta, en l’idioma que demanis. I per això aquest paràgraf és aquí i no amagat al final de la documentació. Per a una contrasenya que faràs servir tu, el generador d’aquest lloc corre sencer al teu navegador i no envia res. L’API és per a l’altra cosa: el que passa sense ningú davant d’una pantalla.

Els detalls són a dues pàgines. Què és l’API explica per a qui és, què respon avui i què no. La referència té els nou paràmetres, tots els camps explicats un a un, els codis d’error i els límits; és la que s’obre amb l’editor al costat. I si el que vols és que ho llegeixi una màquina, hi ha openapi.json.


Fonts: la mateixa API, verificada contra producció el 31 d’agost de 2026 — POST /v1/generate, POST /v1/check (501), POST /mcp i GET /openapi.json · els números de l’anàlisi surten del mateix motor que el generador i el comprovador de password.es · el model d’atac és 10¹² intents per segon, sense connexió i amb hash ràpid, el mateix que la resta del lloc · el servidor MCP implementa l’especificació 2025-06-18 amb transport Streamable HTTP sense estat.

Foto de Stanislav Kondratiev · Pexels

← Tornar al blog