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. Разумеется, он вернет экземпляры производного класса. И это не абстрактно, поэтому все это законно.
Абстрактные классы используются везде, а не для использования более конкретного класса. Они предназначены для использования с версиями.