RandomNumberGenerator与RNGCryptoServiceProvider

时间:2012-09-08 09:59:35

标签: c# random cryptography

根据RandomNumberGenerator的MSDN文档:

  

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

     

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

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

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

最值得注意的是StackExchange(我假设包含SO)以及BCrypt.Net

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

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

3 个答案:

答案 0 :(得分:18)

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

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

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

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


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

  

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

框架4.0的文档说:

  

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

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

答案 1 :(得分:3)

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

  

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

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

我怀疑最初的意图是:

  

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

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

答案 2 :(得分:1)

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

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