RandomNumberGenerator vs RNGCryptoServiceProvider

В соответствии с документацией MSDN для RandomNumberGenerator:

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

Для реализации генератора криптографических случайных чисел используйте производный класс RNGCryptoServiceProvider.

Однако, я видел следующий код, используемый в нескольких случаях в разных базовых кодах:

byte[] bytes = new byte[...];
RandomNumberGenerator rng = RandomNumberGenerator.Create();
rng.GetBytes(bytes);

В первую очередь с StackExchange (который, как я предполагаю, включает SO), а также с BCrypt.Net.

Поэтому я немного смущен - какой тип RandomNumberGenerator является приведенным выше кодом? Также является ли это недостатком, что некоторые базы кода используют RandomNumberGenerator, а не RNGCryptoServiceProvider?

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

Ответ 1

Метод RandomNumberGenerator.Create() вызывает метод RandomNumberGenerator.Create("System.Security.Cryptography.RandomNumberGenerator"), который в конечном итоге создаст экземпляр RNGCryptoServiceProvider.

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

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

Этот способ создания экземпляров разных типов в зависимости от входных данных используется в нескольких местах в структуре, например, методом WebRequest.Create.


Кто-то в Micrsoft "исправил" текущую документацию (framework 4.5) для метода Create(). Теперь говорится:

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

Документация для Framework 4.0 гласит:

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

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

Ответ 2

Документация для RandomNumberGenerator в основном запутана. В качестве другого примера есть такая документация:

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

... для статического метода. Статические методы нельзя переопределить. Тот, кто написал документацию, явно не думал прямо.

Я подозреваю, что первоначальное намерение было чем-то вроде:

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

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

Ответ 3

RandomNumberGenerator.Create - статический метод factory. Разумеется, он вернет экземпляры производного класса. И это не абстрактно, поэтому все это законно.

Абстрактные классы используются везде, а не для использования более конкретного класса. Они предназначены для использования с версиями.