Skip to content
← 1001 Widgets
N° 007 · ●●○

Password

A strong password generator, adjustable in length, copied in one click. The right exercise to understand why Math.random() is not enough.

HTMLJS
What you'll learn
  • Draw at random with crypto.getRandomValues
  • Guarantee one character from each family
  • Copy to the clipboard with the Clipboard API
Why this language

Pourquoi un générateur ? Parce qu'un humain est un très mauvais générateur de hasard. On choisit des mots, des dates, des motifs. Une machine, elle, peut tirer chaque caractère sans préférence.

Le piège, c'est Math.random() : il est fait pour les jeux, pas pour la sécurité. Ici, on utilise crypto.getRandomValues(), le hasard cryptographique du navigateur.

Pourquoi en JavaScript simple ? Tout se passe dans le navigateur : le mot de passe n'est envoyé nulle part.

How it works
  1. LE HTML

    <output id="mdp"></output>
    <input id="longueur" type="range" min="8" max="64" value="20">
    <label><input type="checkbox" id="chiffres" checked> Chiffres</label>
    <label><input type="checkbox" id="symboles" checked> Symboles</label>
    <button id="generer">Générer</button>
    <button id="copier">Copier</button>
  2. LES ALPHABETS

    On retire l, I, O, 0 et 1 : impossibles à distinguer dans certaines polices.

    const LETTRES = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
    const CHIFFRES = '23456789';
    const SYMBOLES = '!@#$%&*?-_+=';
  3. UN TIRAGE SANS BIAIS

    crypto.getRandomValues donne des nombres imprévisibles. On rejette les valeurs trop hautes pour que chaque caractère ait exactement la même chance.

    function tirer(max) {
      const limite = Math.floor(4294967296 / max) * max;
      const n = new Uint32Array(1);
      do crypto.getRandomValues(n); while (n[0] >= limite);
      return n[0] % max;
    }
  4. GÉNÉRER

    function generer() {
      let alphabet = LETTRES;
      if (document.getElementById('chiffres').checked) alphabet += CHIFFRES;
      if (document.getElementById('symboles').checked) alphabet += SYMBOLES;
      const longueur = Number(document.getElementById('longueur').value);
      let mdp = '';
      for (let i = 0; i < longueur; i++) mdp += alphabet[tirer(alphabet.length)];
      document.getElementById('mdp').textContent = mdp;
    }
  5. COPIER

    L'API Clipboard est asynchrone : elle renvoie une promesse.

    document.getElementById('copier').addEventListener('click', async () => {
      await navigator.clipboard.writeText(document.getElementById('mdp').textContent);
    });
    document.getElementById('generer').addEventListener('click', generer);
    generer();
Pitfalls

PIÈGE 1 : Math.random()

Pitfall

Mauvais : alphabet[Math.floor(Math.random() * n)]. Math.random est prévisible : il n'est pas fait pour la sécurité.

Fix

Correct : crypto.getRandomValues(), disponible dans tous les navigateurs récents.

PIÈGE 2 : Le biais du modulo

Pitfall

Mauvais : n % alphabet.length directement. Certains caractères sortent un peu plus souvent que d'autres.

Fix

Correct : rejeter les tirages au-dessus du plus grand multiple de la taille de l'alphabet, comme dans tirer().

PIÈGE 3 : Des options cochées mais absentes

Pitfall

Mauvais : cocher « Chiffres » et obtenir un mot de passe sans chiffre, ce qui arrive sur les mots courts.

Fix

Correct : placer d'abord un caractère de chaque type coché, compléter, puis mélanger le tout (c'est ce que fait la démo).

PERSONNALISER
  • Un champ « caractères à exclure », retirés de l'alphabet avant le tirage.
  • Une phrase de passe : quatre mots tirés d'une liste, séparés par des tirets. Plus facile à retenir, aussi solide.
  • Le presse-papier vidé au bout de 30 secondes avec un setTimeout.
OPTIMISATION
  • Générez à chaque mouvement du curseur de longueur : le résultat suit le geste.
  • Affichez la force en bits : longueur × log2(taille de l'alphabet). C'est la base de la variante « Jauge de robustesse ».
VERS REACT

Les options vont dans un useState, le mot de passe se recalcule avec useMemo quand elles changent.

La copie reste une fonction appelée au clic, jamais pendant le rendu.

Variants
Comments
0/1000

Loading comments…

Audience measurement

With your consent, this site measures its traffic with Google Analytics and the Meta pixel, via Google Tag Manager. Nothing is loaded until you choose, and you can change your mind at any time with the "Cookies" link at the bottom of the page.