web-dev-qa-db-fra.com

Avantages et inconvénients de RNGCryptoServiceProvider

Quels sont les avantages et les inconvénients de l'utilisation de System.Security.Cryptography.RNGCryptoServiceProvider contre System.Random. Je sais que RNGCryptoServiceProvider est 'plus aléatoire', c'est-à-dire moins prévisible pour les pirates. D'autres avantages ou inconvénients?


MISE À JOUR:

Selon les réponses, voici les avantages et les inconvénients de l'utilisation de RNGCryptoServiceProvider jusqu'à présent:

Avantages

  • RNGCryptoServiceProvider est un nombre aléatoire cryptographiquement plus fort, ce qui signifie qu'il serait préférable de déterminer les clés de chiffrement et autres.

Les inconvénients

  • Random est plus rapide car il s'agit d'un calcul plus simple; lorsqu'il est utilisé dans des simulations ou de longs calculs où l'aléatoire cryptographique n'est pas important, il doit être utilisé. Remarque: voir réponse de Kevin pour plus de détails sur les simulations - Random n'est pas nécessairement assez aléatoire, et vous voudrez peut-être utiliser un PRNG non cryptographique différent.
68
configurator

Un RNG cryptographiquement fort sera plus lent --- il faut plus de calcul --- et sera spectralement blanc, mais ne sera pas aussi bien adapté aux simulations ou aux méthodes de Monte Carlo, à la fois parce qu'ils do prennent plus de temps, et parce qu'ils peuvent ne pas être répétables, ce qui est bien pour les tests.

En général, vous souhaitez utiliser un cryptographique PRNG lorsque vous voulez un numéro unique comme un UUID, ou comme clé de cryptage, et un déterministe PRNG pour vitesse et en simulation.

51
Charlie Martin

System.Random n'est pas thread-safe.

12
Yury Chaikou

Oui, il n'y en a qu'un de plus. Comme l'a écrit Charlie Martin System.Random est plus rapide.

Je voudrais ajouter les informations suivantes:

RNGCryptoServiceProvider est l'implémentation par défaut d'un générateur de nombres aléatoires conforme aux normes de sécurité. Si vous avez besoin d'une variable aléatoire pour des raisons de sécurité, vous devez utiliser cette classe, ou un équivalent, mais n'utilisez pas System.Random car elle est hautement prévisible.

Pour toutes les autres utilisations, les performances supérieures de System.Random et les classes équivalentes sont les bienvenues.

9
Jader Dias

En plus des réponses précédentes:

System.Random ne devrait [~ # ~] jamais [~ # ~] être utilisé dans les simulations ou les solveurs numériques pour la science et l'ingénierie, où il y a des conséquences négatives importantes de résultats de simulation inexacts ou d'échec de convergence. Cela est dû au fait que l'implémentation de Microsoft est profondément imparfaite à plusieurs égards, et ils ne peuvent pas (ou ne vont pas) le corriger facilement en raison de problèmes de compatibilité. Voir ce post .

Alors:

  • S'il y a un adversaire qui ne devrait pas connaître la séquence générée , alors utilisez RNGCryptoServiceProvider ou un autre RNG soigneusement conçu, implémenté et validé cryptographiquement fort, et utiliser idéalement le hasard matériel si possible. Sinon;

  • S'il s'agit d'une application telle qu'une simulation qui nécessite de bonnes propriétés statistiques , alors utilisez un non-crypto soigneusement conçu et implémenté PRNG comme le Mersenne Twister . (Un RNG crypto serait aussi correct dans ces cas, mais souvent trop lent et trop lourd.) Sinon ;

  • [~ # ~] seulement [~ # ~] si l'utilisation des nombres est complètement triviale , comme décider quelle image afficher ensuite dans un diaporama aléatoire, puis utilisez System.Random.


J'ai récemment rencontré ce problème de manière très tangible lorsque je travaillais sur une simulation Monte Carlo destinée à tester les effets de différents modèles d'utilisation pour les dispositifs médicaux. La simulation a produit des résultats qui vont légèrement dans le sens opposé de ce qui aurait été raisonnablement attendu.

Parfois, quand vous ne pouvez pas expliquer quelque chose, il y a une raison derrière cela, et cette raison peut être très onéreuse !

Voici un tracé des valeurs p - obtenues sur un nombre croissant de lots de simulation:

Input & output _p_‑values while using <code>System.Random</code>

Les graphiques rouge et magenta montrent la signification statistique des différences entre les deux modèles d'utilisation dans deux mesures de sortie à l'étude.

Le tracé cyan est un résultat particulièrement choquant, car il représente p - les valeurs d'une caractéristique de l'aléatoire entrée pour la simulation. (Cela était tracé juste pour confirmer que l'entrée n'était pas défectueuse.) L'entrée était, bien sûr, par conception la même entre les deux modèles d'utilisation à l'étude, donc il ne devrait pas y avoir de différence statistiquement significative entre l'entrée aux deux modèles. Pourtant, ici, je voyais mieux que 99,97% de confiance qu'il y avait une telle différence !!

Au début, je pensais qu'il y avait quelque chose de mal dans mon code, mais tout s'est vérifié. (En particulier, j'ai confirmé que les discussions ne partageaient pas System.Random Instances.) Lorsque des tests répétés ont révélé que ce résultat inattendu était très cohérent, j'ai commencé à soupçonner System.Random.

J'ai remplacé System.Random avec une implémentation de Mersenne Twister - aucune autre modification, - et immédiatement la sortie est devenue radicalement différente, comme illustré ici:

Input & output _p_‑values after switching to a better PRNG

Ce graphique indique qu'il n'y a pas de différence statistiquement significative entre les deux modèles d'utilisation pour les paramètres utilisés dans cet ensemble de test particulier. C'était un résultat attendu.

Notez que dans le premier graphique, l'échelle logarithmique verticale (sur la valeur p - couvre sept décennies , alors que il n'y a qu'une seule décennie dans la seconde - ce qui montre à quel point la signification statistique des fausses divergences était prononcée! (L'échelle verticale indique la probabilité que des écarts aient pu se produire par hasard.)

Je suppose que ce qui se passait était que System.Random a quelques corrélations sur un cycle de générateur assez court, et différents modèles d'échantillonnage aléatoire interne entre les deux modèles testés (qui avaient des nombres d'appels sensiblement différents à Random.Next) a provoqué ces effets sur les deux modèles de manière distincte.

Il se trouve que la simulation entrée puise dans les mêmes flux RNG que les modèles utilisent pour les décisions internes, et cela a apparemment causé ces écarts d'échantillonnage à affecter l'entrée. (C'était en fait une chose chanceuse, car sinon je ne me serais peut-être pas rendu compte que le résultat inattendu était une erreur logicielle et non une propriété réelle des appareils simulés!)

2
Kevin