En quoi les nombres pseudo-aléatoires et les nombres véritablement aléatoires sont-ils différents et pourquoi est-ce important?

664

Je n'ai jamais vraiment eu ça. Dites simplement que vous écrivez un petit programme dans n'importe quelle langue qui lance des dés (en utilisant les dés comme exemple). Après 600 000 lancers, chaque nombre aurait été roulé environ 100 000 fois, ce à quoi je m'attendais.

Pourquoi existe-t-il des sites Web dédiés au «vrai hasard»? Étant donné l'observation ci-dessus, les chances d'obtenir n'importe quel nombre sont presque exactement égales à 1, quel que soit le nombre de nombres qu'il peut choisir.

Je l'ai essayé en Python : voici le résultat de 60 millions de rouleaux. La variation la plus élevée est de 0,15. N'est-ce pas aussi aléatoire que cela va arriver?

1 - 9997653 2347.0
2 - 9997789 2211.0
3 - 9996853 3147.0
4 - 10006533 -6533.0
5 - 10002774 -2774.0
6 - 9998398 1602.0
Peter
la source
1
Consultez l' article de wikipedia sur les nombres aléatoires générés par le matériel. Voir aussi: stats.stackexchange.com/questions/32794/…
steadyfish
21
Qu'entendez-vous par "lance des dés"? At-il un bras de robot et une caméra attachés?
starblue
3
alors que je suis d' accord avec le sens général de votre ton, que nous nous inquiétons souvent ce trop, mais il a été exploité dans la vie réelle: en.wikipedia.org/wiki/Ronald_Dale_Harris
Grady joueur
3
Voyez cet article sur un jeu de poker en ligne manquant de véritable caractère aléatoire pour son importance.
Varaquilex
1
Si vous ne faites que garder un compteur de 0 à 5 et lancer un dé en conséquence, 666 milliards de fois, vous obtiendrez également une distribution égale.
jcora

Réponses:

1383

Jouons au poker informatique, juste vous, moi et un serveur auquel nous faisons confiance. Le serveur utilise un générateur de nombre pseudo-aléatoire qui est initialisé avec une graine 32 bits juste avant de jouer. Il y a donc environ quatre milliards de ponts possibles.

J'ai cinq cartes dans la main - apparemment, nous ne jouons pas au Texas Hold 'Em. Supposons que les cartes soient distribuées une pour moi, une pour vous, une pour moi, une pour vous, etc. J'ai donc les première, troisième, cinquième, septième et neuvième cartes dans le paquet.

Auparavant, j'avais exécuté le générateur de nombres pseudo-aléatoires quatre milliards de fois, une fois avec chaque graine, et noté la première carte générée pour chacune dans une base de données. Supposons que ma première carte est la reine de pique. Cela ne représente qu'une carte parmi les premières cartes sur 52, nous avons donc réduit le nombre de cartes possibles de quatre à environ 80 millions.

Supposons que ma deuxième carte est le trois de coeurs. Maintenant, je lance mon RNG 80 millions de fois en utilisant les 80 millions de graines qui produisent la reine de pique comme premier chiffre. Cela me prend quelques secondes. J'écris tous les paquets qui produisent les trois coeurs comme la troisième carte - la deuxième carte dans ma main. Encore une fois, cela ne représente que 2% environ des ponts. Nous en sommes maintenant à 2 millions.

Supposons que la troisième carte dans ma main est le 7 des clubs. J'ai une base de données de 2 millions de graines qui distribue mes deux cartes; Je lance mon RNG encore 2 millions de fois pour trouver la troisième carte des 2% de ces decks qui produisent les 7 clubs, et il ne reste plus que 40 000 decks.

Vous voyez comment cela se passe. Je lance plusieurs fois mon RNG 40000 pour trouver toutes les graines qui produisent ma quatrième carte, ce qui nous ramène à 800 decks, puis je le lance encore 800 fois pour obtenir les ~ 20 graines qui produisent ma cinquième carte. générer ces vingt jeux de cartes et je sais que vous avez l'une des vingt mains possibles. De plus, j'ai une très bonne idée de ce que je vais dessiner ensuite.

Maintenant, voyez-vous pourquoi le vrai hasard est important? Selon votre description, la distribution est importante, mais ce n’est pas ce qui rend un processus aléatoire. L’imprévisibilité est ce qui rend un processus aléatoire.

MISE À JOUR

D'après les commentaires (maintenant supprimés en raison de leur nature non constructive), au moins 0,3% des personnes qui ont lu ceci sont confus quant à mon point. Quand les gens vont à l' encontre des points que je ne l' ai pas fait, ou pire, faire valoir des points que je ne fais l'hypothèse que je ne les ai pas, je sais que je dois expliquer plus clairement et soigneusement.

Il semble y avoir une confusion particulière autour de la distribution des mots , je tiens donc à rappeler les usages avec soin.

Les questions à résoudre sont les suivantes:

  • Comment les nombres pseudo-aléatoires et les nombres vraiment aléatoires diffèrent-ils?
  • Pourquoi la différence est-elle importante?
  • Les différences ont-elles quelque chose à voir avec la distribution de la production du PRNG?

Commençons par examiner le moyen idéal pour générer un jeu de cartes aléatoire permettant de jouer au poker. Ensuite, nous verrons en quoi les autres techniques de génération de decks sont différentes et s'il est possible de tirer parti de cette différence.

