Générateur cryptographiquement sûr – Loto, dés, entiers, décimaux
Un générateur de nombres aléatoires (RNG - Random Number Generator) produit des séquences de nombres imprévisibles. En informatique, on distingue deux types : PRNG (Pseudo-Random Number Generator) et TRNG (True Random Number Generator). Les PRNG utilisent des algorithmes mathématiques déterministes avec une graine initiale (seed). Même séquence avec même graine, donc prévisibles si on connaît l'algorithme et la graine. Exemple : Math.random() en JavaScript. Les TRNG exploitent des phénomènes physiques imprévisibles (bruit électronique, décroissance radioactive, mouvements souris). Vraiment aléatoires et non prévisibles. Exemple : crypto.getRandomValues() qui utilise les sources d'entropie du système.
crypto.getRandomValues() est la méthode recommandée en JavaScript pour générer des nombres aléatoires cryptographiquement sûrs. Elle accède aux générateurs d'entropie du système d'exploitation (timing processeur, interruptions hardware, bruit électronique). Contrairement à Math.random() qui utilise un PRNG simple et prévisible, crypto.getRandomValues() produit des nombres impossibles à prédire même en observant une longue séquence. Utilisations : cryptographie (clés, tokens), tirages au sort sensibles, jeux d'argent en ligne, génération d'identifiants uniques critiques.
La distribution uniforme signifie que tous les nombres d'une plage ont la même probabilité d'apparaître. Pour un dé à 6 faces équitable : chaque face a exactement 1/6 (16.67%) de chance. Pour générer correctement un nombre entier aléatoire entre min et max avec distribution uniforme, on doit éviter le biais du modulo. Méthode naïve biaisée : random % (max-min+1) + min introduit un biais si la plage ne divise pas parfaitement 2^32. Méthode correcte : rejeter les valeurs au-dessus d'un seuil pour garantir l'uniformité (rejection sampling). Notre générateur implémente cette méthode pour garantir des tirages parfaitement équitables.
Pour générer un nombre vraiment aléatoire en informatique, utilisez crypto.getRandomValues() en JavaScript, qui exploite les sources d'entropie du système (mouvements souris, timing processeur, bruit électronique des composants). C'est un générateur cryptographiquement sûr (CSPRNG), contrairement à Math.random() qui est pseudo-aléatoire et prévisible. Exemple : const array = new Uint32Array(1); crypto.getRandomValues(array); const random = array[0]. Pour un TRNG (True RNG) absolu, il faudrait du matériel dédié (bruit électronique amplifié, décroissance radioactive), mais crypto.getRandomValues() est suffisant pour 99.9% des usages incluant la cryptographie. Évitez Math.random() pour tout usage sécurisé (mots de passe, tokens, jeux d'argent) car il est prévisible avec un algorithme LCG (Linear Congruential Generator) simple.
Aléatoire vrai (TRNG) : imprévisible par nature, basé sur phénomènes physiques (bruit électronique, décroissance radioactive, turbulences atmosphériques). Impossible de reproduire la même séquence. Exemple : random.org utilise le bruit atmosphérique. Pseudo-aléatoire (PRNG) : suite déterministe générée par un algorithme mathématique à partir d'une graine (seed). Même graine = même séquence. Prévisible si on connaît l'algorithme et la graine. Exemple : Math.random() en JavaScript (algorithme xorshift128+ dans V8). Cryptographiquement sûr (CSPRNG) : pseudo-aléatoire avancé qui résiste à la prédiction même en observant des millions de valeurs. Exemple : crypto.getRandomValues(). Usage : TRNG pour cryptographie militaire/bancaire critique. CSPRNG (crypto.getRandomValues()) pour 99% des usages (mots de passe, tokens, jeux, tirages). PRNG simple (Math.random) uniquement pour simulations non-critiques, animations, jeux offline.
Math.random() ne doit JAMAIS être utilisé pour la sécurité car il est prévisible. Raisons : (1) Algorithme déterministe : Math.random() utilise xorshift128+ ou LCG (Linear Congruential Generator), algorithmes rapides mais prévisibles. (2) Graine limitée : initialisée avec timestamp ou valeur système, espace de graines limité (~2^53). Attaquant peut brute-forcer. (3) État observable : en observant quelques valeurs successives, un attaquant peut déduire l'état interne et prédire les suivantes. Démonstration : avec 3-4 valeurs Math.random(), on peut prédire toute la séquence future. (4) Non résistant cryptographiquement : ne passe pas les tests statistiques stricts de cryptographie. Dangers concrets : tokens session prévisibles → piratage comptes, clés crypto faibles → déchiffrement, tirages au sort truquables → fraude. Solution : toujours utiliser crypto.getRandomValues() pour génération tokens, mots de passe, clés, identifiants uniques, tirages au sort sensibles.
Pour tirer au sort sans doublon (nombres uniques), deux méthodes selon la plage : Méthode 1 - Mélange Fisher-Yates (optimal si beaucoup de tirages) : créer tableau contenant tous les nombres [1,2,3...N], mélanger aléatoirement avec Fisher-Yates, prendre les K premiers. Complexité O(N). Exemple : tirer 5 numéros entre 1-49 (loto). Méthode 2 - Tirage avec retrait (optimal si peu de tirages) : tirer un nombre, l'ajouter à un Set, recommencer jusqu'à avoir K uniques. Si tiré = déjà présent, retirer. Complexité O(K×log(N)). Notre générateur utilise méthode 1 pour garantir pas de répétition infinie. Piège à éviter : tirer aléatoirement puis filter() les doublons = biais statistique (premiers tirages favorisés). Applications : loto (5 numéros sur 49), distribution équipes (joueurs uniques), échantillonnage statistique sans remplacement.
Question philosophique ! En informatique classique, non, pas vraiment. Les ordinateurs sont déterministes : même entrée = même sortie. PRNG (Math.random) : suite déterministe qui simule l'aléatoire. Pas vraiment aléatoire, mais suffisamment imprévisible pour simulations, jeux. CSPRNG (crypto.getRandomValues) : utilise sources d'entropie système (timing interruptions, bruit hardware, mouvements souris). Plus proche du "vrai" aléatoire, mais théoriquement prévisible avec connaissance parfaite du système. En pratique : impossible à prédire. TRNG matériel : utilise phénomènes quantiques (bruit thermique résistances, décroissance radioactive). Aléatoire au sens physique quantique (principe d'incertitude Heisenberg). Conclusion pratique : crypto.getRandomValues() est "assez aléatoire" pour toute application terrestre (cryptographie militaire, banques, casinos en ligne). Seuls les physiciens quantiques et philosophes débattent encore si c'est "vraiment" aléatoire !