Question:
Pourquoi Math.random () n'est-il pas conçu pour être sécurisé cryptographiquement?
forest
2018-03-15 11:11:06 UTC
view on stackexchange narkive permalink

La fonction JavaScript Math.random () est conçue pour renvoyer une seule valeur à virgule flottante IEEE n telle que 0 ≤ n < 1. Il est (ou du moins devrait être) largement connu que la sortie n'est pas sécurisée par cryptographie. La plupart des implémentations modernes utilisent l'algorithme XorShift128 + qui peut être facilement cassé. Comme il n'est pas du tout rare que des gens l'utilisent par erreur alors qu'ils ont besoin d'un meilleur caractère aléatoire, pourquoi les navigateurs ne le remplacent-ils pas par un CSPRNG? Je sais que Opera fait cela *, au moins. Le seul raisonnement auquel je pourrais penser serait que XorShift128 + est plus rapide qu'un CSPRNG, mais sur les ordinateurs modernes (et même pas si modernes), il serait trivial de produire des centaines de mégaoctets par seconde en utilisant ChaCha8 ou AES-CTR. Celles-ci sont souvent suffisamment rapides pour qu'une implémentation bien optimisée puisse être goulotée uniquement par la vitesse de la mémoire du système. Même une implémentation non optimisée de ChaCha20 est extrêmement rapide sur toutes les architectures, et ChaCha8 est plus de deux fois plus rapide.

Je comprends qu'il ne pourrait pas être redéfini comme CSPRNG car la norme ne donne explicitement aucune garantie de aptitude à l'utilisation cryptographique, mais il ne semble y avoir aucun inconvénient à ce que les fournisseurs de navigateurs le fassent volontairement. Cela réduirait l’impact des bogues dans un grand nombre d’applications Web sans enfreindre la norme (il ne faudrait que la sortie soit des nombres arrondis au plus proche pair IEEE 754), diminuer les performances ou interrompre la compatibilité avec des applications Web.


EDIT: Quelques personnes ont souligné que cela pourrait potentiellement amener les gens à abuser de cette fonction même si la norme dit que vous ne pouvez pas compter dessus pour la sécurité cryptographique. Dans mon esprit, il y a deux facteurs opposés qui déterminent si l'utilisation d'un CSPRNG serait ou non un avantage de sécurité net:

  1. Faux sentiment de sécurité - Le nombre de personnes qui autrement utiliseraient une fonction conçue à cet effet, telle que window.crypto , décidez plutôt d'utiliser Math.random () car il se trouve être cryptographiquement sécurisé sur la plate-forme cible prévue.

  2. Opportuniste security - Le nombre de personnes qui ne connaissent pas mieux et utilisent quand même Math.random () pour des applications sensibles qui seraient protégées de leur propre erreur. Évidemment, il serait préférable de les éduquer à la place, mais ce n'est pas toujours possible.

Il semble raisonnable de supposer que le nombre de personnes qui seraient protégées contre les leurs les erreurs dépasseraient largement le nombre de personnes qui sont bercées par un faux sentiment de sécurité.

* Comme le souligne CodesInChaos, ce n'est plus vrai maintenant qu'Opera est basé sur Chromium. sub>


Plusieurs grands navigateurs ont eu des rapports de bogues suggérant de remplacer cette fonction par une alternative cryptographiquement sécurisée, mais aucun des changements sécurisés suggérés n'a abouti:

Les arguments pour le changement correspond essentiellement au mien. Les arguments contre cela varient d'une performance réduite sur les microbenchmarks (avec peu d'impact dans le monde réel) à des malentendus et des mythes, tels que l'idée erronée qu'un CSPRNG s'affaiblit avec le temps à mesure que le hasard est généré. En fin de compte, Chromium a créé un tout nouvel objet crypto et Firefox a remplacé son RNG par l'algorithme XorShift128 +. La fonction Math.random () reste entièrement prévisible.