Commençons par supposer que nous avons une boîte magique étiquetée TRNG. En entrée, nous lui donnons un entier n supérieur ou égal à un et en sortie, un nombre véritablement aléatoire compris entre un et n, inclus. La sortie de la boîte est totalement imprévisible (lorsqu'on lui attribue un nombre autre qu'un) et tout nombre compris entre un et n est aussi probable qu'un autre; c'est-à-dire que la distribution est uniforme . (Nous pourrions effectuer d'autres vérifications statistiques plus poussées de l'aléa statistique; j'ignore ce point car cela ne correspond pas à mon argument. TRNG est parfaitement statistiquement aléatoire par hypothèse.)

Nous commençons avec un jeu de cartes non mélangé. Nous demandons à la case un nombre compris entre un et 52 - c'est-à-dire TRNG(52),. Quel que soit le nombre de cartes rendues, nous comptons le nombre de cartes de notre deck trié et retirons cette carte. Cela devient la première carte du jeu mélangé. Ensuite, nous demandons TRNG(51)et faisons de même pour sélectionner la deuxième carte, et ainsi de suite.

Une autre façon de voir les choses est la suivante: il y en a 52! = 52 x 51 x 50 ... x 2 x 1 ponts possibles, ce qui correspond à environ 2 226 . Nous avons choisi l'un d'entre eux au hasard.

Maintenant, nous distribuons les cartes. Quand je regarde mes cartes, je n'ai aucune idée de ce que vous avez. (Mis à part le fait évident que vous n'avez aucune des cartes que j'ai.) Ce pourrait être n'importe quelle carte, avec une probabilité égale.

Alors laissez-moi m'assurer que je l'explique clairement. Nous avons une distribution uniforme de chaque sortie individuelle de TRNG(n); chacun choisit un nombre compris entre 1 et n avec une probabilité de 1 / n. En outre, le résultat de ce processus est que nous avons choisi l'un des 52! ponts possibles avec une probabilité de 1/52 !, de sorte que la distribution sur l’ensemble des ponts possibles est également uniforme.

D'accord.

Supposons maintenant que nous ayons une boîte moins magique, étiquetée PRNG. Avant de pouvoir l' utiliser, il doit être tête de série avec un nombre non signé de 32 bits.

AUSSI: Pourquoi 32 ? Ne pourrait-il pas être associé à un nombre de 64, 256 ou 10 000 bits? Sûr. Mais (1) dans la pratique, la plupart des PRNG disponibles dans le commerce sont associées à un nombre de 32 bits et (2) si vous avez 10 000 bits aléatoires pour créer la graine, pourquoi utilisez-vous un PRNG? Vous avez déjà une source de 10000 bits de hasard!

Quoi qu'il en soit, revenons à la façon dont fonctionne le PRNG: une fois qu’il a été semé, vous pouvez l’utiliser de la même façon TRNG. C'est-à-dire que vous lui attribuez un nombre n et qu'il vous restitue un nombre compris entre 1 et n inclus. De plus, la distribution de cette production est plus ou moins uniforme . Autrement dit, lorsque nous demandons PRNGun nombre compris entre 1 et 6, nous obtenons 1, 2, 3, 4, 5 ou 6 chacun environ un sixième du temps, quelle que soit la graine.

Je tiens à souligner ce point à plusieurs reprises, car il semble que ce soit la source de confusion pour certains commentateurs. La distribution du PRNG est uniforme à au moins deux égards. Premièrement, supposons que nous choisissions une graine en particulier. Nous nous attendions à ce que la séquence PRNG(6), PRNG(6), PRNG(6)...un million de fois produise une distribution uniforme de nombres entre 1 et 6. Et deuxièmement, si nous choisissions un million de semences différentes et appelions PRNG(6) une fois pour chaque graine, nous nous attendrions à une distribution uniforme de nombres de 1 à 6. L'uniformité du GNRP au cours de l'une ou l'autre de ces opérations n'est pas pertinente pour l'attaque que je décris .

Ce processus est dit pseudo-aléatoire car le comportement de la boîte est en réalité totalement déterministe; il choisit parmi l'un des 2 32 comportements possibles en fonction de la graine. C'est-à-dire qu'une fois qu'il est semé, il PRNG(6), PRNG(6), PRNG(6), ... produit une séquence de nombres avec une distribution uniforme, mais cette séquence est entièrement déterminée par la graine. Par exemple, pour une séquence d'appels donnée, PRNG (52), PRNG (51), etc., il n'y a que 2 32 séquences possibles. La graine choisit essentiellement celle que nous obtenons.

Pour générer une plate-forme, le serveur génère maintenant une graine. (Comment? Nous reviendrons sur ce point.) Ensuite , ils appellent PRNG(52), PRNG(51)et ainsi de suite pour générer la plate - forme, semblable auparavant.

Ce système est sujet à l'attaque que j'ai décrite. Pour attaquer le serveur, nous devons d'abord, à l'avance, ensemencer notre propre copie de la boîte avec 0, puis demander PRNG(52)et écrire cette information. Ensuite, nous re-semons avec 1, demandons PRNG(52)et notons-le jusqu’à 2 32 -1.

Maintenant, le serveur de poker qui utilise PRNG pour générer des decks doit générer une graine en quelque sorte. Peu importe comment ils le font. Ils pourraient appeler TRNG(2^32)pour obtenir une graine vraiment aléatoire. Ils pourraient aussi prendre l’heure actuelle comme une graine, ce qui n’est guère aléatoire. Je sais quelle heure il est autant que toi. Le point de mon attaque est que cela n’a aucune importance, car j’ai ma base de données . Quand je vois ma première carte, je peux éliminer 98% des graines possibles. Quand je vois ma deuxième carte, je peux éliminer 98% de plus, et ainsi de suite, jusqu'à ce que je puisse finalement en arriver à une poignée de semences possibles et savoir avec une grande probabilité ce qui est dans votre main.

Maintenant, encore une fois, je tiens à souligner que l’hypothèse retenue ici est que si nous appelions PRNG(6)un million de fois, nous aurions chaque numéro environ un sixième du temps . Cette distribution est (plus ou moins) uniforme , et si l'uniformité de cette distribution est tout ce qui vous intéresse , c'est bien. La question était la suivante: y a-t-il autre chose que la distribution de ce PRNG(6)qui nous intéresse? et la réponse est oui . Nous nous soucions également de l' imprévisibilité .

Une autre façon d’envisager le problème est que, même si la distribution d’un million d’appels PRNG(6)pourrait bien se dérouler, car le PRNG choisit parmi seulement 2 32 comportements possibles, il ne peut pas générer toutes les réponses possibles. Il ne peut générer que 2 32 des 2 226 ponts possibles; une infime fraction. La distribution sur l’ensemble des decks est donc très mauvaise. Mais là encore, l’attaque fondamentale consiste à pouvoir prédire avec succès le comportement passé et futur d’ PRNGun petit échantillon de ses résultats.

Permettez-moi de dire ceci une troisième ou quatre fois pour m'assurer que cela est bien intégré. Premièrement, la distribution du processus qui produit la graine aléatoire 32 bits. Cela peut être parfaitement aléatoire, imprévisible et uniforme et l’attaque fonctionnera toujours . Deuxièmement, la distribution d'un million d'appels à PRNG(6). Cela peut être parfaitement uniforme et l’attaque fonctionnera toujours. Troisièmement, la distribution des paquets choisie par le processus pseudo-aléatoire que j'ai décrit. Cette distribution est extrêmement pauvre; seule une infime fraction des ponts IRL possibles peut éventuellement être choisie. L'attaque dépend de la prévisibilité du comportement du PRNG sur la base d'une connaissance partielle de ses résultats .

EN DEHORS: Cette attaque nécessite que l'attaquant sache ou soit capable de deviner quel est l'algorithme exact utilisé par le PRNG. Que ce soit réaliste ou non est une question ouverte. Cependant, lors de la conception d'un système de sécurité, vous devez le concevoir pour qu'il soit sécurisé contre les attaques, même si l'attaquant connaît tous les algorithmes du programme . En d'autres termes: la partie d'un système de sécurité qui doit rester secrète pour que le système soit sécurisé s'appelle la "clé". Si votre système dépend pour sa sécurité des algorithmes que vous utilisez étant un secret, votre clé contient ces algorithmes . C'est une position extrêmement faible pour être dans!

Passer à autre chose

Supposons maintenant que nous ayons une troisième boîte magique étiquetée CPRNG. C'est une version de crypto-force de PRNG. Il faut une graine 256 bits plutôt qu'une graine 32 bits. Il partage avec PRNGla propriété que la graine choisit parmi l’un des 2 256 comportements possibles. Et, à l'instar de nos autres machines, il a la propriété de faire un grand nombre d'appels pour CPRNG(n)produire une distribution uniforme des résultats entre 1 et n: chacune se produit 1 / n des fois. Pouvons-nous lancer notre attaque contre elle?

Notre attaque initiale nécessite que nous stockions 2 32 cartographies à partir de graines PRNG(52). Mais 2 256 est un nombre beaucoup plus grand; il est totalement impossible de l'exécuter CPRNG(52)autant de fois et de stocker les résultats.

Mais supposons qu'il y ait un autre moyen de prendre la valeur CPRNG(52)et d'en déduire un fait à propos de la graine? Nous avons été assez stupides jusqu'à présent, nous avons simplement forcé toutes les combinaisons possibles. Pouvons-nous regarder à l'intérieur de la boîte magique, comprendre comment cela fonctionne et déduire des faits sur la graine en fonction de la sortie?

Non . Les détails sont trop compliquées à expliquer, mais CPRNGs sont intelligemment conçus de sorte qu'il est impossible d' en déduire tout fait utile sur la graine de la première sortie CPRNG(52)ou de tout sous - ensemble de la production, peu importe la taille .

OK, supposons maintenant que le serveur utilise CPRNGpour générer des decks. Il faut une graine de 256 bits. Comment choisit-il cette graine? S'il choisit une valeur qu'un attaquant peut prédire , l'attaque redevient soudainement viable . Si nous pouvons déterminer que sur les 2 256 semences possibles, seuls quatre milliards d'entre elles sont susceptibles d'être choisies par le serveur, nous sommes de retour dans les affaires . Nous pouvons à nouveau monter cette attaque, en ne prêtant attention qu'au petit nombre de graines pouvant éventuellement être générées.

Le serveur doit donc faire en sorte que le nombre de 256 bits soit uniformément distribué - en d’autres termes, chaque graine possible est choisie avec une probabilité de 1/2 256 . Fondamentalement, le serveur devrait appeler TRNG(2^256)-1pour générer le germe CPRNG.

Que se passe-t-il si je peux pirater le serveur et y jeter un œil pour voir quelle graine a été choisie? Dans ce cas, l'attaquant connaît tout le passé et l'avenir du CPRNG . L'auteur du serveur doit se prémunir contre cette attaque! (Bien sûr, si je réussis à monter cette attaque, je pourrai probablement aussi transférer l'argent directement sur mon compte bancaire, alors ce n'est peut-être pas si intéressant. L'important, c'est que la graine doit être un secret difficile à deviner, et nombre vraiment aléatoire 256 bits est sacrément difficile à deviner.)

Revenons à mon point précédent sur la défense en profondeur: la valeur de départ de 256 bits est la clé de ce système de sécurité. L'idée d'un CPRNG est que le système est sécurisé tant que la clé est sécurisée . Même si tous les autres faits concernant l'algorithme sont connus, tant que vous pouvez garder la clé secrète, les cartes de l'adversaire sont imprévisibles.

OK, la graine doit donc être à la fois secrète et uniformément distribuée, sinon, nous pouvons organiser une attaque. Nous supposons que la distribution des produits CPRNG(n)est uniforme. Qu'en est-il de la distribution sur l'ensemble des decks possibles?

Vous pourriez dire: le CPRNG produit 2 256 séquences possibles, mais il n’ya que 2 226 ponts possibles. Par conséquent, il y a plus de séquences possibles que de decks, donc tout va bien; toutes les cartes IRL possibles sont maintenant (avec une probabilité élevée) possibles dans ce système. Et c'est un bon argument, sauf que ...

2 226 n’est qu’une approximation de 52 !. Divisez-le. 2 256/52 ! ne peut pas être un nombre entier parce que, d'une part, 52! est divisible par 3 mais aucune puissance de deux n'est! Comme il ne s’agit pas d’un nombre entier, nous sommes dans une situation où tous les ponts sont possibles , mais certains ponts sont plus susceptibles que d’autres .

Si ce n'est pas clair, considérons la situation avec des nombres plus petits. Supposons que nous ayons trois cartes, A, B et C. Supposons que nous utilisions un PRNG avec une graine à 8 bits, il y a donc 256 graines possibles. Il y a 256 sorties possibles de PRNG(3)selon la graine; il est impossible qu'un tiers d'entre eux soit A, un tiers d'entre eux B et un tiers d'entre eux C, car 256 n'est pas également divisible par 3. Il doit y avoir un léger parti pris pour l'un d'eux.

De même, 52 ne se divise pas également en 2 256 , il doit donc y avoir un biais envers certaines cartes en tant que première carte choisie et un biais par rapport aux autres.

Dans notre système original avec une graine 32 bits, il y avait un biais énorme et la grande majorité des ponts possibles n’ont jamais été produits. Dans ce système, tous les ponts peuvent être produits, mais la distribution des ponts est toujours défectueuse . Certains ponts sont très légèrement plus susceptibles que d'autres.

Maintenant, la question est: avons-nous une attaque basée sur cette faille? et la réponse est en pratique, probablement pas . CPRNGs sont conçus de telle sorte que si la graine est vraiment aléatoire alors il est infaisable de faire la différence entre CPRNGet TRNG.

OK, alors résumons.

Comment les nombres pseudo-aléatoires et les nombres vraiment aléatoires diffèrent-ils?

Ils diffèrent par le niveau de prévisibilité qu'ils présentent.

  • Les nombres vraiment aléatoires ne sont pas prévisibles.
  • Tous les nombres pseudo-aléatoires sont prévisibles si la graine peut être déterminée ou devinée.

Pourquoi la différence est-elle importante?

Parce qu'il existe des applications où la sécurité du système repose sur l' imprévisibilité .

  • Si un TRNG est utilisé pour choisir chaque carte, le système est inattaquable.
  • Si un CPRNG est utilisé pour choisir chaque carte, le système est sécurisé si la valeur de départ est imprévisible et inconnue.
  • Si un PRNG ordinaire avec un petit espace d’origine est utilisé, le système n’est pas sécurisé, que l’initialisation soit imprévisible ou inconnue; un espace de germination assez petit est susceptible d'attaques par force brute du type que j'ai décrit.

La différence a-t-elle quelque chose à voir avec la distribution de la production du PRNG?

L'uniformité de la distribution ou de l' absence de celle - ci pour des appels individuels à RNG(n)ne concerne pas les attaques que je viens de décrire.

Comme nous l’avons vu, a PRNGet CPRNGproduit de mauvaises distributions de la probabilité de choisir n’importe quel deck de tous les decks possibles. Le PRNGest considérablement pire, mais les deux ont des problèmes.

Encore une question:

Si TRNG est tellement meilleur que CPRNG, qui à son tour est tellement meilleur que PRNG, pourquoi quelqu'un utilise-t-il CPRNG ou PRNG?

Deux raisons.

Premièrement: les dépenses. TRNG est cher . Générer des nombres vraiment aléatoires est difficile. Les CPRNG donnent de bons résultats pour un nombre arbitraire d'appels avec un seul appel à TRNG pour la graine d'origine. L'inconvénient est bien sûr que vous devez garder cette graine secrète .

Deuxièmement: nous voulons parfois de la prévisibilité et la distribution nous importe simplement . Si vous générez des données "aléatoires" en tant qu'entrées de programme pour une suite de tests et que cela indique un bogue, il serait bien que l'exécution de la suite de tests produise à nouveau le bogue!

J'espère que c'est maintenant beaucoup plus clair.

Enfin, si vous appréciez cela, vous pourrez approfondir vos connaissances sur le hasard et les permutations:

Eric Lippert
la source
20
Ok, les garçons et les filles. C'est assez commentant pour le moment. Si vous voulez en discuter plus avant, allez vous chercher un salon de discussion, kthnxbye!
Ivo Flipse
1
@Eric Mais la graine n'est pas réinitialisée avant chaque nouveau tirage au sort, n'est-ce pas? Ainsi, bien que vous ayez raison de dire que nous n’échantillons que peu de trajectoires , vous ne savez pas exactement où vous vous trouvez dans la trajectoire actuelle et les trajectoires se croisent.
AS
Un bon (mais dense) traitement des problèmes connexes est présenté dans la section 3.5 «Qu'est-ce qu'une séquence aléatoire?» De TAOCP, volume 2, de Knuth (p. 149), commençant par éclairer les définitions des séquences équidistribuées, distribuées k et distribuées. Les séquences pseudo-aléatoires sont discutées dans 3.5.F (p. 170). Voir aussi les critères de pseudo-aléas de la théorie de la complexité et du BSI allemand .
ShreevatsaR
160

Comme le dit Eric Lippert, il ne s'agit pas uniquement de la distribution. Il existe d'autres moyens de mesurer le caractère aléatoire.

L'un des premiers générateurs de nombres aléatoires a une séquence dans le bit le moins significatif - il alterne les 0 et les 1. Par conséquent, le LSB était prévisible à 100%. Mais vous devez vous soucier de plus que cela. Chaque bit doit être imprévisible.

Voici un bon moyen de réfléchir au problème. Disons que vous générez 64 bits de hasard. Pour chaque résultat, prenez les 32 premiers bits (A) et les 32 derniers bits (B), et créez un index dans un tableau x [A, B]. Effectuez maintenant le test un million de fois et, pour chaque résultat, incrémentez le tableau à ce nombre, c’est-à-dire X [A, B] ++;

Dessinez maintenant un diagramme 2D, où plus le nombre est grand, plus le pixel est lumineux à cet endroit.

Si c'est vraiment aléatoire, la couleur devrait être un gris uniforme. Mais vous pourriez avoir des modèles. Prenez par exemple ce diagramme du "caractère aléatoire" dans le numéro de séquence TCP du système Windows NT:

Windows NT

ou même celui-ci sous Windows 98:

Windows 98

Et voici le caractère aléatoire de la mise en œuvre du routeur Cisco (IOS). Cisco ISO

Ces diagrammes sont une gracieuseté du papier de Michał Zalewski . Dans ce cas particulier, si on peut prédire ce que sera le numéro de séquence TCP d'un système, on pourra emprunter l'identité de ce système lors de l'établissement d'une connexion à un autre système - ce qui permettrait le détournement de connexions, l'interception de communications, etc. ne peut pas prédire le prochain nombre 100% du temps, si nous pouvons provoquer la création d'une nouvelle connexion sous notre contrôle , nous pouvons augmenter les chances de succès. Et lorsque des ordinateurs peuvent générer 100 000 connexions en quelques secondes, les chances d’une attaque réussie vont d’astronomiques à possibles ou même probables.

Bruce Barnett
la source
30
C'est tellement brillant que j'en ai les larmes aux yeux. Il devrait y avoir une application qui les crée pour chaque système d'exploitation (mobile / desktop / serveur) et chaque plate-forme (JVM / Javascript / etc).
HDave
5
La fonction Windows rand () est plutôt bonne! Il en résulte un nuage qui ne présente aucune structure apparente. Voir mon implémentation pour l'essayer (et d'autres algorithmes): github.com/Zalastax/visualize_random
Zalastax
93

