Ce qui n’allait pas sur password.es, et qui va mieux

Publié le par David Carrero

Ce blog compte douze articles qui expliquent comment il faudrait faire les choses : que la longueur compte plus que les symboles, qu’un gestionnaire n’est pas un confort mais le seul moyen de tenir la règle, qu’un pourcentage ne dit rien.

Écrire cela est facile. Le plus inconfortable, c’est de regarder son propre site avec la même exigence. Nous l’avons fait, et trois choses n’allaient pas. Elles figurent ici en entier, avec les chiffres qui les ont trahies, parce qu’un site de sécurité qui ne publie que ses réussites vaut nettement moins.

Le vérificateur figeait pendant que vous tapiez

Le vérificateur analyse votre mot de passe avec zxcvbn, une bibliothèque qui cherche des motifs au lieu de compter les majuscules. Elle fonctionne très bien et elle a un coût : elle s’exécute d’un bloc, sur le fil qui dessine la page. Pendant ce temps, le navigateur ne peut rien faire d’autre.

Ce coût grimpe vite avec la longueur. Mesuré avec le paquet même que sert le site, et avec des mots de passe comme ceux que les gens tapent vraiment — des mots, des années, @ à la place de a :

longueur une exécution
16 caractères 45 ms
20 caractères 121 ms
32 caractères 273 ms
64 caractères 843 ms
128 caractères 3 621 ms

Jusque-là, rien d’anormal. Le problème, c’était le nombre de fois où nous la lancions.

Le champ avait deux écouteurs branchés, input et keyup. Une touche ordinaire déclenche les deux. Donc à chaque lettre tapée, l’analyse complète tournait deux fois : 90 ms pour un mot de passe de 16 caractères, une demi-seconde pour un de 32.

Et rien ne la freinait : ni minuteur, ni limite de longueur, ni fil séparé. Au-delà d’une vingtaine de caractères, le navigateur mettait plus de temps à analyser que vous à appuyer sur la touche suivante. Les frappes s’empilaient dans une file qui ne se vidait plus, et la page cessait de répondre pendant la saisie. Coller un mot de passe long la figeait plusieurs secondes.

La correction tient en deux petits changements. Nous avons retiré l’écouteur keyup, car input couvre déjà la frappe, le collage, l’effacement et le remplissage automatique du gestionnaire : la moitié du travail disparaît sans rien changer à ce que vous voyez. Et nous avons ajouté une attente de 150 millisecondes : rien n’est analysé pendant que vous tapez, et tout est analysé dès que vous vous arrêtez. Personne ne tape assez lentement pour le remarquer.

Le résultat est identique. Barcelona1992$ dit toujours la même chose : que « barcelona » est dans le dictionnaire, que 1992 ressemble à une année, et que cela tombe en moins d’une seconde.

La description était coupée en plein milieu dans quinze langues

Celle-ci est plus bête et plus gênante.

La phrase qui apparaît sous le titre dans le moteur de recherche — la meta description — était tronquée dans quinze des dix-huit langues du vérificateur. Seuls l’espagnol, le coréen et le japonais s’en sortaient. Quelqu’un l’a rognée par longueur à un moment, a coupé en plein mot, et personne n’a regardé ensuite.

Dans trois langues, la coupe est tombée au milieu d’un caractère spécial : ce que nous publiions dans Google, c’était ceci.

langue ce que nous servions ce qu’il fallait lire
portugais …datas e padr&o padrões
turc …arıyor ve ger&cced gerçekten
vietnamien …chúng tôi tra mật kh&# mật khẩu

Le plus frappant, c’est où : sur la page qui fonctionne le mieux de tout le site. Le vérificateur convertit bien mieux que le générateur, et il le faisait avec une description cassée. Les quinze sont complétées.

Au passage, en coréen, en japonais et en vietnamien, la marque est passée du début à la fin du titre. Dans les résultats, le domaine s’affiche déjà à part : commencer par « password.es · » ne faisait que gaspiller la place qui compte le plus.

Un biais d’un sur cent millions

Le générateur choisit chaque caractère avec crypto.getRandomValues(), la bonne source de hasard du navigateur. Mais pour transformer ce très grand nombre en « une position dans l’alphabet », nous faisions un reste de division, et il y a là un piège classique : 2³² n’est pas un multiple de 83, donc les premières positions de l’alphabet sortaient un tout petit peu plus souvent que les dernières.

