Cosa non andava in password.es, e adesso sì

Pubblicato il di David Carrero

Questo blog conta dodici articoli che spiegano come andrebbero fatte le cose: che la lunghezza conta più dei simboli, che un gestore non è una comodità ma l’unico modo di rispettare la regola, che una percentuale non dice niente.

Scriverlo è facile. La parte scomoda è guardare il proprio sito con lo stesso metro. Lo abbiamo fatto, e tre cose non andavano. Stanno qui per intero, con i numeri che le hanno tradite, perché un sito di sicurezza che pubblica solo i propri successi vale parecchio meno.

Il controllo si bloccava mentre scrivevi

Il controllo analizza la tua password con zxcvbn, una libreria che cerca schemi invece di contare maiuscole. Funziona benissimo e ha un costo: gira tutta insieme, sullo stesso thread che disegna la pagina. Mentre gira, il browser non può fare altro.

Quel costo cresce in fretta con la lunghezza. Misurato con lo stesso pacchetto che serve il sito, e con password come quelle che la gente scrive davvero — parole, anni, @ al posto di a:

lunghezza una esecuzione
16 caratteri 45 ms
20 caratteri 121 ms
32 caratteri 273 ms
64 caratteri 843 ms
128 caratteri 3.621 ms

Fin qui, normale. Il problema era quante volte la lanciavamo.

Il campo aveva due ascoltatori collegati, input e keyup. Un tasto normale li fa scattare entrambi. Così a ogni lettera digitata l’analisi completa girava due volte: 90 ms su una password di 16 caratteri, mezzo secondo su una di 32.

E niente la frenava: né un timer, né un limite di lunghezza, né un thread a parte. Oltre una ventina di caratteri il browser impiegava più tempo ad analizzare di quanto tu ne impiegassi a premere il tasto successivo. Le battute si accumulavano in una coda che non si svuotava più, e la pagina smetteva di rispondere mentre scrivevi. Incollare una password lunga la congelava per secondi.

La correzione sono due modifiche piccole. Abbiamo tolto l’ascoltatore keyup, perché input copre già digitazione, incolla, cancellazione e riempimento automatico del gestore: metà del lavoro sparisce senza cambiare nulla di quello che vedi. E abbiamo aggiunto un’attesa di 150 millisecondi: mentre scrivi non si analizza niente, e si analizza appena ti fermi. Nessuno digita così piano da accorgersene.

Il risultato è identico. Barcelona1992$ dice sempre le stesse cose: che «barcelona» sta nel dizionario, che 1992 sembra un anno, e che cade in meno di un secondo.

La descrizione era troncata a metà frase in quindici lingue

Questa è più sciocca e più imbarazzante.

La frase che appare sotto il titolo nel motore di ricerca — la meta description — era troncata in quindici delle diciotto lingue del controllo. Si salvavano solo spagnolo, coreano e giapponese. Qualcuno l’ha tagliata per lunghezza a un certo punto, ha reciso a metà parola, e dopo nessuno ha guardato.

In tre lingue il taglio è caduto in mezzo a un carattere speciale, quindi quello che pubblicavamo su Google era questo:

lingua cosa servivamo cosa doveva dire
portoghese …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

La cosa notevole è dove stava: sulla pagina che funziona meglio di tutto il sito. Il controllo converte molto meglio del generatore, e lo faceva con la descrizione rotta. Tutte e quindici sono complete.

Già che c’eravamo, in coreano, giapponese e vietnamita il marchio è passato dall’inizio alla fine del titolo. Nei risultati il dominio si vede comunque a parte, quindi aprire con «password.es ·» sprecava solo lo spazio che pesa di più.

Un bias di uno su cento milioni

Il generatore sceglie ogni carattere con crypto.getRandomValues(), la buona fonte di casualità del browser. Ma per trasformare quel numero enorme in «una posizione dell’alfabeto» usavamo un resto, e lì c’è una trappola classica: 2³² non è multiplo di 83, quindi le prime posizioni dell’alfabeto uscivano un pochettino più spesso delle ultime.