Bien que les nombres pseudo-aléatoires générés par les ordinateurs soient acceptables pour la majorité des cas d'utilisation rencontrés par les utilisateurs d'ordinateurs, il existe des scénarios qui nécessitent des nombres aléatoires complètement imprévisibles.

Dans les applications sensibles à la sécurité telles que le cryptage, un générateur de nombres pseudo-aléatoires (PRNG) peut produire des valeurs qui, bien qu'apparemment aléatoires, sont en fait prévisibles par un attaquant. Une personne qui tente de déchiffrer un système de chiffrement peut être en mesure de deviner les clés de chiffrement si un PRNG a été utilisé et que l'attaquant dispose d'informations sur l'état du PRNG. Par conséquent, pour de telles applications, un générateur de nombre aléatoire qui produit des valeurs qui sont vraiment impossibles à deviner est nécessaire. Notez que certains PRNG sont conçus pour être sécurisés de manière cryptographique et sont utilisables pour de telles applications sensibles à la sécurité.

Plus d'informations sur les attaques RNG peuvent être trouvées dans cet article Wikipedia .

bwDraco
la source
9
Les PRNG cryptographiques existent et sont largement utilisés. Ils peuvent, à partir d’une graine de taille modeste, générer un flux pratiquement illimité de nombres aléatoires. Du point de vue des calculs, il est impossible de distinguer un tel flux des vrais nombres aléatoires. Par conséquent, aucune information supplémentaire ne peut être obtenue à partir de quelque partie que ce soit d'un tel flux, et dans un but pratique, les nombres valent aussi bien que les vrais nombres aléatoires.
aaaaaaaaaaaaa
Je pense que la meilleure façon d’expliquer cela est que des algorithmes générateurs de nombres aléatoires doivent être programmés. Cela signifie qu’un ensemble d’instructions est suivi. S'il y a un ensemble d'instructions, cela ne peut pas être aléatoire.
Keltari
6
@Keltari Il manque l'élément d'entropie ... La plupart des RNG (au moins ceux cryptographiques) recueillent des informations provenant de sources extérieures (par exemple, des mouvements de souris) et les utilisent comme partie de la condition de départ - ainsi, la transformation de Avers Best programmée, mais l'état initial de A(devrait) être indiscutable. Linux /dev/randomva garder une approximation de combien d'entropie est disponible et arrêtera de donner des nombres si elle tombe trop bas.
Basic
Par curiosité, pourquoi les lampes à lave sont-elles considérées comme "vraiment aléatoires"? Je crois comprendre que son comportement est plutôt imprévisible, mais une personne ayant une connaissance assez solide de la dynamique des fluides et de la façon dont ces fluides interagissent dans l'environnement gravitationnel de la Terre peut certainement produire des résultats "prévisibles", non? Bien sûr, les lampes à lave sont imprévisibles, mais pour moi, elles ne sont pas du tout aléatoires, mais très prévisibles.
theGreenCabbage
1
@theGreenCabbage: Je soupçonne que les lampes à lave sont chaotiques. Avec un modèle informatique suffisant et des chiffres de précision suffisants, vous pouvez (en principe) prédire le comportement pendant un certain temps. Mais, comme le système est chaotique, deux lampes à lave avec le plus petit changement dans les conditions initiales vont rapidement diverger en comportement. (Et ce commentaire ignore les attracteurs chaotiques.)
dmm
76