De combien : avec un alphabet allant jusqu’à 89 caractères, de l’ordre d’une partie sur cent millions. Cela ne change rien. Cela ne rend pas votre mot de passe mesurablement plus faible, loin de là.

Nous l’avons corrigé quand même, et cela tient en trois lignes : on écarte les 45 valeurs excédentaires sur les 4 294 967 296 possibles et on retire au sort. Sur un site consacré aux mots de passe, « c’est négligeable » n’est pas une bonne raison de laisser un biais quand l’enlever coûte si peu.

Ce qui manquait : que le navigateur fasse respecter la promesse

Nous avons un article entier qui explique que votre mot de passe ne sort pas d’ici. C’était vrai, et pourtant ce n’était qu’une phrase de notre part : rien n’empêchait techniquement un script injecté de faire autre chose.

Désormais chaque page porte une politique de sécurité du contenu. Les deux points qui comptent :

  • Aucun script ne s’exécute s’il n’était pas dans la page à sa construction. Chaque script légitime est signé par son empreinte ; un script injecté ne correspond pas et le navigateur refuse de l’exécuter.
  • connect-src 'none'. Le site ne fait pas une seule requête réseau depuis JavaScript, et c’est maintenant le navigateur qui l’impose. Si un jour quelque chose tentait d’envoyer ce que vous tapez, cela ne sortirait pas.

La promesse a cessé d’être une déclaration pour devenir une règle.

Ce qui ne va toujours pas

Mise à jour du 31 août. Les trois points de cette section ont été corrigés le jour même de la publication de cet article : les quinze langues décrivent désormais le vrai moteur, les deux échelles n’en font qu’une, et la FAQ du vérificateur explique l’affaire des symboles. Ils restent écrits, car le registre de ce qui a cloché vaut plus que la photo d’un site impeccable.

C’est ici que cet article justifie sa place.

Quinze langues décrivent encore le vérificateur comme l’ancien moteur. Leur texte dit qu’il reproduit la logique classique de PasswordMeter. Plus maintenant : ce moteur a été remplacé parce qu’il jugeait Password1! très fort et recalait une phrase de cinq mots, soit exactement l’inverse. L’espagnol, le coréen et le japonais sont à jour ; les quinze autres, non.

Il y a deux échelles différentes dans la même maison. La page d’accueil décide de la force d’un mot de passe par ses bits ; le vérificateur décide par le temps qu’il faudrait pour le casser. Deux critères, et nulle part nous ne le disons.

Le générateur et le vérificateur ne comptent pas les mêmes symboles : l’un en utilise 27, l’autre en suppose 33. L’écart est faible, mais il existe.

Aucune des trois n’est grave. Toutes les trois sont de la dette, et elles préfèrent être écrites ici qu’attendre que quelqu’un d’autre les trouve.

Le journal de cette version

Le dépôt n’étant pas public, le journal des modifications figure ici en entier. Version 0.2.0, du 31 août 2026 :

Ajouté. Une politique de sécurité du contenu par page, avec l’empreinte de chaque script. L’article sur l’endroit où se trouvent vos mots de passe enregistrés, dans les dix-huit langues. Une file éditoriale qui décide de ce qui s’écrit, et qui ordonne de ne rien publier quand elle se vide.

Corrigé. La description du vérificateur, coupée en plein milieu dans quinze langues, dont trois avec un caractère tranché en deux. Le blocage de l’onglet pendant la saisie. Le biais du tirage. Et la photo manquante de l’article précédent.

Modifié. Le titre du vérificateur en coréen, japonais et vietnamien. Le déploiement, qui se déclenche désormais une fois le site construit et non une minute avant. Et les traductions en vietnamien, hindi et arabe, qui cessent de bloquer une publication tout en restant les plus fragiles.


Les chiffres de cet article sont mesurés, pas estimés : les temps de zxcvbn avec le paquet même que sert le site et des mots de passe contenant des mots et des substitutions ; le biais du tirage, calculé sur les 4 294 967 296 valeurs d’un entier de 32 bits. Le moteur du vérificateur est zxcvbn, en source ouverte.

Photo de Ernandes Alves · Pexels

← Retour au blog