Aller au contenu
← 1001 Widgets
N° 007 · ●●○

Mot de passe

Un générateur de mots de passe solides, réglable en longueur, à copier d'un clic. Le bon exercice pour comprendre pourquoi Math.random() ne suffit pas.

HTMLJS
Ce qu'on apprend
  • Tirer au sort avec crypto.getRandomValues
  • Garantir un caractère de chaque famille
  • Copier dans le presse-papier avec l'API Clipboard
Pourquoi ce langage

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.

Comment ça marche
  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();
Pièges

PIÈGE 1 : Math.random()

Piège

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

Piège

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

Piège

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.

Variantes
Commentaires
0/1000

Chargement des commentaires…