Je l'ai essayé en Python: voici le résultat de 60 millions de rouleaux. La variation la plus élevée est de 0,15. N'est-ce pas aussi aléatoire que cela va arriver?

En fait, c'est tellement "bon" que c'est mauvais ... Toutes les réponses existantes se concentrent sur la prévisibilité étant donné une petite séquence de valeurs initiales. Je veux soulever un autre problème:

    votre distribution a un écart-type beaucoup plus petit que les rouleaux aléatoires

Le véritable caractère aléatoire n’est tout simplement pas aussi proche de la moyenne «quasiment exactement 1 sur le nombre de nombres qu’il peut choisir» que vous utilisez comme indication de la qualité.

Si vous regardez cette question de Stack Exchange sur les distributions de probabilité pour plusieurs lancers de dés , vous verrez une formule pour l'écart type de N lancers de dés (en supposant des résultats véritablement aléatoires):

 sqrt(N * 35.0 / 12.0).

En utilisant cette formule, l’ écart type pour:

  • 1 million de rouleaux est 1708
  • 60 millions de rouleaux, c'est 13229

Si on regarde vos résultats:

  • 1 million de rouleaux: stddev (1000066, 999666, 1001523, 999452, 999294, 999999) est égal à 804
  • 60 millions de rouleaux: stddev (9997653, 9997789, 9996853, 10006533, 10002774, 9998398) est égal à 3827

Vous ne pouvez pas vous attendre à ce que l’écart type d’un échantillon fini corresponde exactement à la formule, mais il devrait être très proche. Pourtant, avec un million de lancers, vous avez moins de la moitié de la valeur normale, et par 60 millions, vous avez moins d'un tiers - la situation empire et ce n'est pas un hasard ...

Les pseudo-RNG ont tendance à se déplacer dans une séquence de nombres distincts, en commençant par la graine et en ne revenant pas sur le numéro d'origine pour une période spécifique. Par exemple, les mises en œuvre de l'ancienne rand()fonction de bibliothèque C ont généralement une période de 2 ^ 32, et elles visitent chaque numéro entre 0 et 2 ^ 32-1 exactement une fois avant de répéter la graine. Donc, si vous simulez 2 ^ 32 dés lance le pré-module (%) les résultats incluraient chaque nombre de 0 à 2 ^ 32, les comptes pour chaque résultat de 1 à 6 seraient 715827883 ou 715827882 (2 ^ 32 n’est pas un multiple de 6), et l’écart-type n’est donc que trivialement supérieur à 0. Utiliser Dans la formule ci-dessus, l'écart-type correct pour 2 ^ 32 rouleaux est 111924. Quoi qu'il en soit, à mesure que votre nombre de rouleaux pseudo-aléatoires augmente, vous convergez vers un écart-type égal à 0. On peut s’attendre à ce que le problème soit important lorsque le nombre de rôles est une fraction importante de la période, mais certains pseudo-RNG peuvent présenter des problèmes plus graves que d’autres, voire des problèmes, même avec un nombre inférieur d’échantillons.

Ainsi, même si vous ne vous souciez pas des vulnérabilités cryptographiques, dans certaines applications, vous pouvez vous préoccuper des distributions qui n'ont pas trop, artificiellement, même des résultats. Certains types de simulation tentent tout particulièrement de déterminer les conséquences des résultats inégaux qui se produisent naturellement avec de grands échantillons de résultats aléatoires individuels, mais ils sont sous-représentés dans certains résultats de pRNG. Si vous essayez de simuler la réaction d'une énorme population à un événement, ce problème pourrait modifier radicalement vos résultats et aboutir à des conclusions extrêmement erronées.


Pour donner un exemple concret, disons qu'un mathématicien dit à un programmeur de machine à poker qu'après 60 millions de rouleaux simulés - utilisés pour scintiller des centaines de petites "lumières" autour de l'écran, s'il y a eu 10 013 229 ou plus, ce que le mathématicien s'attend à être 1 stddev loin de la moyenne, il devrait y avoir un petit paiement. Selon la règle 68–95–99.7 (Wikipedia), cela devrait se produire environ 16% du temps (environ 68% se situent dans un écart-type / seule la moitié en dehors est au-dessus). Avec votre générateur de nombres aléatoires, cela représente environ 3,5 écarts types au-dessus de la moyenne: moins de 0,025% de probabilité - pratiquement aucun client ne bénéficie de cet avantage. Voir le tableau Déviations supérieures sur la page que nous venons de mentionner, en particulier:

