Быстрая реализация генератора случайных чисел в С#

Я читал о Random.Next(), что для "криптографически безопасного случайного числа, подходящего для создания случайного пароля" MSDN предлагает класс RNGCryptoServiceProvider

Какова скорость пения? Существует какой-то самый быстрый способ получить истинные случайные числа?

EDIT: С Random.Next() я получаю новое случайное число. И с...

byte[] randomNumber = new byte[1];
RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
Gen.GetBytes(randomNumber);
int rand = Convert.ToInt32(randomNumber[0]);

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

Ответ 1

Самый простой способ ответить на ваш вопрос может состоять в том, чтобы перевернуть вопрос вверх ногами.

Предположим, что реализация CryptoServiceProvider обладает всеми преимуществами. Это так же быстро и использует так же мало памяти, как Random.Next.

Тогда почему существуют обе реализации? Почему у нас даже есть Random.Next в рамках?

Посмотрите, что мы знаем о каждой реализации. Один генерирует криптографически безопасное случайное число, другое не делает promises.

Что проще? Генерация случайных чисел, которые являются достаточно случайными для использования в криптографии, или генерирование чисел, которые просто "смотрят" случайным образом, но не гарантируют ничего другого? Если бы не было затрат, связанных с генерированием криптографически безопасных случайных чисел, то каждый генератор случайных чисел сделал бы это.

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

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

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

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

Ответ 2

Эмпирическое правило, касающееся безопасности и криптографии:

Никогда не пишите свой собственный.

Пойдите со стандартным способом этого и избегайте опасных оптимизаций.

Изменить для ответа на обновленный вопрос:

Используйте Random.Next, если вам нужны статистически случайные числа, которые не используются в секретном коде безопасности и RNGCryptoServiceProvider в секретном коде. Это не так быстро, как Random.Next, но имеет приемлемую производительность. Вы должны ориентироваться, чтобы увидеть реальную разницу. Обычно нецелесообразно жертвовать безопасностью для производительности.

Ответ 3

"Криптографически безопасное случайное число", сгенерированное вашим примером кода, будет только от 0 до 255 включительно!

Если вы хотите вернуть все возможные значения Int32, вы должны использовать 4 случайных байта. Ваш код должен выглядеть примерно так:

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] rndBytes = new byte[4];
rng.GetBytes(rndBytes);
int rand = BitConverter.ToInt32(rndBytes, 0);

Быстрый тест на моей машине (старое) предполагает, что Random.Next примерно на 200 раз быстрее, чем при использовании RNGCryptoServiceProvider.

Ответ 4

Что вы должны делать в первую очередь, это изучение основных различий между RNG, PRNG и CSPRNG.

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

Ответ 5

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

Я нахожусь с Мехрдадом на этом: не пытайтесь катиться самостоятельно.

Ответ 6

Вопрос, но интересный, является вашим использованием "истины" в вопросе. Истинное случайное число не существует в аппаратном или программном обеспечении. Они существуют в "реальной жизни", как в случае радиоактивного распада или шума на линии, но не могут быть созданы программой. Таким образом, обратите внимание на использование "псевдо" и проверку ссылок jcinacio на wikipedia.

Ответ 7

AFAIK истинный случайный генератор никогда не будет реализован в С#. Это можно сделать только с помощью аппаратного обеспечения?

Ответ 8

Еще один момент, который не был поднят:

PRNG будет давать прогнозируемые результаты, учитывая одно и то же начальное значение затравки. CSPRNG не будет - у него нет начального значения. Это делает PRNG (в некоторой степени) подходящим для использования в алгоритмах потока cypher. Два компьютера с одинаковыми векторами инициализации (используемые в качестве начальных значений для одного или нескольких PRNG) могли бы эффективно взаимодействовать друг с другом в частном порядке с использованием результата XORed из простых текстовых байтов и вывода использованных PNG (s).

Я не утверждаю, что такая реализация обязательно должна быть криптографически защищена, конечно; только то, что такая реализация потребует предсказуемости PRNG, который CSPRNG не предлагает.