views:

4205

answers:

9

I was reading about Random.Next() that for "cryptographically secure random number suitable for creating a random password" MSDN suggests 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...

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?

+17  A: 

The rule of thumb when it comes to security and cryptography stuff:

Never write 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.

Mehrdad Afshari
Can someone explain (beginner here) why everyone is saying "don't write your own?" I don't think the op is writing his own? I thought he was just asking which if the crypto secure method is as fast as Random.Next?
J M
Actaully, never mind - I think it was just a warning to to consider it (and a good one of course). I didn't read the rest of the answer and therefore didn't see it go on to explain about which to use.
J M
Arg - can't edit comments - "to to" should read "not to even"
J M
A: 

Your best bet is to profile it.

jeffamaphone
+4  A: 

The only known way to get truly random 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.

I'm with Mehrdad on this one: don't try to roll your own.

MarkusQ
A reference to random numbers based on isotope decay? I grinned.
Zan Lynx
Good one {10chars]
Ed Swangren
Haha! Well, there is quantum random number generation, I don't know how cheap it is, though.
Matt Olenik
@MattOlenik -- ...whoooshhhh...
MarkusQ
+5  A: 

The "cryptographically secure random number" generated by your example code will only ever be between 0 and 255 inclusive!

If you want to return all possible Int32 values then you should use 4 random bytes. Your code should look something like this:

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.

LukeH
Wow! 200x is a lot of difference! Thanks! :)
Click Ok
+14  A: 

The simplest way to answer your question might be to turn your question upside down.

Assume that the CryptoServiceProvider implementation holds all the advantages. It is just as fast and uses just as little memory as Random.Next.

Then why do both implementations exist? Why do we even Have Random.Next in the framework?

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 every random 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.

CryptoServiceProvider is designed to generate random numbers strong enough to be used in cryptography, and do that as efficiently as possible. If there was a way to do this as efficiently as Random.Next, then Random.Next would use it too.

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.

jalf
+1 for well written. I loved this answer because it asks the questions "Why are there two methods?" and "How do you sensibly choose between each one?" I want to link it to a question I asked a few hours ago about real world examples of framework choices but not sure how....
J M
Thanks. I was worried it came across too harsh (which wasn't intended)I just wanted to make the point that the framework designers have tried to implement both functions as efficiently as possible, and that presumably there is a reason why both exist.
jalf
+1 Very well explained
Nifle
+3  A: 

What you should be doing first and foremost, is learning the basic differences between a RNG, PRNG, and 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.

jcinacio
+1 for the useful links and pointing out other options.
J M
Reading those links - aren't the only choices between PRNG and CSPRNG? If a person does need CSPRNG, what is the next set of considerations?
J M
+1  A: 

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.

They exist in hardware
Blorgbeard
Well sure, they exist everywhere, but it's hard to get them into software without a specialized setup (like a radioactive source).
David Zaslavsky
Right, but you can buy one - http://www.protego.se/
Blorgbeard
+1  A: 

AFAIK a true random generator will never be implemented in C#. That can only be done with the help of hardware?

Tobias Hertkorn
For those not interested in building or buying their own hardware based true-RNG, you can use this free site: http://www.random.org which provides webservice, webform, RESTful, and HTTP methods for generating true random numbers using atmospheric noise data.
LBushkin
A: 

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.

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.

Jeremy Wilson