| Range    | In range   | Outside range | Approx. freq. for daily event  |
| µ ± 1σ   | 0.68268... | 1 in 3        | Twice a week                   |
| µ ± 3.5σ | 0.99953... | 1 in 2149     | Every six years                |
Tony D
la source
Vous comparez des pommes et des oranges ici. Les deux écarts-types n’ont absolument rien à voir.
Jbeuh
50

Je viens d'écrire ce générateur de nombres aléatoires pour générer des jets de dés

def get_generator():
  next = 1
  def generator():
    next += 1
    if next > 6:
      next = 1
    return next
  return generator

Vous l'utilisez comme ça

>> generator = get_generator()
>> generator()
1
>> generator()
2
>> generator()
3
>> generator()
4
>> generator()
5
>> generator()
6
>> generator()
1

etc etc. Seriez-vous heureux d'utiliser ce générateur pour un programme qui exécute un jeu de dés? N'oubliez pas que sa distribution correspond exactement à ce que vous attendez d'un générateur "vraiment aléatoire"!

Les générateurs de nombres pseudo-aléatoires font essentiellement la même chose: ils génèrent des nombres prévisibles avec la distribution correcte. Ils sont mauvais pour la même raison que le générateur de nombres aléatoires simpliste ci-dessus est mauvais - ils ne conviennent pas aux situations dans lesquelles vous avez besoin d'une réelle imprévisibilité, pas seulement de la distribution correcte.

Chris Taylor
la source
2
"Les générateurs de nombres pseudo-aléatoires ... génèrent des nombres prévisibles avec la distribution correcte" - Ce n'est pas parce que c'est un PRNG que sa distribution est parfaite (en fait, les distributeurs commerciaux ne le sont généralement pas, car raisons exposées dans ces réponses). Bien qu’elles puissent être prévisibles avec suffisamment d’informations (algo utilisé, graine de départ, valeurs de sortie, w / e), elles présentent toujours une variance.
Brian S
3
En plus du point, je sais, mais get_generator = lambda: itertools.cycle(range(1,7)), generator = get_generator(), next(generator) # and so onest tout simplement trop élégante sans parler :)
Janus Troelsen
2
@BrianS En réalité, un PRNG dont les tests de distribution ont échoué au fil du temps serait prévisible par définition. Donc, sur certains gros N, si vous obtenez même un peu de distance de N / 2 têtes dans des lancers N pièces, vous pouvez commencer à parier sur les têtes et vous pouvez gagner plus que vous ne perdez. De même, si vous obtenez une répartition parfaite des têtes contre les queues, mais que les têtes viennent toujours par paires, vous aurez à nouveau une recette pour gagner. Les tests de distribution vous permettent de savoir si un PRNG est bon.
Jon Kiparsky
1
Vous avez oublié nonlocal next:-).
Kos
5
Encore meilleur exemple: Pi est considéré comme normal , ce qui signifie que toute séquence de chiffres de n'importe quelle longueur dans une base quelconque n'apparaît pas plus souvent que toute autre séquence de cette longueur dans cette base. Un algorithme qui, lorsqu'on lui demande n bits aléatoires, prend les n bits suivants de pi et les renvoie (le "germe" est le bit sur lequel vous démarrez), devrait à terme produire une distribution parfaitement égale. Mais vous n'en voudriez toujours pas pour votre générateur - quelqu'un qui connaît le dernier groupe de bits que vous avez généré pourrait trouver la première fois que cette séquence se produit, suppose que votre graine est là et probablement correcte.
cpast
26

La génération de nombres aléatoires que votre ordinateur peut effectuer convient à la plupart des besoins, et il est peu probable que vous rencontriez un moment où vous avez besoin d'un nombre réellement aléatoire.

La véritable génération de nombres aléatoires a cependant ses objectifs. En sécurité informatique, jeu, échantillonnage statistique volumineux, etc.

Si vous êtes intéressé par les applications de nombres aléatoires, consultez l'article de Wikipedia .

Alex McKenzie
la source
12
Le gros problème est lorsque vous avez besoin de nombres aléatoires qu'un attaquant ne peut pas prédire pour des raisons de sécurité.
David Schwartz
16
Vous êtes certain de pouvoir rencontrer un moment où vous avez besoin d'un nombre vraiment aléatoire. Il suffit d'ouvrir une page Web qui commence par https://...
Jan Hudec
3
@JanHudec: Dans l'utilisation quotidienne, vous aurez besoin de nombres aléatoires sécurisés au moment de l'ouverture de tout programme, bien avant de taper dans une barre d'adresse: voir la randomisation du format d'espace d'adressage . C'est pourquoi des choses comme celle-là se produisent.
Reid
5
@ JanHudec Je parlais plus précisément du fait que vous auriez besoin d'un générateur de nombres aléatoires en ligne. Les vrais nombres aléatoires sont fréquemment utilisés, mais très peu de gens ont besoin de les générer eux-mêmes.
Alex McKenzie
2
Les machines à sous utilisent également un PRNG, pas un TRNG. Le générateur fonctionne tout le temps et un nombre est choisi exactement au moment où le bouton de rotation est enfoncé. La somme du temps passé sur le bouton PRNG et du bouton vraiment aléatoire correspond à un TRNG.
Roger Dahl
26

Les nombres aléatoires générés par des fonctions typiques dans la plupart des langages de programmation ne sont pas purement des nombres aléatoires. Ce sont des nombres pseudo aléatoires. Puisqu'ils ne sont pas des nombres purement aléatoires, ils peuvent être devinés avec suffisamment d'informations sur les nombres précédemment générés. Ce sera donc un désastre pour la sécurité en cryptographie .

Par exemple, la fonction de générateur de nombre aléatoire suivante utilisée dans glibcne génère pas un nombre purement aléatoire. Le nombre pseudo aléatoire généré par ceci peut être deviné. C'est une gaffe pour les problèmes de sécurité. Il y a une histoire de cela en train de devenir désastreux. Cela ne devrait pas être utilisé en cryptographie.

glibc random():
    r[i] ← ( r[i-3] + r[i-31] )  % (2^32)
    output  r[i] >> 1

Ce type de générateur de nombres pseudo-aléatoires ne devrait jamais être utilisé dans des endroits sensibles à la sécurité, même s'il est statistiquement significatif.

L’une des attaques les plus connues sur les clés pseudo aléatoires est l’attaque sur le WEP 802.11b . Le WEP a une clé à long terme de 104 bits, concaténée avec un IV (compteur) de 24 bits pour créer une clé de 128 bits, qui est à son tour appliquée à l' algorithme RC4 pour générer une clé pseudo aléatoire.

( RC4( IV + Key ) ) XOR (message)

Les clés étaient étroitement liées les unes aux autres. Ici, seule la IV augmentée de 1 à chaque étape et toutes les autres sont restées les mêmes. Comme ce n'était pas purement aléatoire, c'était désastreux et facile à décomposer. La clé pourrait être récupérée en analysant environ 40000 images, soit quelques minutes. Si le WEP utilisait une IV purement aléatoire à 24 bits, il pourrait être sécurisé jusqu'à environ 2 ^ 24 (près de 16,8 millions) de trames.

Il faut donc utiliser le générateur de nombres aléatoires purs dans les questions sensibles de sécurité, lorsque cela est possible.

Prabhu
la source
3
Je blâmerais le truc WEP sur un protocole mal conçu utilisant un chiffre faible. Avec les chiffrements de flux modernes, vous pouvez utiliser un compteur comme IV.
CodesInChaos
2
Le principal problème du WEP était la répétition de la clé en 2 ^ 24 (près de 16 millions) d'images. C'était encore pire avec les clés associées, ce qui permettait de déchiffrer le code dans environ 40000 images. Le point principal ici est que la clé n'est pas aléatoire. C'est étroitement lié, alors c'est aussi facile à craquer.
Prabhu
1
Le pseudo-aléatoire est mauvais en cryptographie uniquement lors de la génération de clés cryptographiques . C'est parfaitement bien au-delà de ça. En effet, RC4 n’est guère plus qu’un générateur de nombres pseudo-aléatoires doté de l’extension à 128 bits de la clé XORed sur le texte en clair du message.
Matt
12

La différence est que les nombres générés pseudo-aléatoires sont prévisibles (se répètent) après un certain temps où les vrais nombres aléatoires ne le sont pas. La longueur nécessaire pour répéter dépend de la longueur de la graine utilisée pour sa génération.

