C#中真随机数生成器的最快实现
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/668361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fastest implementation of a true random number generator in C#
提问by Click Ok
I was reading about Random.Next()that for "cryptographically secure random number suitable for creating a random password" MSDN suggests RNGCryptoServiceProvider Class
我正在阅读关于“适合创建随机密码的加密安全随机数”的Random.Next()MSDN 建议RNGCryptoServiceProvider Class
What the speed penality? There is some fastest way to get true random numbers?
速度惩罚是什么?有什么最快的方法可以获得真正的随机数?
EDIT: With Random.Next() I get a new random number. And with...
编辑:使用 Random.Next() 我得到一个新的随机数。与...
byte[] randomNumber = new byte[1];
RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
Gen.GetBytes(randomNumber);
int rand = Convert.ToInt32(randomNumber[0]);
I get a "cryptographically secure random number" I want know if the above code is fast compared with "Random.Next()"and if there is some fast way to get same results, ok?
我得到一个“密码安全的随机数”我想知道上面的代码与“Random.Next()”相比是否快,如果有一些快速的方法可以获得相同的结果,好吗?
回答by Mehrdad Afshari
The rule of thumb when it comes to security and cryptography stuff:
在安全和加密方面的经验法则:
Neverwrite your own.
永远不要自己写。
Go with the standard way of doing it and avoid dangerous optimizations.
按照标准的方式去做,避免危险的优化。
Edit to address the updated question:
编辑以解决更新的问题:
Use Random.Next
when you need statistically random numbers not used in security sensitive code and RNGCryptoServiceProvider
in security sensitive code. It's not as fast as Random.Next
but it has acceptable performance. You should benchmark to see the actual difference. It usually doesn't make sense to sacrifice security for performance.
使用Random.Next
时,你需要在安全性敏感的代码,而不是用统计学的随机数RNGCryptoServiceProvider
在安全敏感的代码。它没有那么快,Random.Next
但它具有可接受的性能。您应该进行基准测试以查看实际差异。为了性能而牺牲安全性通常是没有意义的。
回答by MarkusQ
The only known way to get trulyrandom numbers in hardware is slow; if you try to speed it up your hair turns white, falls out in clumps, and the NRC sends robots in to clean up your server room.
在硬件中获得真正随机数的唯一已知方法是缓慢;如果你想加快速度,你的头发会变白,成团脱落,NRC 会派机器人来清理你的服务器机房。
I'm with Mehrdad on this one: don't try to roll your own.
我和 Mehrdad 在一起:不要尝试自己动手。
回答by LukeH
The "cryptographically secure random number" generated by your example code will only ever be between 0 and 255 inclusive!
您的示例代码生成的“密码安全随机数”只会在 0 到 255 之间(包括 0 和 255)!
If you want to return all possible Int32
values then you should use 4 random bytes. Your code should look something like this:
如果要返回所有可能的Int32
值,则应使用 4 个随机字节。您的代码应如下所示:
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] rndBytes = new byte[4];
rng.GetBytes(rndBytes);
int rand = BitConverter.ToInt32(rndBytes, 0);
A quick benchmark on my (old-ish) machine suggests that Random.Next
is approximately 200x faster than using RNGCryptoServiceProvider
.
我的(旧式)机器上的快速基准测试表明,Random.Next
它比使用RNGCryptoServiceProvider
.
回答by jalf
The simplest way to answer your question might be to turn your question upside down.
回答问题的最简单方法可能是将问题颠倒过来。
Assumethat the CryptoServiceProvider implementation holds all the advantages. It is just as fast and uses just as little memory as Random.Next.
假设CryptoServiceProvider 实现拥有所有优点。它与 Random.Next 一样快,占用的内存也一样少。
Then why do both implementations exist? Why do we even HaveRandom.Next in the framework?
那么为什么这两种实现都存在呢?为什么我们甚至在框架中有Random.Next ?
Look at what we know about each implementation. One generates cryptographically secure random number, the other makes no promises.
看看我们对每个实现的了解。一个生成加密安全的随机数,另一个不作任何承诺。
Which is simpler? Generating random numbers that are sufficiently random to be used in cryptography, or generating numbers that simply "look" random, but don't guarantee anything else? If there wasn't a cost associated with generating cryptographically secure random numbers, then everyrandom number generator would do it.
哪个更简单?生成足够随机以用于密码学的随机数,或者生成简单“看起来”随机但不保证其他任何内容的数字?如果没有与生成加密安全随机数相关的成本,那么每个随机数生成器都会这样做。
You can usually assume that standard library functions are designed to do what it says on the box and do it well. Random.Next is designed to get you the next random number in a sequence of pseudo-random numbers as efficiently as possible.
您通常可以假设标准库函数的设计目的是按照包装盒上所说的去做并且做得很好。Random.Next 旨在让您尽可能高效地获取伪随机数序列中的下一个随机数。
CryptoServiceProvider is designed to generate random numbers strong enough to be used in cryptography, and do thatas efficiently as possible. If there was a way to do this as efficiently as Random.Next, then Random.Next would use it too.
CryptoServiceProvider 旨在生成足够强大的随机数以用于密码学,并尽可能高效地执行此操作。如果有办法尽可能高效Random.Next做到这一点,那么Random.Next会使用它太。
Your question seems to assume brain damage on the part of the framework designers - that they somehow designed a needlessly slow function to generate cryptographically secure random numbers, even though there was a faster way.
你的问题似乎假设框架设计者的大脑受到了伤害——他们以某种方式设计了一个不必要的缓慢函数来生成加密安全的随机数,即使有更快的方法。
The fastest way to generate cryptographically secure random numbers is most likely to call the function designed by experts to generate cryptographically secure random numbers.
生成密码安全随机数的最快方法最有可能调用专家设计的函数来生成密码安全随机数。
回答by J.C. Inacio
What you should be doing first and foremost, is learning the basic differences between a RNG, PRNG, and CSPRNG.
您首先应该做的是了解RNG、PRNG和CSPRNG之间的基本区别。
Only after this should you be deciding on what you really need, and what possible implementations could be. As a general rule, though, you should just accept what has been established and proven to be a proper implementation.
只有在此之后,您才应该决定您真正需要什么,以及可能的实现是什么。但是,作为一般规则,您应该只接受已经建立并被证明是正确实现的内容。
回答by user32848
A side issue, but interesting, is your use of "true" in the question. True random numbers do not exist in hardware or software. They exist in "real life" as in radioactive decay or noise on a line, but can not be generated by a program. Thus, please note jalf's use of "pseudo-" and check jcinacio's links to wikipedia.
一个附带但有趣的问题是您在问题中使用了“true”。硬件或软件中不存在真随机数。它们存在于“现实生活”中,就像在线路上的放射性衰变或噪音一样,但不能由程序生成。因此,请注意 jalf 使用“伪-”并检查 jcinacio 的维基百科链接。
回答by Tobias Hertkorn
AFAIK a true random generator will never be implemented in C#. That can only be done with the help of hardware?
AFAIK 永远不会在 C# 中实现真正的随机生成器。那只能借助硬件来完成吗?
回答by Jeremy Wilson
Another point that hasn't been brought up:
还有一点没有提到:
PRNG will produce predictable results given the same initial seed value. CSPRNG will not - it has no seed value. This makes PRNGs (to some degree) suitable for use in cypher stream algorithms. Two computers given the same initialization vectors (used as seed values to one or more PRNGs) could effectively communicate with each other in private using the XORed result of the plain text bytes and the output of the seeded PNG(s) used.
给定相同的初始种子值,PRNG 将产生可预测的结果。CSPRNG 不会——它没有种子价值。这使得 PRNG(在某种程度上)适用于密码流算法。给定相同初始化向量(用作一个或多个 PRNG 的种子值)的两台计算机可以使用纯文本字节的异或结果和所用种子 PNG 的输出进行有效的私下通信。
I'm not claiming that such an implementation would be necessarily be cryptographically secure of course; only that such an implementation would require the predictability of a PRNG that CSPRNG does not offer.
当然,我并不是说这样的实现在密码学上一定是安全的;只是这样的实现需要 CSPRNG 不提供的 PRNG 的可预测性。