RandomNumberGenerator与RNGCryptoServiceProvider

问题描述 投票:13回答:3

根据RandomNumberGenerator的MSDN文档:

应用程序代码不直接使用此类。此抽象类作为所有加密随机数生成器的基类提供。

对于加密随机数生成器的实现,请使用派生类RNGCryptoServiceProvider。

但是,我看到以下代码在不同代码库中的几个场景中使用:

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

最值得注意的是StackExchange(我假设包括SO)和BCrypt.Net

因此,我有点困惑 - 上面的代码返回什么类型的RandomNumberGenerator?还有一些缺陷,一些代码库使用RandomNumberGenerator而不是RNGCryptoServiceProvider

我假设RandomNumberGenerator.Create()在幕后做,我在这里完全没有,但从技术上讲(因为它是一个抽象类)不应该上面的代码抛出错误?

c# random cryptography
3个回答
18
投票

RandomNumberGenerator.Create()方法调用RandomNumberGenerator.Create("System.Security.Cryptography.RandomNumberGenerator"),最终将创建RNGCryptoServiceProvider的实例。

(它在一对字典中进行一些查找,因此您可以通过在某处注册默认随机生成器来更改该调用的行为。)

返回的对象的实际类型在编译时是未知的,只知道它将继承RandomNumberGenerator类,因此您可以使用RandomNumberGenerator引用变量。

这种根据输入创建不同类型实例的方式在框架中的几个地方使用,例如通过WebRequest.Create方法。


微软的某个人已经“修复”了Create()方法的当前文档(框架4.5)。它现在说:

“在派生类中重写时,创建一个可用于生成随机数据的加密随机数生成器的默认实现的实例。”

框架4.0的文档说:

“创建可用于生成随机数据的加密随机数生成器的默认实现的实例。”

这是该方法的正确描述。我将提出将该描述放回到较新文档中的请求。


3
投票

RandomNumberGenerator的文档基本搞砸了。另一个例子,有这样的文档:

在派生类中重写时,创建加密随机数生成器的指定实现的实例。

...对于静态方法。静态方法无法覆盖。谁清楚地写了这些文件并没有直接思考。

我怀疑最初的意图是这样的:

应用程序代码不直接实例化此类。此抽象类作为所有加密随机数生成器的基类提供。

我认为你发布的代码(使用静态Create方法)是完全合理的。它与用于XmlReader.Create等的模式相同 - 静态方法选择最合适的实现。


1
投票

RandomNumberGenerator.Create是一种静态工厂方法。当然它会返回派生类的实例。那个不是抽象的所以这一切都是合法的。

抽象类可以在任何地方使用,而不是使用更具体的类。它们是一个版本友好的界面。

© www.soinside.com 2019 - 2024. All rights reserved.