Voici une jolie vidéo sur ce sujet: http://www.youtube.com/watch?v=itaMNuWLzJo

Fatal705
la source
Prévisibilité! = Répéter. Mersenne Twister en est un bon exemple. Sur la plupart des implémentations après 624 Int32, vous pouvez prédire tous les nombres suivants, mais la séquence de Mersenne Twister est beaucoup plus longue que cela (2 ^ 19937 - 1).
HoLyVieR
Je ne comprends pas pourquoi cette réponse ne soit pas poussée à la traîne, car cela me semble être la réponse précise et concise à la question, au moins partiellement. Des nombres pseudo aléatoires peuvent être facilement prédits après certains tirages, le nombre de tirages variant avec l'algorithme pseudo aléatoire "qualité". La sélection d’un "bon" algorithme s’appuie sur les aspects suivants: 1. chaque valeur est dessinée de manière égale (fréquence) (distribution), 2. il faut un "temps long" pour relancer la séquence au début et recommencer à tracer les mêmes numéros dans le même ordre.
minutes
"les vrais nombres aléatoires ne sont pas [prévisibles]". Pour aujourd'hui c'est vrai. Maintenant, si nous croyons en la théorie du Big Bang et que nous avons beaucoup de pouvoir pour calculer l’état de l’Univers à tout moment après le BB, en nous basant sur la physique, nous pouvons prédire l’avenir, y compris le fait que J'écris ce commentaire très exact. Droite?
min
Cela est hypothétiquement vrai, cependant, compte tenu du vaste degré d'entropie impliqué dans les actions réelles de corps réels, la puissance de calcul requise serait ridiculement énorme. Pensez aux continents couverts en ordinateurs. De plus, en raison de la dépendance vis-à-vis de l'état antérieur, il faudrait enregistrer l'état de chaque corps de l'univers à tout moment, ce qui, par définition, nécessiterait plus d'espace que celui disponible dans l'univers, complètement rempli d'appareils de mémoire
TheEnvironmentalist
@TheEnvironmentalist - Ah! "Les continents couverts par les ordinateurs" ... n'est-ce pas ce que "Guide de l'auto-stoppeur de la galaxie"? ;-)
ysap
10

Supposons qu'un nombre pseudo aléatoire puisse être deviné par quiconque avant qu'il ne soit généré.

Pour les applications triviales, un pseudo-hasard convient, car avec votre exemple, vous obtiendrez approximativement le pourcentage correct (environ 1/6 du total des résultats) avec une légère variation (que vous verriez si vous lancez un dé 600k fois);

Cependant, lorsqu'il s'agit de choses comme la sécurité informatique; Le véritable caractère aléatoire est requis.

Par exemple, l'algorithme RSA commence lorsque l'ordinateur choisit deux nombres aléatoires (P et Q), puis effectue plusieurs étapes pour générer ces nombres spéciaux, appelés clés publique et clé privée. (L'important dans une clé privée est qu'il est privé, et personne d'autre ne le sait!)

Si un attaquant peut savoir quels sont les deux nombres «aléatoires» choisis par votre ordinateur, il peut suivre la même procédure pour calculer votre clé privée (celle que personne d'autre n'est censée connaître!)

Avec votre clé privée, un attaquant peut: a) Parler à votre banque en se faisant passer pour vous, b) Écouter votre trafic Internet "sécurisé" et pouvoir le décoder, c) Se faire passer pour quelqu'un d'autre sur Internet.

C'est là que le véritable caractère aléatoire (c'est-à-dire ne pas pouvoir être deviné / calculé) est requis.

DoubleFission
la source
10

Le premier nombre aléatoire que j'ai jamais utilisé possédait l'excellente propriété que de deux nombres aléatoires consécutifs, le second était plus grand avec une probabilité de 0,6. Pas 0.5. Et le troisième était plus grand que le second avec une probabilité de 0,6, et ainsi de suite. Vous pouvez imaginer à quel point cela simule une simulation.

Certaines personnes ne me croiraient pas que c'était même possible avec les nombres aléatoires distribués de manière égale, mais c'est évidemment possible si vous regardez la séquence (1, 3, 5, 2, 4, 1, 3, 5, 2, 4, ...) où le deuxième des deux nombres est plus grand avec une probabilité de 0,6.

D'autre part, pour les simulations, il peut être important de pouvoir reproduire des nombres aléatoires. Supposons que vous effectuez une simulation de trafic et que vous souhaitiez savoir comment certaines actions que vous pourriez entreprendre pourraient améliorer le trafic. Dans ce cas, vous voulez pouvoir recréer exactement les mêmes données de trafic (comme des personnes essayant d'entrer dans une ville) avec différentes actions pour améliorer le trafic.

gnasher729
la source
8

La réponse courte est que les gens ont généralement besoin du "vrai hasard" pour une mauvaise raison, à savoir qu'ils ne comprennent pas la cryptographie.

Les primitives cryptographiques telles que les chiffrements de flux et les CSPRNG sont utilisées pour produire d’énormes flux de bits imprévisibles une fois qu’ils ont été alimentés par quelques bits imprévisibles.

Le lecteur attentif aura maintenant compris qu'il existe un problème d'amorçage: nous devons rassembler quelques bits d'entropie pour tout lancer. Ensuite, ils peuvent alimenter un CSPRNG qui, à son tour, fournira avec bonheur tous les bits imprévisibles dont nous avons besoin. Ainsi, un RNG matériel est requis pour initialiser un CSPRNG . C'est le seul cas où l'entropie est requise en vérité.

(Je pense que cela aurait dû être posté dans Sécurité ou Cryptographie.)

Éditer: Au final, il faut sélectionner un générateur de nombres aléatoires assez bon pour la tâche envisagée et, en ce qui concerne la génération de nombres aléatoires, le matériel ne signifie pas nécessairement bon. Tout comme les mauvais PRNG, les sources aléatoires matérielles ont généralement des biais.

Edit: Certaines personnes ici supposent un modèle de menace dans lequel un attaquant pourrait lire l’état interne d’un CSPRNG et à partir de là, conclure que les CSPRNG ne constituent pas une solution sûre. Ceci est un exemple de mauvaise modélisation de thread. Si un attaquant possède votre système, le jeu est terminé, simplement. Que vous utilisiez un TRNG ou un CSPRNG à ce stade ne fait aucune différence.

Edit: Donc, pour résumer tout cela… Entropie est nécessaire pour générer un CSPRNG. Une fois que cela est fait, un CSPRNG fournira tous les bits imprévisibles dont nous avons besoin pour les applications de sécurité beaucoup plus rapidement que nous ne pouvons (généralement) collecter l'entropie. Si l'imprévisibilité n'est pas nécessaire, par exemple pour la simulation, un Twister Mersenne fournira des nombres avec de bonnes propriétés statistiques à un taux beaucoup plus élevé.

Edit: Toute personne désireuse de comprendre le problème de la génération sécurisée de nombres aléatoires devrait lire ceci: http://www.cigital.com/whitepapers/dl/The_Importance_of_Reliable_Randomness.pdf

Erwan Legrand
la source
2
Ce n'est pas nécessairement une question de sécurité. Je pense qu'il y a des raisons d'utiliser des nombres vraiment aléatoires sans sécurité. Si je faisais des recherches scientifiques qui dépendent de nombres aléatoires et que, pour une raison quelconque, les chiffres soient aussi aléatoires que possible, je tirerais certainement parti d'un RNG matériel pour que je puisse être assuré que les propriétés observées ne sont pas dues. aux bizarreries de la RNG.
Kef Schecter
3
@KefSchecter Les PRNG dont ils ont entendu parler ont généralement une sortie biaisée et / ou corrélée. Ils ont besoin d'une étape de post-traitement pour en faire une sortie indépendante et uniforme. Il n'y a aucune raison de croire que cette étape de post-traitement est plus fiable qu'un chiffrement de flux moderne. Je ferais certainement davantage confiance au code de flux. En prime, il est reproductible, ce qui est précieux en science.
CodesInChaos
OK très bien. Mais ne serait-ce pas la même chose pour les applications de cryptographie? Même la réponse fournie ici indique qu'il vous faut un générateur de ressources matérielles pour amorcer le CSPRNG.
Kef Schecter
2
@KefSchecter Oui, les applications cryptographiques ont besoin de vrais nombres aléatoires pour générer le CSPRNG. Mais pour tout le reste, nous pouvons utiliser ce CSPRNG.
CodesInChaos
@KefSchecter: Les applications cryptographiques exigent que le flux ne soit pas reproductible par le monde entier. En revanche, dans les applications scientifiques, il est utile de pouvoir montrer que les nombres "aléatoires" utilisés ne sont pas simplement choisis pour afficher une analyse sous un bon angle. Par exemple, si on annonce après avoir annoncé ses méthodes que l'on générera des données d'une certaine manière en utilisant les numéros de loterie de l'état le lendemain, les lecteurs peuvent être quelque peu confiants qu'ils n'ont pas faussé leurs résultats, même si le tirage du jour de la semaine n'en compte qu'une douzaine. des bits d'entropie.
Supercat
7

