За и против RNGCryptoServiceProvider

Каковы плюсы и минусы использования System.Security.Cryptography.RNGCryptoServiceProvider против System.Random. Я знаю, что RNGCryptoServiceProvider является "более случайным", то есть менее предсказуемым для хакеров. Есть еще плюсы или минусы?


ОБНОВИТЬ:

Согласно ответам, вот плюсы и минусы использования RNGCryptoServiceProvider данный момент:

Pros

  • RNGCryptoServiceProvider - более сильное криптографически случайное число, означающее, что оно было бы лучше для определения ключей шифрования и тому подобного.

Cons

  • Random быстрее, потому что это более простой расчет; при использовании в симуляциях или длинных вычислениях, где криптографическая случайность не важна, это следует использовать. Примечание: подробности об имитации см. В ответе Кевина. Random не обязательно является достаточно случайным, и вы можете использовать другой не криптографический PRNG.

Ответ 1

Криптографически сильный RNG будет медленнее - он требует больше вычислений --- и будет спектрально-белым, но не будет так хорошо подходить для моделирования или методов Монте-Карло, так как они занимают больше времени и потому что они могут не повторяться, что хорошо для тестирования.

В общем, вы хотите использовать криптографический PRNG, если хотите уникальный номер, например UUID, или как ключ для шифрования, и детерминированный PRNG для скорости и моделирования.

Ответ 2

System.Random не является потокобезопасным.

Ответ 3

Да, есть еще один. Как писал Чарли Мартин System.Random быстрее.

Я хотел бы добавить следующую информацию:

RNGCryptoServiceProvider - это стандартная реализация генератора случайных чисел, совместимого с стандартами безопасности. Если вам нужна случайная переменная для целей безопасности, вы должны использовать этот класс или эквивалент, но не использовать System.Random, потому что он очень предсказуем.

Для всех других целей приветствуется более высокая производительность System.Random и эквивалентных классов.

Ответ 4

В дополнение к предыдущим ответам:

System.Random НИКОГДА не следует использовать в симуляциях или численных решениях для науки и техники, где имеются существенные негативные последствия неточных результатов моделирования или сбоя сходимости. Это связано с тем, что реализация Microsoft имеет серьезные недостатки в нескольких отношениях, и они не могут (или не будут) легко ее исправить из-за проблем совместимости. Смотрите этот пост.

Так:

  • Если есть злоумышленник, который не должен знать сгенерированную последовательность, используйте RNGCryptoServiceProvider или другой тщательно спроектированный, реализованный и проверенный криптографически RNGCryptoServiceProvider ГСЧ и, по возможности, используйте аппаратную случайность. Иначе;

  • Если это приложение, такое как моделирование, которое требует хороших статистических свойств, тогда используйте тщательно разработанный и внедренный не криптографический PRNG, такой как Mersenne Twister. (Крипто-ГСЧ также будет правильным в этих случаях, но часто слишком медленным и громоздким.) В противном случае;

  • ТОЛЬКО если использование чисел совершенно тривиально, например, решить, какое изображение показывать дальше в рандомизированном слайд-шоу, тогда используйте System.Random.


Недавно я столкнулся с этой проблемой очень ощутимо, работая над симуляцией Монте-Карло, предназначенной для проверки влияния различных моделей использования медицинских устройств. Моделирование дало результаты, которые мягко шли в направлении, противоположном ожидаемому.

Иногда, когда вы не можете что-то объяснить, за этим стоит причина, и эта причина может быть очень обременительной!

Вот график значений p, которые были получены в течение возрастающего числа партий моделирования:

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

Красные и пурпурные графики показывают статистическую значимость различий между двумя моделями использования в двух исследуемых выходных метриках.

Голубой график является особенно шокирующим результатом, поскольку он представляет p-значения для характеристики случайного ввода в симуляцию. (Это было построено только для того, чтобы подтвердить, что входные данные не были ошибочными.) Входные данные, конечно, были одинаковыми для двух исследуемых моделей использования, поэтому не должно было быть статистически значимой разницы между входными данными для двух моделей., Тем не менее, здесь я видел, что уверенность в 99,97% в том, что была такая разница!

Сначала я думал, что в моем коде что-то не так, но все проверили. (В частности, я подтвердил, что потоки не делятся экземплярами System.Random.) Когда повторное тестирование показало, что этот неожиданный результат является весьма непротиворечивым, я начал подозревать System.Random.

Я заменил System.Random на реализацию Mersenne Twister - никаких других изменений - и сразу же результат стал резко отличаться, как показано здесь:

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

Эта диаграмма отражает отсутствие статистически значимой разницы между двумя моделями использования параметров, используемых в этом конкретном тестовом наборе. Это был ожидаемый результат.

Обратите внимание, что на первом графике вертикальная логарифмическая шкала (в значении p) охватывает семь десятилетий, тогда как во втором - только одно десятилетие - демонстрируя, насколько ярко выражена статистическая значимость ложных расхождений! (Вертикальная шкала указывает на вероятность того, что расхождения могли возникнуть случайно.)

Я подозреваю, что происходило то, что System.Random имеет некоторые корреляции в течение некоторого довольно короткого цикла генератора, и различные образцы внутренней выборки случайности между двумя тестируемыми моделями (которые имели существенно различное количество вызовов Random.Next) вызвали их влияние две модели по-разному.

Так получилось, что входные данные моделирования основаны на тех же потоках ГСЧ, что и модели, используемые для внутренних решений, и это, очевидно, привело к тому, что несоответствия выборки повлияли на входные данные. (Это на самом деле повезло, потому что в противном случае я, возможно, не понял бы, что неожиданный результат был программной ошибкой, а не каким-то реальным свойством моделируемых устройств!)