Les commentaires ne sont pas destinés à une discussion approfondie;cette conversation a été [déplacée vers le chat] (https://chat.stackexchange.com/rooms/74736/discussion-on-question-by-forest-why-is-math-random-not-designed-to-be-cryptog).
Dire qu'une caractéristique a certaines qualités implique une obligation.L'obligation entraîne des frais, d'abord pour mettre en œuvre l'obligation, ensuite pour la tenir à jour et, troisièmement, lorsque vous découvrez que vous n'avez pas respecté votre obligation.Cela est particulièrement vrai lorsque vous avez l'obligation de fournir une fonctionnalité ** sécurisée **.
@MichaelK Mais il y a tellement d'autres exemples où ce n'est pas vrai.Il n'est pas nécessaire de dire qu'une fonctionnalité a certaines qualités n'importe où.Gardez la norme telle qu'elle est et améliorez la sécurité de manière opportuniste.Un bon exemple est n'importe quel compilateur C moderne.Diriez-vous qu'il est insensé que le compilateur prenne en charge `FORTIFY_SOURCE`?Pourquoi ne pas simplement éduquer les gens pour qu'ils ne créent pas de programmes vulnérables?Pourquoi GCC les protège-t-il?Je ne connais personne qui soit bâclé dans son code parce qu'il pense que GCC les protégera, mais je connais de nombreuses personnes qui ont été sauvées par les mesures de sécurité de GCC.
En d'autres termes, vous dites que le _fail-safe design_ est une mauvaise chose.
@forest Sécurité opportune?Des mots que je n'aurais jamais pensé que quiconque dirait.
Performance peut-être?L'obtention d'une valeur aléatoire sécurisée par cryptographie est bien plus lourde en CPU qu'une valeur pseudo aléatoire.Lors de la conception d'un jeu (en C ++), je devais spécifiquement choisir un algorithme aléatoire offrant des performances décentes.
Blink est un moteur de rendu.V8 est l'implémentation JavaScript utilisée par Chrome et Opera.
@Rolf ツ Cette question a été largement discutée dans les réponses et les commentaires.Les performances de XorShift128 + par rapport à, disons ChaCha8, utilisé pour renvoyer des nombres à virgule flottante individuels.
Comparer les performances de XorShift128 + à ChaCha8 n'est qu'une partie de la question des performances.Un CSPRNG doit collecter suffisamment d'entropie avant d'être prêt à émettre des bits aléatoires sécurisés.Cela peut prendre beaucoup de temps.
@JamesKPolk Vous n'avez besoin que de 128 bits, une fois (ChaCha prend 256 bits mais il est parfaitement acceptable de répéter la clé deux fois, tant que vous changez la constante).Au moment où un navigateur se charge, beaucoup d'entropie sera disponible pour le système.Sur les microcontrôleurs qui exécutent un interpréteur JavaScript pour une raison quelconque et n'ont aucune source de bonne entropie, ils pourraient simplement utiliser XorShift128 + (puisque je ne suggère pas de changement des normes).
@forest: assez juste, cela ne devrait en effet pas être un problème sur aucune plate-forme moderne, bureau ou mobile.
Onze réponses:
Eric Lippert
2018-03-15 20:10:44 UTC
view on stackexchange narkive permalink

J'étais l'un des implémenteurs de JScript et membre du comité ECMA du milieu à la fin des années 1990, donc je peux fournir une perspective historique ici.

La fonction JavaScript Math.random () est conçu pour renvoyer une valeur à virgule flottante entre 0 et 1. Il est bien connu (ou du moins devrait l'être) que la sortie n'est pas cryptographiquement sécurisée

Tout d'abord: la conception de nombreux RNG Les API sont horribles . Le fait que la classe .NET Random puisse être utilisée à mauvais escient de plusieurs manières pour produire de longues séquences du même nombre est horrible. Une API où la manière naturelle de l'utiliser est également la mauvaise est une API «gouffre»; nous voulons que nos API soient des puits de succès, où la manière naturelle et la bonne manière sont les mêmes.

Je pense qu'il est juste de dire que si nous savions alors ce que nous savons maintenant, l'API aléatoire JS serait différente. Même des choses simples comme changer le nom en "pseudo-aléatoire" aideraient, car comme vous le notez, dans certains cas, les détails d'implémentation sont importants. Au niveau architectural, il y a de bonnes raisons pour lesquelles vous voulez que random () soit une fabrique qui renvoie un objet représentant une séquence aléatoire ou pseudo-aléatoire, plutôt que de simplement renvoyer des nombres. Etc. Leçons apprises.

Deuxièmement, rappelons-nous quel était l'objectif fondamental de la conception de JS dans les années 1990. Faites danser le singe lorsque vous déplacez la souris . Nous pensions que les scripts d'expressions en ligne étaient normaux, nous pensions que les blocs de script de deux à dix lignes étaient courants, et l'idée que quelqu'un pourrait écrire cent lignes de script sur une page était vraiment très inhabituelle. Je me souviens de la première fois que j'ai vu un programme JS de dix mille lignes et ma première question aux personnes qui me demandaient de l'aide parce que c'était si lent par rapport à leur version C ++ était une version de "êtes-vous fou ?! 10KLOC JS ?! "

L'idée que n'importe qui aurait besoin de l'aléatoire cryptographique dans JS était tout aussi insensée. Vous avez besoin que vos mouvements de singe soient imprévisibles à la force cryptographique? Peu probable.

N'oubliez pas non plus que c'était au milieu des années 1990. Si vous n’êtes pas là, je peux vous dire que c’était un monde très différent d’aujourd’hui en ce qui concerne la cryptographie ... Voir export de cryptographie.

Je n'aurais même pas envisagé d'intégrer le caractère aléatoire de la force de la cryptographie à tout ce qui est livré avec le navigateur sans obtenir une énorme quantité de conseils juridiques de la part de l'équipe MSLegal. Je ne voulais pas toucher la crypto avec un poteau de dix pieds dans un monde où le code d'expédition était considéré comme l'exportation de munitions vers des ennemis de l'État . Cela semble fou du point de vue d'aujourd'hui, mais c'était le monde qui était.

pourquoi les navigateurs ne le remplacent-ils pas par un CSPRNG?

Les auteurs de navigateurs n'ont pas à fournir de raison pour NE PAS faire de changement. Les changements coûtent de l'argent et réduisent l'effort à de meilleurs changements; chaque changement a un coût d'opportunité énorme.

Plutôt, vous devez fournir un argument non seulement pourquoi faire le changement est une bonne idée, mais pourquoi c'est la meilleure utilisation possible de leur temps. Il s'agit d'un petit changement pour le prix.

Je comprends qu'il ne peut pas être redéfini en tant que CSPRNG car la norme ne donne explicitement aucune garantie d'aptitude à l'utilisation cryptographique, mais il ne semble pas y avoir d'inconvénient à le faire de toute façon

L'inconvénient est que les développeurs sont toujours dans une situation où ils ne peuvent pas savoir de manière fiable si leur caractère aléatoire est la force de la cryptographie ou pas, et peut encore plus facilement tomber dans le piège de s'appuyer sur une propriété qui n'est pas garantie par la norme. La modification proposée ne résout pas réellement le problème, qui est un problème de conception.

(Un peu hors sujet) Pourriez-vous fournir une référence pour "la classe .NET Random peut trivialement être mal utilisée de plusieurs façons pour produire de longues séquences du même nombre est horrible"?: Je n'ai jamais entendu parler de cela auparavant, ou êtes-vousse référant au classique "créer un millier d'instances aléatoires dans une boucle serrée"?
@VisualMelon: Créer un millier d'instances dans une boucle serrée est le classique.Mais il existe également des modes d'échec lorsque vous utilisez une instance de Random sur deux threads en même temps.Random n'est pas threadsafe et il y a un scénario où une course peut le faire retourner zéro pour toujours!
@VisualMelon: Il existe également des scénarios plus subtils.Supposons que vous ayez deux instances de Random avec des graines différentes.Ça semble bien, non?Mais supposons que vous combiniez ensuite ces deux instances de Random d'une manière ou d'une autre.Peut-être que vous les utilisez pour produire chacun une séquence de jets de dés et les additionner par paires.** Les deux séquences sont-elles corrélées l'une avec l'autre d'une manière non aléatoire **?Cela semble plausible.Après tout, ils exécutent le même algorithme "en parallèle", juste avec une graine différente.
Merci d'avoir précisé: je suppose que je suis assez méfiant pour ne pas essayer d'utiliser _toute_ source de plusieurs threads à moins qu'elle ne soit clairement documentée à cette fin, donc je ne le remarquerais jamais.Je ne suis pas sûr que le dernier point soit une préoccupation spécifique pour toute «implémentation» plutôt que pour l'algorithme qui la sous-tend: je ne pense pas que nous puissions tenir les concepteurs d'API responsables de cela!
Je pense que c'est la meilleure réponse ici jusqu'à présent, d'autant plus qu'elle provient d'une source aussi fiable.Je marquerai cette réponse comme acceptée pour le moment à moins qu'une meilleure réponse ne se présente.
@EricLippert Je ne comprends pas vos 2 flux avec différentes clés ajoutées par exemple.S'il s'agit d'un CSPRNG, je pense que cela devrait être correct.S'il ne s'agit pas d'un CSPRNG (juste un plan PRNG), vous ne devriez jamais l'utiliser pour la sécurité, même si vous n'avez qu'une seule instance.
@Buge: Il est assez facile d'imaginer un (pas très bon) RNG qui génère des entiers, et où le bit inférieur de la sortie est aléatoire, mais indépendant de la graine.Si vous ajoutez la sortie de deux de ces instances (prédéfinies indépendamment), le résultat sera toujours pair.(Le point d'Eric n'avait rien à voir avec la sécurité - je ne sais pas ce qui vous a fait penser que c'était le cas.)
Oui!Pourquoi * toutes * les API aléatoires sur * toutes * les plates-formes sont-elles si faussées?Je suppose que les équipes vont "laisser le stagiaire faire ça".
@EricLippert Je pense qu'il vaut la peine d'ajouter un exemple concret à cette réponse de `Random` abusable de C #.Quelque chose comme ce (pseudo) code: `while (something) {int rand = new Random (). NextInt ();doSomething (rand);} `- Cela échoue parce que` Random` de C # utilise l'heure actuelle avec la résolution du cours comme graine, donc si `doSomething` est rapide, vous obtiendrez le premier nombre de la séquence avec la graine de ce temps, encore et encoreencore une fois, plutôt que des différents.(Je sais que vous le savez; j'explique pour les personnes qui n'ont pas travaillé sur C # avec Microsoft)
@Buge En fait, parfois mélanger plusieurs mauvais PRNG ensemble peut en fait vous donner un chiffrement décent, du moins si cela est fait correctement.Par exemple, E0 (le chiffrement utilisé par tous les protocoles Bluetooth sauf les plus récents) implique quatre LFSR.Chaque LFSR individuel est facile à casser, mais E0 lui-même est un peu plus fort (mais toujours pas génial).
@MartinBonner Je pensais que le commentaire d'Eric parlait des CSPRNG, parce que c'est security.stackexchange.com et que la question et la réponse d'Eric parlaient de CSPRNG.
@forest J'aurais dû limiter ma déclaration en disant "Si ce n'est pas un CSPRNG (juste un simple PRNG), vous ne devriez jamais l'utiliser pour la sécurité à moins que vous ne soyez un expert en cryptographie."Tout comme un expert en crypto peut créer un nouveau chiffrement à l'aide de primitives non sécurisées telles que l'addition, le xor et la multiplication, un expert en crypto peut également créer un nouveau CSPRNG à l'aide de PRNG.Et tout comme un profane ne devrait jamais créer un nouveau chiffrement en utilisant des primitives non sécurisées, un profane ne devrait jamais utiliser un PRNG pour la sécurité.
Une excellente réponse informative.Le «coût d'opportunité» est probablement la seule véritable explication nécessaire, mais tout le reste est un vrai régal
J'allais fournir une réponse très similaire qui jouait sur les mêmes thèmes mentionnés ici, essentiellement la version courte et insatisfaisante de ce qui est "la spécification ne l'exige pas, donc les implémentations n'ont pas besoin de la rendre cryptographiquement aléatoire"
@Buge Le raisonnement utilisé par Martin s'applique aux CSPRNG.Cela ne vous dérange pas particulièrement, mais la plupart des CSPRNG utilisés par les langages traditionnels sont tout sauf incroyables.
@Voo Si "le bit inférieur de la sortie est aléatoire, mais indépendant de la graine" alors ce n'est pas un CSPRNG.Un CSPRNG [requiert] (https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator) que si vous n'avez aucune connaissance de la graine, alors la sortie du CSPRNG est indiscernable du vrai hasard.Mais ce mauvais PRNG se distingue assez facilement du vrai hasard même sans connaissance de la graine.Vérifiez simplement si le bit inférieur suit le modèle.
@Buge Je pensais à une source partagée d'aléatoire (disons un module matériel).Mais vous avez raison de dire que cela ne fonctionnerait pas si vous aviez deux séquences.
Philipp
2018-03-15 15:22:47 UTC
view on stackexchange narkive permalink

Parce qu'il existe en fait une alternative cryptographiquement sécurisée à Math.random():

window.crypto.getRandomValues ​​(typedArray)

Cela permet au développeur d'utiliser le bon outil pour le travail. Si vous voulez générer de jolies images ou des butins pour votre jeu, utilisez le rapide Math.random () . Lorsque vous avez besoin de numéros aléatoires sécurisés par cryptographie, utilisez la window.crypto , plus coûteuse.

Pourquoi n'utiliseriez-vous pas une fonction aléatoire sécurisée pour les butins?
@xDaizu Parce que chaque butin n'est pas une boîte à butin où quelqu'un va en faire une vraie loterie.
Si votre butin doit être sécurisé par cryptographie, * et * vous utilisez un RNG côté client pour générer le butin (plutôt que de demander au serveur "qu'est-ce que j'ai obtenu?"), Vous faites très probablement quelque chose de mal.
Cela ne répond pas à la question ... la forêt demande pourquoi `Math.Random ()` est implémenté tel quel, pas comment utiliser un CSPRNG en Javascript
Pour être plus explicite, `window.crypto` est largement inutile si vous ne faites pas confiance à l'utilisateur.Dans ce cas précis, ils (ou leur agent utilisateur, ou tout proxy en qui ils ont confiance) peuvent simplement le remplacer par `() => 0.42` avant qu'il ne soit exécuté.Ce sont des utilitaires pour permettre à l'utilisateur d'établir la sécurité, pas à vous.
@xDaizu votre question trouve une réponse dans le message auquel vous avez répondu: c'est une question de "rapide vs [lent et] cher"
@OrangeDog, c'est pourquoi vous devez toujours utiliser le mot-clé `const` avec lui.
@NH.rien de ce que vous écrivez dans le script ne va vous aider, l'utilisateur en a le contrôle total
@OrangeDog, est-ce un CVE?Sinon, pouvez-vous poster vos préoccupations dans un article séparé (nous commençons à nous éloigner du sujet ...)
@OrangeDog C'est vrai, mais c'est vrai parce que la question concerne les scripts côté client.Cela n'a aucun rapport avec le fait que «Math.random» n'est pas sécurisé par cryptographie.
Luc
2018-03-15 16:13:53 UTC
view on stackexchange narkive permalink

JavaScript (JS) a été inventé en 1995.

  1. Potentiellement illégal: la cryptographie était encore sous contrôle strict des exportations en 1995, donc un bon CSPRNG pourrait même ne pas avoir était légal de distribuer dans un navigateur.
  2. Performance: historiquement, les CSPRNG (générateurs de nombres pseudo-aléatoires cryptographiquement sécurisés) sont beaucoup plus lents que les PRNG, alors pourquoi utiliser un CSPRNG par défaut?
  3. Aucun état d'esprit de sécurité: en 1995, SSL venait d'être inventé. Pratiquement aucun serveur ne le supportait encore, Internet se composait de lignes téléphoniques et était utilisé pour les forums publics ( BBS) et MUDs. Le chiffrement était réservé aux agences de renseignement.
  4. Pas besoin: les applications Web n'existaient pas encore, car JavaScript venait juste d'être inventé. Il a été conçu comme un langage interprété (donc lent) pour aider les pages à être plus dynamiques. Il n'aurait traversé l'esprit de personne d'utiliser un CSPRNG lent (et à peine existant) par défaut pour une fonction aléatoire.
  5. Si peu besoin, en fait, qu'il n'y avait pas d'alternative: JavaScript n'avait même pas d'API généralement prise en charge pour un CSPRNG jusqu'en décembre 2013, donc une cryptographie appropriée dans les applications Web était à peine possible jusqu'à il y a quelques années.
  6. Cohérence: plutôt que de changer une fonction existante pour avoir une signification différente, ils ont créé une nouvelle fonction avec un nom différent. Vous pouvez accéder au CSPRNG maintenant via crypto.getRandomValues.

En résumé: héritage, mais aussi rapidité et cohérence . Les PRNG non sécurisés sont encore beaucoup plus rapides car vous ne pouvez pas supposer que tout le matériel prend en charge AES ni dépendre de la disponibilité ou de la sécurité de RDRAND.

Personnellement, je pense qu'il est temps d'échanger toutes les fonctions aléatoires avec des CSPRNG et de renommer les fonctions plus rapides et non sécurisées en quelque chose comme fast_insecure_random () . Ils ne devraient être nécessaires que par des scientifiques ou d'autres personnes qui font des simulations qui nécessitent beaucoup de nombres aléatoires, mais où la prévisibilité du RNG n'est pas un problème. Mais pour une fonction avec deux décennies d'histoire, où une alternative n'existe que depuis quatre ans maintenant (en 2018), je peux comprendre pourquoi nous n'en sommes pas encore à ce point.

De plus, Javascript est un peu plus ancien que la plupart des gens ne le pensent.et la fonction math.random y est depuis au moins 1997 (version 1.1) Une époque où personne n'essaierait même quelque chose comme la cryptographie en javascript (SSL lui-même n'a pas vu la lumière du public jusqu'en 1995, quelques années auparavant)
Je ne suis pas d'accord avec la dernière phrase.Alors que `crypto.getRandomValues` aurait pu être un meilleur nom isolément, avec` math.Random` existe déjà depuis un certain nombre d'années, quelque chose comme `math.RandomCrypto` aurait été un bien meilleur choix car il serait listé ensuiteà l'appel non sécurisé dans toutes les listes d'API et une bonne saisie semi-automatique ferait apparaître les deux versions chaque fois qu'un développeur tapait `math.rando`, ce qui rendrait beaucoup plus probable qu'il se rendrait compte qu'il devrait utiliser la nouvelle quand il en a besoin.
sémantiquement, votre proposition est fausse.vous voulez obtenir des valeurs aléatoires qui sont cryptographiquement saines.pas obtenir une fonction crypto aléatoire / ciper / etc. De plus, la bibliothèque Math ne concerne que les fonctions mathématiques.un CSPRNG est une fonction cryptographique et donc des appartenances dans la bibliothèque cryptographique.(et n'oubliez pas que l'ajout à la norme nécessite un consensus de tous les différents constructeurs de moteurs.)
@DanNeely Je comprends votre point de vue, mais je ne sais pas comment le changer au mieux.N'hésitez pas à modifier!
@LvB Je suis ouvert à différents noms pour la fonction (`math.RandomSecure`?) Ou même à l'implémentation dans` crypto. * `Avec juste un alias sous` math. * `(Est-ce que les js modernes peuvent insérer l'alias àéviter la surcharge d'un appel fonctionnel supplémentaire pour implémenter l'alias?).Mais avec le grand nombre d'outils différents que les gens utilisent pour modifier le javascript, placer l'ancien nom comme première partie du nouveau maximise la probabilité qu'un éditeur soit en mesure de suggérer la source aléatoire sécurisée aux développeurs.
@DanNeely vous essayez ici de résoudre un problème humain par des moyens techniques.e.a.l'humain doit apprendre quel outil utiliser et où, et non l'EDI en utilisant une fonction pratique pour suggérer la bonne.(il serait préférable d'avoir l'IDE que de suggérer le bon, mais cela dépend de l'IDE).Cela n'aiderait pas non plus toutes les personnes qui écrivent du javascript dans le navigateur / vim / nano / notepad / stone tablet / punch card / ou tout autre éditeur de texte ou méthodologie de saisie directe.De plus, vous auriez besoin de beaucoup de développeurs de moteurs, des gens qui ne sont pas faciles à convaincre.
@DanNeely, vous pouvez être en désaccord tout ce que vous voulez, vous n'êtes pas au comité TC39, et ce n'est pas non plus le forum approprié pour discuter de leurs décisions.FWIW, vous pouvez polyfill votre propre suggestion en assignant simplement `Math.randomCrypto = function () {const u = new Uint32Array (1);crypto.getRandomValues (u);renvoie u [0] / 2 ** 32;} `.Bien sûr, il existe des optimisations possibles, mais ce n'est qu'un exemple d'implémentation.
Jared Smith
2018-03-15 16:56:31 UTC
view on stackexchange narkive permalink

C'est trop long pour un commentaire.

Je pense qu'il y a une prémisse erronée dans votre question:

sur les ordinateurs modernes (et même pas si modernes), il serait trivial de produire des centaines de mégaoctets par seconde en utilisant ChaCha8 ou AES-CTR

Vous pensez à un navigateur de bureau sur une machine connectée au secteur ou à un ordinateur portable avec une grosse batterie honkin 10Ah.

Nous vivons dans un monde de plus en plus mobile, et si les appareils mobiles de nos jours sont assez puissants, ils ont deux contraintes importantes: la chaleur et l'autonomie de la batterie. Contrairement à un processeur de bureau qui peut facilement atteindre 100 ° C, vous ne pouvez pas brûler la main de l'utilisateur du smartphone. Et les batteries de téléphone ne contiennent généralement que peut-être 1/3 de la quantité d'un ordinateur portable (si vous avez de la chance). Il n'y a tout simplement aucune bonne raison d'ajouter la production de chaleur / consommation d'énergie supplémentaire si vous n'en avez pas besoin.

Je doute que vous remarquiez la différence de performance / consommation d'énergie entre le RNG crypto et non crypto pour le code typique, même sur mobile.Il faudrait écrire une simulation de monte carlo en javascript.Nous parlons de quelque chose comme 30 cycles CPU pour chaque nombre.
@CodesInChaos qui peut être vrai.Je voudrais voir des analyses (en particulier sur par exemple un port d'un CRPG) avant de passer cet appel.Mais c'est la prémisse implicite de "les ordinateurs sont rapides maintenant, donc peu importe" qui est un problème.
ChaCha8 peut fournir environ 3 cycles par octet même sur les anciens processeurs, et moins d'un cycle par octet avec AVX512.XorShift128 + est inférieur à 1 cycle par octet sur un processeur Haswell haut de gamme, donc la différence n'est pas grande.J'imagine que le simple fait de transformer la valeur aléatoire en une virgule flottante appropriée et de la renvoyer prend plus de cycles que de générer la valeur aléatoire en premier lieu.
@CodesInChaos Les gens écrivent des simulations de Monte Carlo en JavaScript.
En y réfléchissant bien, je suis presque sûr qu'un processeur de bureau atteignant 100 ° C serait _très mauvais_.Les processeurs d'ordinateurs portables peuvent généralement le gérer (même si c'est à peine), mais les ordinateurs de bureau?
@CodesInChaos Techniquement, vous n'avez pas besoin de RNG cryptographiquement fort pour Monte Carlo.Tout RNG décent fonctionnera (comme Mersenne Twister).
@jb.Mon point est que les RNG crypto sont assez rapides pour pratiquement tous les cas d'utilisation et devraient donc être la valeur par défaut.Les simulations de Monte Carlo sont l'un des rares cas où vous voudrez peut-être troquer la qualité contre la performance.
@CodesInChaos Étant donné que `Math.random ()` ne renvoie que des valeurs à virgule flottante individuelles et doit être appelé pour chaque nouvelle valeur, ce serait un moyen assez terrible d'obtenir le caractère aléatoire pour les simulations de Monte Carlo, que XorShift128 + ou ChaCha soit ou nonutilisé.De plus, le LSB de XorShift128 + est un LFSR qui n'est probablement pas très bon pour de telles simulations.
@CodesInChaos: La différence de * génération * d'octets est probablement petite, mais personne ne semble avoir mentionné la partie la plus difficile d'un CSPRNG: la collecte d'entropie.
le navigateur peut utiliser avec plaisir les données aléatoires produites par OS
@JamesKPolk: S'il y a une possibilité qu'un état de CSPRNG ait été exposé, il est nécessaire de le réensemencer avec une source d'entropie indépendante de toute précédente, mais si l'on a un bon CSPRNG avec par ex.4096 bits d'état avec par ex.160 bits d'entropie "pure", et qui ne sont jamais exposés, y a-t-il des attaques qui seraient pratiques qui ne seraient pas pratiques si elles étaient ensemencées avec 4096 bits d'entropie?
@forest: Ce n'est pas qu'un processeur de bureau peut tolérer plus de température en toute sécurité (il ne le peut pas, bien que la limite soit généralement similaire à un processeur mobile, disons 90, 95 ou 100 ° C).C'est que la plupart des processeurs de bureau sont installés avec un refroidissement efficace de sorte qu'ils peuvent exécuter des opérations cryptographiques à pleine inclinaison tout en restant relativement froids, peut-être 60 ° C.Vous ne pouvez tout simplement pas installer cette solution de refroidissement dans un appareil portable, entre autres raisons, car il pèse plus et est plus grand que le reste du téléphone et ne fonctionne qu'avec les bouches d'aération et le flux d'air, inacceptable pour un ordinateur de poche résistant à l'eau quisac.
@BenVoigt Oh hein, j'aurais pu jurer que le Tj Max pour les processeurs de bureau est bien inférieur à celui des ordinateurs portables.J'ai dû me souvenir incorrectement.
LSerni
2018-03-15 12:15:35 UTC
view on stackexchange narkive permalink

La principale raison est qu'il existe une alternative à Math.random () : voir la réponse de Philipp . Donc, quiconque a besoin d'une crypto forte peut l'avoir, et ceux qui n'en ont pas peuvent gagner du temps et de l'énergie (de la batterie).

Mais en supposant que vous ayez demandé, "pourquoi, même s'il existe une alternative plus les développeurs ne mettent pas à jour Math.random () de la même manière - c'est-à-dire ont fait de random () un dérivé de getRandomValues ​​() - afin de renforcer automatiquement un grand nombre d'applications? " - alors je ne pense pas que cela puisse vraiment répondre avec une quelconque confiance, sauf par les développeurs qui ont pris la décision (mise à jour: et comme le veut le destin, nous avons une telle réponse).

En principe - comme vous l'avez déjà dit - il n'y a pas de raison valable .

De plus, la plupart des équipes de développement ont un arriéré important de choses qui sont plus urgentes à faire ; et même un changement apparemment mineur comme celui-ci nécessite des tests, une régression et aller à l'encontre de la règle d'or " Si elle n'est pas enfreinte, ne la corrigez pas ", une forme plus forte du critère YAGNI.

Je suis sûr qu'il y a eu des discussions à ce sujet sur les trackers Mozilla et Google.Peut-être pourriez-vous fournir des liens pour montrer cela?Je serais content que la réponse soit simplement "parce que personne ne l'a encore fait", mais j'aimerais voir quelques exemples de cela se présenter avant et que les développeurs considèrent l'idée comme inutile.
Votez contre parce que je pense qu'il y a lieu de répondre et il est ridicule de le dire, en gras en haut, comme résumé de votre réponse.
@Luc J'ai modifié la réponse pour clarifier ma signification - ainsi que pour voter la réponse de Philipp, qui, je crois, est la bonne réponse à la question posée.
Rob
2018-03-16 08:29:02 UTC
view on stackexchange narkive permalink

Les nombres aléatoires et les bits cryptographiques sont des animaux complètement différents. Ils ne sont même pas utilisés dans le même but. Si vous voulez un nombre aléatoire uniformément réparti entre 0 et 42, vous voulez une distribution uniforme sans motif évident. Notez que si vous modifiez un plus grand nombre avec un plus petit, alors ce n'est pas exactement une distribution uniforme. Cet exemple est facile à voir pour un nombre aléatoire de 0 à 31 pris mod 27. 0 à 4 apparaît deux fois plus souvent que 5 à 31.

Jusqu'à ce que vous parliez de crypto-aléatoire, la notion d'entropie n'est pas ' t même discuté. Un peu d'entropie double l'espace de recherche pour deviner le nombre (pour l'utilisateur prévu des nombres).

Lorsque vous demandez des bits cryptographiques aléatoires, vous demandez N bits d'entropie. Il ne suffit pas d'avoir un modèle non évident, car si une fonction qui le génère est découverte (peu importe sa complexité), alors il y a en fait 0 bit d'entropie du point de vue de celui qui connaît cette fonction.

Un bon exemple de ceci est un générateur de nombres pseudo-aléatoires de type Fortuna. Vous cryptez un nombre 1 avec une clé pour le premier nombre aléatoire (où le bloc de chiffrement est un grand nombre), puis cryptez le numéro 2 avec une clé pour le deuxième nombre aléatoire, et ainsi de suite. En ce qui concerne l'utilisateur qui ne connaît pas la clé (de K bits) du chiffrement, un bloc de chiffrement parfait à N bits aura N bits d'entropie pour ce bloc.

Si vous étendez à un million de bits de données pseudo-aléatoires à partir de celui-ci, alors vous n'avez toujours que K bits d'entropie si vous continuez avec la même clé K. En d'autres termes: si vous aviez un livre de 1 million de bits dont vous savez qu'il a été généré avec un seul chiffre sous K, alors n'essayez pas de deviner tous les bits du flux de chiffrement. Tenez-vous-en à deviner la clé et générez le flux de chiffrement à partir de celle-ci.

Ainsi, un générateur de nombres aléatoires est souvent un chiffrement qui continue d'être réamorcé avec plus d'aléatoire, car il peut être atteint. Par comparaison, un simple générateur de nombres aléatoires [0,1] ne peut pas avoir plus d'entropie que le nombre de bits dans le nombre; et aura généralement une distribution étrange qui n'est pas exactement ce que vous voulez aussi. Crypto a besoin de centaines de bits, lorsque les nombres à virgule flottante ne sont que de 32 ou 64 bits, et l'algorithme lui-même enlève une grande partie de l'entropie .... en supposant que vous voulez quelque chose uniformément distribué à partir de [0..1], plutôt que de dire un représentation en virgule flottante composée de bits aléatoires. Je ne sais même pas quelle distribution cela aurait même.

richzilla
2018-03-15 16:39:06 UTC
view on stackexchange narkive permalink

Vous avez en quelque sorte répondu à la question vous-même:

la norme ne donne explicitement aucune garantie d'aptitude à l'utilisation cryptographique

Donc, plutôt que de changer l'implémentation, l'accent doit être mis sur la formation des développeurs à choisir le 'bon outil pour le travail' ™.

Compte tenu de cela, et de la charge technique liée à la modification de l'implémentation d'une fonction couramment utilisée, ainsi que du fait qu'il existe déjà des solutions spécifiques à ce problème (voir la réponse @Philipps), il n'y a aucune raison impérieuse de faire le changement.

Pourquoi le DV?Les votes anonymes ne servent à rien ...
J'ai voté contre parce que cela répond à une question différente.Naturellement, la norme ne garantit pas la sécurité cryptographique.Cependant, ma question portait spécifiquement sur la sécurité opportuniste.Les normes n'auraient pas besoin d'être touchées.La surcharge technique devrait être faible, car le navigateur est déjà lié à une bibliothèque TLS.Je pourrais probablement éditer un navigateur pour utiliser la bibliothèque de `Math.random ()` en moins de 5 lignes de diff.
allo
2018-03-15 15:10:49 UTC
view on stackexchange narkive permalink

La conception du langage de programmation doit prendre en compte de nombreux éléments. Les navigateurs sont très puissants et optimisent beaucoup javascript aujourd'hui. Mais lorsque vous considérez les systèmes embarqués, vous n'avez peut-être pas de bonne source d'aléa. Par exemple, il y a des microcontrôleurs exécutant un environnement nodeJS (comme).

Un tel microcontrôleur n'a pas de sources aléatoires qui garantissent des nombres aléatoires cryptographiquement sécurisés. Vous auriez donc besoin de connecter un appareil capable de fournir une entrée aléatoire à une broche pour pouvoir implémenter un langage de programmation qui offre de solides garanties sur les nombres aléatoires. Et vous auriez besoin de quelques connaissances pour construire un appareil qui offre suffisamment de caractère aléatoire et pour traiter les entrées de l'appareil de manière appropriée.

Un navigateur exécutant JavaScript aura généralement une bonne source d'aléa pour fournir TLS.Et comme je l'ai dit que la norme n'aurait pas besoin d'être modifiée, il n'est pas nécessaire de garantir que l'API produira un caractère aléatoire sécurisé par cryptographie.
Si l'API ne garantit pas le vrai hasard, vous ne devriez pas vous y fier en tant que développeur.Si les développeurs ne comptent pas dessus, vous n'avez pas besoin de l'implémenter.Imaginez que la plupart des navigateurs aient un vrai hasard là-bas.Les sites Web y construiraient des éléments, car ils sont là.Et puis le prochain navigateur n'a pas le vrai hasard.Oops.Une autre raison peut être que vous épuisez davantage le pool d'entropie et que vous avez besoin de plus de temps si vous sortez de vraies valeurs aléatoires dans chaque appel d'API qui ne les nécessite pas.
Mais certains développeurs comptent dessus, non pas parce qu'ils pensent qu'il est cryptographiquement sécurisé, mais parce qu'ils ne savent pas comment fonctionne l'aléatoire.Il n'y a pas non plus de "entropie épuisante".Une seule graine de 128 bits peut produire une quantité effectivement illimitée de données imprévisibles.
@forest S'il est vrai qu'une clé de 128 bits suffisamment aléatoire combinée à des primitives cryptographiques suffisamment bonnes peut générer des données pseudo-aléatoires plus sécurisées cryptographiquement que quiconque est susceptible d'en avoir besoin dans notre vie, il y a beaucoup de mises en garde.Le fait est que, dans certaines implémentations de CSPRNG, y compris de nombreux noyaux Linux, les pools d'entropie ne sont * pas * une ressource illimitée et peuvent être épuisés / épuisés si vous les interrogez suffisamment.Encouragez les gens à utiliser des choses comme `/ dev / urandom` et non` / dev / random`, si vous voulez, mais ne prétendez pas que `/ dev / random` ne peut pas s'épuiser.
@CBHacking Ils sont en fait illimités.Et en fait, `/ dev / random` ne" s'épuise "jamais.Au contraire, il bloque intentionnellement pour des raisons d'héritage plutôt idiotes.Lisez le code sur [`drivers / char / random.c`] (https://github.com/torvalds/linux/blob/master/drivers/char/random.c) pour comprendre cela plus en détail (c'est littéralement unappel à `wait_event_interruptible ()` pour le décompte estimé).Tant que ChaCha20 (que `/ dev / urandom` utilise) n'est pas fatalement cassé à bien des égards, alors il n'y a aucune raison d'utiliser le pool de blocage sur le pool non bloquant.Notez que les navigateurs n'utilisent pas le pool de blocage.
@forest Pedantry ne devient pas vous.La piscine d'entropie se remplit d'elle-même, mais prétendre qu'elle "ne s'épuise jamais", c'est comme dire que je ne peux pas "manquer" de lait tant qu'il y a une épicerie accessible.De même, prétendre que les raisons `/ dev / random` peuvent bloquer sont" idiotes "et" héritées "ne change pas le fait que les lectures à partir de celui-ci peuvent bloquer pendant des temps arbitrairement longs, et on a en effet observé que cela se produisait sur des choses comme les VMsans interaction de l'utilisateur ni matériel réel (bien qu'aujourd'hui l'hôte fournisse souvent de l'entropie à la VM).En ce qui concerne les navigateurs, la source d'entropie non bloquante est-elle requise par une spécification?
@CBHacking Lorsque vous buvez du lait, le lait disparaît de la cruche.Lorsque vous utilisez l'entropie, même à partir du pool de blocage, les données du pool sont toujours présentes.La seule chose qui change est un seul entier qui garde la trace d'une estimation de l'entropie.Quant aux navigateurs, oui c'est obligatoire.De nombreuses opérations qui nécessitent un flux imprévisible de nombres aléatoires doivent se produire dans un certain laps de temps selon les spécifications.Une implémentation TCP qui risque d'attendre indéfiniment le caractère aléatoire du numéro de séquence serait une implémentation interrompue.
Si vous deviez patcher le noyau pour supprimer le comportement de blocage de `/ dev / random` par la force, il ne s'étoufferait pas ou ne se transformerait pas en` / dev / zero` comme vous vous en doutez si l'entropie était réellement épuisée.Ce serait toujours un CSPRNG parfaitement sécurisé, même s'il repose sur la résistance de pré-image de SHA1 (le pool de blocage et le pool d'entrée caché utilisent le mélange SHA1, alors qu'un pool non bloquant moderne utilise ChaCha20 avec 48 octets de données aléatoires de l'entrée.bassin).Je suppose donc que vous pouvez utiliser le terme «épuisé», mais seulement dans un sens très libéral.Il est techniquement inexact et favorise les mythes.
@forest Assez juste, mais le comportement ressemble toujours à "manquer" d'entropie pour une application cliente, et je ne compterais pas sur la résistance de pré-image de SHA1 pour durer trop longtemps, à quel point un `/ dev / random non bloquant`ne serait plus un" CSPRNG parfaitement sécurisé ".En ce qui concerne les navigateurs, je parlais de l'API JS, pas de ce que la pile réseau du noyau (pas le navigateur!) Fait avec les numéros de séquence TCP.Evidemment, pour cette question, le navigateur n'implémentera pas `Math.random ()` en utilisant le pool de blocage, mais seulement parce que ce serait idiot, pas impossible.
@CBHacking La façon dont SHA1 est utilisé dans le pilote aléatoire est simplement de mélanger les données et de hacher la totalité du tampon de 4096 bits.Une préimage contre SHA1 telle qu'utilisée dans le noyau serait ... très inattendue (je parierais que ChaCha20 sera cassé avant cette date).Quant aux spécifications JS, je ne sais pas.Il n'a probablement aucune exigence réelle pour l'aléa cryptographique, mais je suis sûr que c'est le cas pour un comportement non bloquant.Le fait est que tout ce dont il a besoin, c'est de 128 bits d'aléa pour rendre `Math.random ()` sécurisé de manière opportuniste, sans que cela fasse partie de la norme.
Le fait est que lorsque l'état de votre CSPRNG fuit, vous aurez besoin d'entropie pour l'amorcer à nouveau à une valeur aléatoire.Et quand vous regardez maintenant votre microcontrôleur, c'est très déterminant.Sa mémoire aura toujours la même apparence après le démarrage, selon la puce, elle aura même eu le même nombre de cycles d'horloge au moment où le nombre aléatoire est demandé.Vous devez donc le semer, sinon votre séquence aléatoire est toujours la même.
Et avec trop peu d'entropie, quelqu'un peut trouver l'état de votre CSPRNG par force brute en utilisant la séquence aléatoire pour la validation si vous ne le semez pas assez souvent.Gardez à l'esprit que non seulement l'état du MC est très limité, mais que le programme lui-même ne peut pas être trop complexe car il y a peu d'espace pour votre programme et vous en avez probablement besoin pour le reste de votre code.
Si vous utilisez `getrandom ()`, il ne reviendra que si le pool d'entropie a été initialisé.Une fois que cela est fait, vous pouvez être sûr que le pool ne peut pas être forcé brutalement.
@forest Nous ne parlons pas ici de Linux.Votre microcontrôleur avec une implémentation javascript simple n'a pas du tout de noyau (dans le sens comme un noyau Linux).Il démarre directement dans son environnement nodejs (like), qui n'a pas d'appel `` getrandom () ''.Vous devrez implémenter l'appel vous-même, avec toutes les considérations mentionnées.
Dans ce cas, vous pouvez simplement vous rabattre sur le PRNG merdique que vous voulez (XorShift128 +, LFSR, LCG, peu importe).Pas besoin de changer la norme pour fournir une sécurité opportuniste sur une seule plateforme.
Cort Ammon
2018-03-17 03:04:51 UTC
view on stackexchange narkive permalink

Comme d'autres, je ferais remarquer que Math.random () n'est pas cryptographiquement sécurisé car il n'est généralement pas nécessaire. Mais j'irais plus loin et soutiendrais qu'il n'est pas sage d'écrire un algorithme cryptographiquement sécurisé dans une spécification à moins que vous n'ayez une très bonne raison.

Que signifie être sécurisé cryptographiquement? Eh bien, il y a toujours la définition ennuyeuse de «personne ne sait encore comment le casser». Mais que se passe-t-il quand quelqu'un le casse? Si vous avez spécifié un CSPRNG, vous devez également inclure un moyen d'interroger quel algorithme est utilisé, ou de le faire autrement pour que l'utilisateur final puisse être certain de ce qu'il obtient.

Cela est également probable conduit à la nécessité de pouvoir prendre en charge plusieurs générateurs, de sorte que l'utilisateur puisse en sélectionner un en qui il a confiance. Cela ajoute une complexité énorme. Soudainement, une fonction d'une ligne dans une API est devenue une suite.

De plus, lorsque vous commencez à parler de crypto, vous commencez à parler d'essayer d'être sécurisé dans le générateur. Vous mentionnez l'utilisation d'AES pour générer des nombres aléatoires: votre implémentation AES doit-elle être immunisée contre les attaques de canaux secondaires? Lorsque vous écrivez une bibliothèque dans le but dédié de fournir des garanties cryptographiques, il n'est pas si déraisonnable d'avoir à poser cette question. Pour une spécification, cela pourrait être terriblement déraisonnable. L'immunité aux attaques par canaux secondaires est une chose très difficile à formuler dans le langage des spécifications.

Et qu'avez-vous accompli en le mettant dans une spécification? La plupart des utilisateurs de PRNG n'ont pas du tout besoin de garanties cryptographiques, vous avez donc simplement gaspillé des cycles de processeur pour eux. Ceux qui veulent des garanties cryptographiques vont probablement chercher une bibliothèque qui prend en charge la suite complète des fonctionnalités nécessaires pour être à l'aise avec une telle cryptogaphie, donc ils ne feront pas confiance à Math.random () de toute façon. Il ne reste plus que le groupe démographique que vous mentionnez: des personnes qui ont commis une erreur et ont utilisé un outil alors qu'elles ne le devraient pas. Eh bien, je peux vous dire par expérience que les principaux langages de programmation ne sont pas un endroit pour rechercher une API que vous ne pouvez pas utiliser de manière incorrecte par erreur. Ils sont pleins de phrases "si vous faites cela, c'est de votre faute".

Aussi, considérez ceci: si vous utilisez Math.random () et que vous assumez des garanties cryptographiques, Quelles sont les chances que vous fassiez une autre erreur de cryptographie fatale quelque part dans votre algorithme? Un CSPRNG Math.random () peut fournir un faux sentiment de sécurité, et nous pouvons trouver encore plus d'erreurs!

Évidemment, vous ne devriez pas l'utiliser comme propriété cryptographique _assume_.Si vous en avez besoin, il existe des API cryptographiques dédiées (c'est aussi pourquoi j'ai suggéré ChaCha8 au lieu du ChaCha20 complet. Notez qu'une rupture cryptographique peut être effectuée contre un ChaCha 7 rounds).
Voir ma modification de la question d'origine qui clarifie cela.
@forest Je vois votre modification, et je pense que mon dernier paragraphe tient toujours.Si l'on pense que leur logiciel est sécurisé parce qu'ils ont eu de la chance et que quelqu'un d'autre a pensé à la sécurité pour eux, ils vont se réveiller brutalement.
Spence
2018-03-22 18:51:10 UTC
view on stackexchange narkive permalink

Tout le monde semble avoir manqué une petite nuance ici: les algorithmes cryptographiques exigent qu'un nombre soit mathématiquement et statistiquement aléatoire sur toutes les exécutions de l'algorithme. Cela signifie par exemple pendant un jeu ou une animation, que vous pourriez utiliser une suite de nombres aléatoires et ce serait parfaitement bien pour une "sorte de nombre aléatoire".

Cependant si ce nombre pouvait être manipulé ou prédit, par exemple un nombre aléatoire prédéfini (qui est le comportement par défaut des fonctions aléatoires de Windows), alors cette graine est en fait prévisible. Si je peux manipuler votre application pour redémarrer puis utiliser un nombre aléatoire prédéfini, je peux prédire quel nombre "aléatoire" vous choisirez. Si cela est possible, la cryptographie peut être vaincue. Une préoccupation secondaire peut également être que certains algorithmes nécessitent une distribution garantie des nombres sur tout le spectre, ce que certains générateurs aléatoires ne peuvent pas garantir.

Les générateurs de nombres aléatoires cryptographiques ont un grand ensemble d'entrées pour créer une entropie, par exemple mesurer le bruit de tir de l'entrée du microphone, les graduations de l'heure, la somme de contrôle des registres de bélier, les numéros de série, etc. Dans un sens cryptographique, les performances ne sont pas l'objectif, mais le "vrai" hasard.

Donc, en fonction de votre cas d'utilisation, vous voudrez peut-être une implémentation raisonnablement aléatoire et performante d'un nombre aléatoire, mais si vous faites une différence -hellman échange de clés vous avez besoin d'un algorithme cryptographiquement sécurisé.

Bobby Baucom
2018-03-24 04:02:59 UTC
view on stackexchange narkive permalink

Une autre considération que je n'ai vu personne mentionner (ou que j'ai simplement négligée) est que certaines utilisations de la fonction Math.random () dépendent en fait de la répétabilité lorsqu'elles sont initialisées de la même manière que les précédentes temps. Le changer maintenant casserait ces utilisations.

Tous les PRNG déterministes le font, sécurisés cryptographiquement ou non.
quels navigateurs sont livrés avec la possibilité d'amorcer le générateur?


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...