Tous les PRNG ne conviennent pas à toutes les utilisations. Par exemple, Java.util.SecureRandom utilise le hachage SHA1, dont la taille de sortie est de 160 bits. Cela signifie que 2 160 flux possibles de nombres aléatoires peuvent en découler. Aussi simple que cela. Vous ne pouvez pas obtenir plus de 2 160 valeurs de l'état interne. Ainsi, vous ne pouvez pas obtenir plus de 2 160 flux uniques de nombres aléatoires à partir d’une seule graine, quelle que soit l’origine de votre graine. Windows CryptGenRandom est censé utiliser un état de 40 octets, il a 2 320 flux possibles de nombres aléatoires.

Le nombre de façons de mélanger un paquet standard de 52 cartes est de 52 !, ce qui correspond à environ 2 226 . Ainsi, quel que soit l'ensemencement, vous ne pouvez pas utiliser Java.util.SecureRandom pour mélanger un jeu de cartes. Il y a environ 2 66 mélanges possibles qu'il ne peut pas produire. Bien sûr, nous ne savons pas lesquels ils sont ...

Donc, si j’avais une source de 256 bits de véritable caractère aléatoire (par exemple, d’une carte Quantis RNG), je pourrais ensemencer un PRNG comme CryptGenRandom () avec cette graine, puis utiliser le PRNG pour mélanger un paquet de cartes. Si je réensemence avec un véritable hasard à chaque lecture aléatoire, tout ira bien: imprévisible et statistique. Si je faisais la même chose avec Java.util.SecureRandom, il y aurait des remaniements qui ne pourraient probablement pas être produits car il ne peut pas être semé avec 256 bits d'entropie et son état interne ne peut pas représenter tous les remaniements possibles.

Notez que les résultats de java.util.SecureRandom seraient à la fois imprévisibles et statistiquement aléatoires. Aucun test statistique ne permettrait jamais d'identifier un problème! Mais la sortie du RNG n’est pas assez grande pour couvrir l’ensemble des sorties possibles pour simuler un jeu de cartes.

Et rappelez-vous, si vous ajoutez les jokers, c'est 54! que vous devez couvrir, ce qui nécessite environ 2 238 possibilités.

Paco Hope
la source
2
Pourquoi vous souciez-vous que certains remaniements ne puissent pas arriver? Cette restriction n'a aucun effet observable.
CodesInChaos
2
Je suis en quelque sorte gobsmacked à la question. Pour les sociétés de jeu fortement réglementées, un tel biais prouverait mathématiquement que vos chances de gagner au jeu de cartes sont différentes avec l'ordinateur et avec un jeu de cartes en papier. Peu importe que les chances soient meilleures ou pires. Ils sont différents. L'ordinateur n'est pas moralement équivalent à un vrai jeu de cartes. De plus, nous ne pouvons pas caractériser la différence. La société de jeux faisant face à de lourdes amendes réglementaires s’inquiéterait beaucoup.
Paco Hope
1
Mais c'est détectable. Je le détecte en utilisant un processus connu: la révision du code source et la connaissance du domaine problématique. C'est ce qui est remarquable. Je ne peux PAS utiliser l'analyse statistique automatisée. Il est aussi détectable que quelqu'un utilisant java.util.Random ou le Twister Mersenne. L'analyse statistique n'est pas le seul mécanisme de détection valide de la non-concordance RNG / domaine problématique. Les échecs qui passent ce détecteur ne sont pas, par définition, des succès.
Paco Hope
1
Je n'ai jamais été en désaccord avec cette déclaration. Ce que j’ai dit, c’est que l’analyse statistique n’est pas une preuve infaillible que le RNG / PRNG est correct. Ceci est un exemple de faux négatif. Il devrait être incorrect, mais le test de sortie statistique le passera. Si j'utilise SHA1 (1), SHA1 (2), SHA1 (3) ... SHA1 (n) comme "RNG", il passera également des tests statistiques. C'est aussi faux. La définition de correct s'étend au-delà de la définition de "passe les tests statistiques". Passer des tests statistiques est nécessaire, mais pas suffisant.
Paco Hope
4
@CodesInChaos: L'argument "nous ne connaissons pas d'attaque qui puisse tirer parti du fait que la grande majorité des possibles-remaniements IRL ne seront jamais produits" n'implique pas qu'une telle attaque est impossible, 'sais pas ce que c'est ou comment se défendre. La bonne attitude dans ce cas est d'éliminer la possibilité d'attaque en éliminant la condition: créer un RNG de qualité suffisante pour qu'il puisse réellement générer tous les decks possibles.
Eric Lippert
6

Les nombres pseudo-aléatoires sont générés à l'aide d'une fonction mathématique et d'une valeur initiale (appelée graine ), alors que les nombres aléatoires ne le sont pas. Leur prévisibilité les rend incroyablement utiles pour les répétitions de jeu, car il vous suffit de sauvegarder la graine et l'entrée du joueur - l'IA répondra exactement de la même manière "aléatoire" à chaque fois.

BonzaiThePenguin
la source
6

La différence entre "vrai" nombre aléatoire et "pseudo" nombre aléatoire est la prévisibilité. Cette réponse a déjà été fournie.

Cependant, la prévisibilité n'est pas nécessairement une mauvaise chose, comme le montrent la plupart des exemples. Voici un exemple pratique d’un des rares cas où la prévisibilité est bonne: le système de positionnement global.

Chaque satellite utilise un code PRN distinct (les codes Gold ) adapté à la corrélation automatique ou à la corrélation croisée nécessaire pour la mesure du temps de propagation du signal. Pour ces codes de Gold, la corrélation entre eux est particulièrement faible, ce qui permet une identification sans équivoque du satellite, mais permet le calcul de distance par la corrélation entre la séquence émise et le récepteur.

radouxju
la source
2

Pour un contrôle rapide de l’aléatoire, vous prenez des points avec des coordonnées aléatoires dans [0; 1), puis vous les placez dans un cube de dimension k. Ensuite, vous effectuez la procédure pour découper ce cube en sous-cubes - chaque volume de sous-cube (ou sous-sphère) doit être mesuré correctement par cette procédure avec des fluctuations selon le théorème bien connu.

La qualité du hasard est importante lorsque vous vous rencontrez ...

  1. des fins de sécurité. Lorsque vous générez un nombre à utiliser comme paramètre pour la génération de votre clé, et que c'est bien prévisible, l'ennemi le détectera avec une probabilité de 100% et réduira le champ de recherche de manière beaucoup plus réduite.

  2. à des fins scientifiques. En science, il faut non seulement avoir la moyenne moyenne en bon état, mais également éliminer les corrélations entre différents nombres aléatoires. Donc, si vous prenez (a_i - a) (a_ {i + 1} -a) et trouvez sa distribution, elle doit correspondre à des statistiques.

La corrélation de paires est appelée "aléatoire faible". Si vous voulez un caractère aléatoire réel, vous devez avoir une corrélation d’ordre élevé avec plus de 2 variances.

Aujourd'hui, seuls les générateurs de la mécanique quantique offrent un véritable caractère aléatoire.

Sanaris
la source
1

Pourquoi le vrai hasard est-il important?

