# O que estaba mal en password.es, e xa non

> Un sitio que se pasa o día dicindo como deberían facerse as cousas ten a obriga de contar cando non as facía. Isto é o que atopamos na nosa propia casa, coas cifras diante.

2026-08-31 · David Carrero · password.es
Original: https://password.es/gl/blog/o-que-estaba-mal-en-password-es/

---

Este blog leva doce artigos explicando como deberían facerse as cousas: que a
lonxitude importa máis que os símbolos, que un xestor non é comodidade senón a
única forma de cumprir a regra, que unha porcentaxe non di nada.

Escribir iso é doado. O incómodo é mirar o teu propio sitio co mesmo rasero.
**Fixémolo, e había tres cousas mal.** Van aquí enteiras, cos números que as
delatan, porque un sitio de seguridade que só publica os seus acertos vale
bastante menos.

## O comprobador conxelábase mentres escribías

O comprobador analiza o teu contrasinal con [zxcvbn](https://github.com/dropbox/zxcvbn),
unha biblioteca que busca patróns en vez de contar maiúsculas. Funciona moi ben e
ten un custo: **execútase enteira, de golpe, no mesmo fío que debuxa a páxina.**
Mentres corre, o navegador non pode facer nada máis.

Ese custo medra rápido coa lonxitude. Medido co mesmo paquete que serve o sitio, e
con contrasinais dos que a xente escribe de verdade —palabras, anos, `@` no canto
de `a`—:

| lonxitude | unha execución |
|---|---|
| 16 caracteres | 45 ms |
| 20 caracteres | 121 ms |
| 32 caracteres | 273 ms |
| 64 caracteres | 843 ms |
| 128 caracteres | 3.621 ms |

Ata aquí, normal. O problema estaba en cantas veces a lanzabamos.

O campo tiña enganchados **dous** detectores distintos, `input` e `keyup`. Unha
tecla normal dispara os dous. Así que cada vez que premías unha letra, a análise
completa corría **dúas veces**: 90 ms nun contrasinal de 16 caracteres, medio
segundo nun de 32.

E non había nada que o frease: nin un temporizador, nin un límite de lonxitude,
nin un fío á parte. A partir duns vinte caracteres, o navegador tardaba máis en
analizar do que ti tardabas en premer a tecla seguinte. As pulsacións acumulábanse
nunha cola que xa non se baleiraba nunca, e **a páxina deixaba de responder
mentres escribías**. Pegar un contrasinal longo conxelábaa varios segundos.

O arranxo son dous cambios pequenos. Quitamos o detector de `keyup`, porque
`input` xa cobre teclear, pegar, borrar e o enchido automático do xestor: a metade
do traballo desaparece sen cambiar absolutamente nada do que ves. E engadimos unha
espera de 150 milisegundos: mentres escribes non se analiza nada, e analízase en
canto paras. Ninguén teclea tan amodo como para notalo.

O resultado é idéntico. `Barcelona1992$` segue dicindo o mesmo: que «barcelona»
está no dicionario, que 1992 parece un ano, e que cae en menos dun segundo.

## A descrición estaba cortada a media frase en quince idiomas

Esta é máis parva e máis vergoñenta.

A frase que aparece baixo o título no buscador —a meta description— estaba
**truncada en quince dos dezaoito idiomas** do comprobador. Só se salvaban o
castelán, o coreano e o xaponés. Alguén a recortou por lonxitude nalgún momento,
cortou a media palabra, e ninguén o mirou despois.

En tres idiomas o corte caeu xusto no medio dun carácter especial, así que o que
publicabamos en Google era isto:

| idioma | o que serviamos | o que debía dicir |
|---|---|---|
| portugués | `…datas e padr&o` | `padrões` |
| turco | `…arıyor ve ger&cced` | `gerçekten` |
| vietnamita | `…chúng tôi tra mật kh&#` | `mật khẩu` |

O chamativo é onde estaba: na **páxina que mellor funciona de todo o sitio**. O
comprobador converte moitísimo mellor que o xerador, e facíao coa descrición rota.
Están completadas as quince.

De paso, en coreano, xaponés e vietnamita movemos a marca do principio á fin do
título. No buscador o dominio xa se ve á parte, así que empezar por «password.es ·»
só gastaba o espazo que máis pesa.

## Un nesgo dun entre cen millóns

O xerador escolle cada carácter con `crypto.getRandomValues()`, a fonte de azar boa
do navegador. Pero para converter ese número enorme en «unha posición do alfabeto»
faciamos unha división con resto, e aí hai unha trampa clásica: 2³² non é múltiplo
de 83, así que **as primeiras posicións do alfabeto saían un chisco máis a miúdo
que as últimas**.

Canto é «un chisco»: cun alfabeto de ata 89 caracteres, da orde dunha parte en cen
millóns. Non cambia nada. Non fai o teu contrasinal apreciablemente máis feble,
nin de lonxe.

Arranxámolo igualmente, e son tres liñas: descártanse os 45 valores sobrantes dos
4.294.967.296 posibles e sortéase de novo. Nun sitio sobre contrasinais, «é
desprezable» non é unha boa razón para deixar un nesgo posto cando quitalo custa
iso.

## O que faltaba: que o navegador fixese cumprir a promesa

Levamos un artigo enteiro explicando que [o teu contrasinal non sae de aquí](/gl/blog/por-que-non-enviamos-o-teu-contrasinal/).
Era verdade, e aínda así era só unha frase nosa: nada impedía tecnicamente que un
script inxectado fixese outra cousa.

Agora cada páxina leva unha política de seguridade de contido. As dúas partes que
importan:

- **Non se executa ningún script que non estivese na páxina ao construíla.** Cada
  guión lexítimo vai asinado coa súa pegada; un inxectado non coincide e o
  navegador négase a executalo.
- **`connect-src 'none'`.** O sitio non fai nin unha soa petición de rede desde
  JavaScript, e agora imponno o navegador. Se algún día algo intentase mandar a
  algunha parte o que escribes, non sairía.

A promesa deixou de ser unha declaración e pasou a ser unha regra.

## O que segue sen estar ben

**Actualización do 31 de agosto.** As tres cousas desta sección arranxáronse o mesmo día en que se publicou este artigo: os quince idiomas xa describen o motor real, as dúas escalas son unha, e as preguntas frecuentes do comprobador explican o dos símbolos. Déixanse escritas, porque o rexistro do que estivo mal vale máis que a foto dun sitio impecable.

Aquí é onde este artigo gaña o seu sitio.

**Quince idiomas seguen describindo o comprobador como o motor antigo.** O texto
desas páxinas di que reproduce a lóxica clásica de PasswordMeter. Xa non: ese motor
cambiouse porque daba «moi forte» a `Contrasinal1!` e suspendía unha frase longa de
cinco palabras, que é exactamente ao revés do que hai que dicir. O castelán, o
coreano e o xaponés están actualizados; os outros quince, non.

**Hai dúas escalas distintas na mesma casa.** A portada decide se un contrasinal é
forte polos seus bits; o comprobador decídeo polo tempo que custaría rompelo.
Criterios distintos, e en ningún sitio o avisamos.

**O xerador e o comprobador non contan os mesmos símbolos**: un usa 27, o outro
supón 33. A diferenza é pequena, pero está aí.

Ningunha das tres é grave. As tres son débeda, e prefiren estar escritas aquí que
agardando a que as atope outro.

## O rexistro desta versión

Como o repositorio non é público, o rexistro de cambios vai aquí enteiro. Versión
**0.2.0**, do 31 de agosto de 2026:

**Engadido.** Política de seguridade de contido por páxina, coa pegada de cada
guión. O artigo sobre onde están os teus contrasinais gardados, nos dezaoito
idiomas. Unha cola editorial que decide que se escribe, e que manda non publicar
nada se queda baleira.

**Corrixido.** A descrición do comprobador, cortada a media frase en quince
idiomas, tres deles cun carácter partido pola metade. O bloqueo da lapela ao
teclear. O nesgo do sorteo. E a foto que faltaba no artigo anterior.

**Cambiado.** O título do comprobador en coreano, xaponés e vietnamita. O
despregamento, que agora se dispara cando o sitio construído xa existe e non un
minuto antes. E as traducións ao vietnamita, hindi e árabe, que deixan de bloquear
unha publicación aínda que sigan sendo as máis febles.

---

*As cifras deste artigo están medidas, non estimadas: os tempos de zxcvbn co mesmo
paquete que serve o sitio e contrasinais con palabras e substitucións; o nesgo do
sorteo, calculado sobre os 4.294.967.296 valores dun enteiro de 32 bits. O motor do
comprobador é [zxcvbn](https://github.com/dropbox/zxcvbn), de código aberto.*