Quanto pochettino: con un alfabeto fino a 89 caratteri, dell’ordine di una parte su cento milioni. Non cambia niente. Non rende la tua password sensibilmente più debole, nemmeno lontanamente.

L’abbiamo corretto lo stesso, e sono tre righe: si scartano i 45 valori in eccesso sui 4.294.967.296 possibili e si risorteggia. Su un sito che parla di password, «è trascurabile» non è una buona ragione per lasciare un bias quando toglierlo costa così poco.

Cosa mancava: che il browser facesse rispettare la promessa

Abbiamo un articolo intero che spiega che la tua password non esce da qui. Era vero, e comunque era solo una nostra frase: tecnicamente nulla impediva a uno script iniettato di fare altro.

Ora ogni pagina porta una politica di sicurezza dei contenuti. Le due parti che contano:

  • Non gira nessuno script che non fosse nella pagina al momento di costruirla. Ogni script legittimo è firmato con la sua impronta; uno iniettato non corrisponde e il browser si rifiuta di eseguirlo.
  • connect-src 'none'. Il sito non fa una sola richiesta di rete da JavaScript, e adesso è il browser a imporlo. Se un giorno qualcosa provasse a mandare da qualche parte ciò che scrivi, non uscirebbe.

La promessa ha smesso di essere una dichiarazione ed è diventata una regola.

Cosa continua a non andare

Aggiornamento del 31 agosto. Le tre cose di questa sezione sono state sistemate lo stesso giorno in cui è uscito l’articolo: le quindici lingue ora descrivono il motore vero, le due scale sono una, e le FAQ del controllo spiegano la faccenda dei simboli. Restano scritte, perché il registro di ciò che non andava vale più della foto di un sito impeccabile.

Qui questo articolo si guadagna il posto.

Quindici lingue descrivono ancora il controllo come il motore vecchio. Il loro testo dice che riproduce la logica classica di PasswordMeter. Non più: quel motore è stato sostituito perché dava «molto forte» a Password1! e bocciava una frase di cinque parole, che è esattamente il contrario. Spagnolo, coreano e giapponese sono aggiornati; gli altri quindici no.

Ci sono due scale diverse nella stessa casa. La home decide se una password è forte in base ai bit; il controllo lo decide in base al tempo che costerebbe romperla. Criteri diversi, e da nessuna parte lo diciamo.

Generatore e controllo non contano gli stessi simboli: uno ne usa 27, l’altro ne suppone 33. La differenza è piccola, ma c’è.

Nessuna delle tre è grave. Tutte e tre sono debito, e preferiscono stare scritte qui piuttosto che aspettare che le trovi qualcun altro.

Il registro di questa versione

Siccome il repository non è pubblico, il registro delle modifiche sta qui per intero. Versione 0.2.0, del 31 agosto 2026:

Aggiunto. Una politica di sicurezza dei contenuti per pagina, con l’impronta di ogni script. L’articolo su dove sono le tue password salvate, in tutte e diciotto le lingue. Una coda editoriale che decide cosa si scrive, e che impone di non pubblicare niente quando si svuota.

Corretto. La descrizione del controllo, troncata a metà frase in quindici lingue, tre delle quali con un carattere spezzato a metà. Il blocco della scheda mentre scrivevi. Il bias del sorteggio. E la foto che mancava nell’articolo precedente.

Cambiato. Il titolo del controllo in coreano, giapponese e vietnamita. Il rilascio, che ora scatta quando il sito costruito esiste già e non un minuto prima. E le traduzioni in vietnamita, hindi e arabo, che smettono di bloccare una pubblicazione pur restando le più fragili.


Le cifre di questo articolo sono misurate, non stimate: i tempi di zxcvbn con lo stesso pacchetto che serve il sito e password con parole e sostituzioni; il bias del sorteggio, calcolato sui 4.294.967.296 valori di un intero a 32 bit. Il motore del controllo è zxcvbn, open source.

Foto di Ernandes Alves · Pexels

← Torna al blog