Il existe essentiellement deux raisons pour lesquelles le véritable caractère aléatoire est nécessaire:

  1. Si vous utilisez le RNG pour la cryptographie (y compris des choses comme le jeu en argent réel et une loterie), alors un PRNG vous rendra le chiffrement beaucoup plus faible que son analyse mathématique (qui suppose un TRNG) vous ferait croire. Le PRNG ne sera pas réellement aléatoire, mais aura un motif - les adversaires peuvent exploiter ce motif pour déchiffrer un chiffre qui aurait dû être insaisissable.
  2. Si vous utilisez le RNG pour simuler des entrées "aléatoires", par exemple pour un test de bogue ou une simulation, un PRNG affaiblit votre approche. Lorsque vous ne découvrirez aucun bug, il y aura toujours ce doute lancinant: existe-t-il un bug qui ne se remarque pas avec le modèle de mon PRNG, mais qui serait apparu si je n'avais utilisé qu'un TRNG? Les résultats de ma simulation décrivent-ils avec exactitude la réalité ou le phénomène que j'ai découvert est-il simplement un artefact du modèle du PRNG?

En dehors de ces zones, cela n'a pas vraiment d'importance. Mise en garde: Si votre PRNG est vraiment très mauvais, il se peut qu'il ne soit toujours pas adapté - vous ne voulez pas faire un jeu de Craps où les dés reviennent toujours même, vos joueurs ne l'aimeraient pas.

Comment le PRNG de Python n'est-il pas assez bon?

Il est très peu probable que vous soyez capable de détecter les pièges d'un vrai PRNG en utilisant une méthodologie aussi simple. L'analyse statistique des RNG est un domaine scientifique à part entière, et des tests très sophistiqués sont disponibles pour évaluer le "caractère aléatoire" d'un algorithme. Celles-ci sont beaucoup plus avancées que votre simple tentative.

Tous les développeurs de logiciels qui créent des bibliothèques du monde réel, tels que les développeurs Python, utilisent ces tests statistiques pour déterminer si leur implémentation PRNG est suffisante. Par conséquent, il est très peu probable que vous soyez en mesure de détecter facilement un modèle dans un PRNG du monde réel, à l'exception des cas de supervision réelle de la part du développeur. Cela ne signifie pas qu'il n'y a pas de modèle - un PRNG a un modèle par définition.

Superbest
la source
0

Fondamentalement, vous ne pouvez pas prouver qu'une source est aléatoire par une analyse mathématique de la sortie, vous avez par exemple besoin d'un modèle physique qui dit que la source est aléatoire (comme dans le cas de la désintégration radioactive).

Vous pouvez simplement exécuter des tests par lots pour trouver une corrélation statistique dans les données de sortie. Dans ce cas, il est prouvé que les données ne sont pas aléatoires (mais une source aléatoire peut également générer des sorties non aléatoires. Sinon, elle ne sera pas vraiment aléatoire si elle ne peut pas donner de données spécifiques. sortie). Sinon, si les tests sont réussis, vous pouvez dire que les données sont pseudo aléatoires.

Passer quelques tests aléatoires signifie seulement que vous avez un bon PRNG (générateur de nombres pseudo aléatoires), ce qui peut être utile pour les applications où la sécurité n’est pas impliquée.

Si la sécurité est en jeu (chiffrement, génération d'une clé, génération de nombres aléatoires pour le jeu, etc.), il ne suffit pas d'avoir un bon PRNG, il doit avoir des qualités supplémentaires, comme la sortie de la fonction ne pouvant pas être facilement déduite des sorties précédentes, la fonction doit avoir un coût de calcul souhaitable (suffisamment limité pour être utilisable, mais suffisamment élevée pour empêcher les tentatives de forçage brutal), le matériel qui exécute la fonction - ou le périphérique, dans le cas étrange où il s’agit d’un périphérique analogique - ne devrait pas être facilement altéré, etc.

Avoir un bon PRNG peut être utile dans les jeux pour créer de nouveaux modèles imprévisibles, et dans le cryptage - trop lourd à expliquer dans un seul post, il suffit de penser à un rôle de pouce quelle sortie de la procédure de cryptage doit être pseudo-aléatoire, ne montrant pas de modèles qui pourraient associer des données cryptées précédentes aux données cryptées suivantes, ou associer des données en texte brut à des données cryptées, ou associer deux cryptographes différents l'un à l'autre (pour que des suppositions puissent être faites sur les textes bruts) ....

Dice9
la source
-5

Histoire courte:

Génère une graine aléatoire en utilisant la microseconde actuelle du système.

Cette astuce est assez ancienne et est toujours fonctionnelle.

En excluant le facteur brut de force, où je peux déterminer chaque combinaison en "pariant" sur tous les nombres possibles et ce n’est pas le but de cette question, en particulier lorsque la plupart des nombres aléatoires sont arrondis avant son utilisation.

Disons un exemple, je peux déterminer la graine utilisée en utilisant seulement 10 valeurs. Donc, connaissant la graine, je peux deviner la valeur suivante.

Si je voudrais utiliser la graine = 1 alors je pourrais obtenir la séquence suivante:

1, 2, 3, 4, 5, 6, 7, 8, 9 ... (et j'en déduis que la graine utilisait id 1 et la valeur suivante 10)

Mais que se passera-t-il si, si on change l’envoi toutes les "nièmes" valeurs ?. Changer le germe par les microsecondes actuelles est une astuce peu coûteuse (c’est-à-dire qu’elle ne nécessite pas beaucoup de cycles de processeur).

La séquence est donc la suivante: (graine = 1) 1, 2, 3, 4, 5 ((graine = 2), 7, 9, 11, 13 ... (15?)

Dans ce cas:

a) Je ne peux pas déduire quelle graine a été utilisée.

b) Ergo, je ne peux pas deviner la valeur suivante.

c) La seule hypothèse que je puisse faire est de déduire que la prochaine graine pourrait être un nombre majeur.

Quoi qu'il en soit, la plupart des algorithmes générateurs d'aléas modernes utilisent déjà cette astuce sous le capot.

Le fait est que nous n’avons pas besoin d’un ordinateur quantique pour créer un «vrai» nombre aléatoire, l’imprécision de notre cristal de quartz de notre ordinateur fait office de générateur aléatoire, de même que l’efficacité aléatoire de notre processeur varie également sans tenir compte que le processeur effectue généralement plusieurs tâches à la fois.

magallanes
la source
2
C'est une idée plutôt mauvaise et une source de vulnérabilité pour des choses qui nécessitent une séquence réellement imprévisible. Si vous prenez des microsecondes, vous n’avez que 10 ^ 6 possibilités de semences, ce qui est plutôt faible.
HoLyVieR
@HoLyVieR: c'est certainement une mauvaise idée si vous vous souciez de la sécurité, mais pas aussi mal que vous le dites: vous utiliseriez normalement des microsecondes depuis le démarrage du système (ou une époque unix ...), ce qui augmente considérablement la plage de valeurs possibles.
Mikera
1
@mikera Ce n'est pas mieux, l'heure à laquelle la demande a été traitée est prévisible. C'est un vecteur de vulnérabilité pour un bon nombre de fonctionnalités de réinitialisation de mot de passe. Ces scripts ont généré un jeton "aléatoire" avec votre technique et l'attaquant pourrait trouver le jeton généré car trouver l'heure à laquelle il a été exécuté est plutôt trivial ... c'est le même moment où la demande de réinitialisation du mot de passe a été envoyée + - 150ms.
HoLyVieR
Bien sûr, cette situation est très mauvaise. Mais la situation dans laquelle l’état a été créé au démarrage du système et où l’attaquant ne dispose pas d’un moyen efficace de deviner le moment du démarrage n’est pas aussi grave. Vous pouvez facilement choisir entre 10 ^ 12 microsecondes possibles, ce qui peut rendre certains types d’attaque irréalisables. Pour être clair: toutes ces solutions sont assez mauvaises du point de vue de la cryptographie, mais les constantes comptent .
Mikera
Pour les serveurs en ligne, les informations sur la disponibilité du système sont parfois proposées publiquement. Ou vous pouvez l'obtenir à partir d'une page d'état "Incidents. Serveur à nouveau". Vous pouvez aussi faire un ping, attendre un grand temps d'arrêt et noter qu'il pourrait s'agir d'un redémarrage de la machine (ce qui donnerait des centaines de millions de temps à vérifier, ce qui est plutôt faible).
Dereckson