Fastest implementation of a true random number generator in C# - c#

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?

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.

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.

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.

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.

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.

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.

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

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.

Related

Is this Guid random or guessable

I'm generating an anti-CSRF token with this code:
TokenCSRF = new Random(Guid.NewGuid().GetHashCode()).Next(1, 9999).ToString();
Is this token guessable or truly random as expected?
Edit: I replaced the token generator with this:
byte[] byt = new byte[sizeof(Int32)];
RNGCryptoServiceProvider rngCrypto = new RNGCryptoServiceProvider();
rngCrypto.GetBytes(byt);
return BitConverter.ToInt32(byt, 0);
Is this token guessable or truly random as expected?
That is the wrong question to ask.
Mike z's comment is correct. Guids are guaranteed to be unique, not random. There are different guid generation techniques, and some of them are more random than others. In particular, a guid generator is allowed to generate sequential guids. Most do not, but if you are using a guid for something other than uniqueness, you are using it off-label. I do not like doing anything off-label when security is on the line.
In particular, we have no evidence that any security professional has reviewed the code in either the guid generator or the hash generator to ensure that it has sufficient entropy to defeat an attacker. You should base your security upon tools which have been reviewed by experts.
While we are at it: the code itself is bizarre. It presumes that the hash of a guid has sufficient entropy to seed a random number generator, and then you generate a single 5 decimal digit number from that RNG. By assumption you already have a 32 bit random number in hand; why are you not using it as your random number, if it's already a source of randomness good enough to be a seed? You have a random seed that is more than large enough to be the random number you seek! Feeding it into Random is not going to make it more random.
That said, you should not be using it at all.
The right question to ask is:
What is the correct way to generate a random number for a security purpose?
Use a crypto-strength randomness generator whose on-label use is precisely that. There is one available in the .NET runtime library; use it!
Further reading:
https://blogs.msdn.microsoft.com/ericlippert/tag/guids/
Part 3 is in particular germane to your question.
GUID is guessable because part of it is identified by the machine on which it is generated, and part is the timestamp. It is nothing better than seeding current timestamp instead, which is again guessable.
If you want to generate secure tokens, you may wish to use System.Security.Cryptography.RNGCryptoServiceProvider class, or some similar method.
On a related note, do not limit your tokens to 10K values or anything that small. You would open yourself for brute force attacks. Use something like 64-bit at least and then you will be safe. If you rely on cryptographic RNG, you may wish to generate 8 or 16 bytes, then turn them to string with base-64 encoding. That sounds pretty safe to me.

How to obfuscate an integer?

From a list of integers in C#, I need to generate a list of unique values. I thought in MD5 or similar but they generates too many bytes.
Integer size is 2 bytes.
I want to get a one way correspondence, for example
0 -> ARY812Q3
1 -> S6321Q66
2 -> 13TZ79K2
So, proving the hash, the user cannot know the integer or to interfere a sequence behind a list of hashes.
For now, I tried to use MD5(my number) and then I used the first 8 characters. However I found the first collision at 51389. Which other alternatives I could use?
As I say, I only need one way. It is not necessary to be able to calculate the integer from the hash. The system uses a dictionary to find them.
UPDATE:
Replying some suggestions about using GetHashCode(). GetHashCode returns the same integer. My purpose is to hide to the end user the integer. In this case, the integer is the primary key of a database. I do not want to give this information to users because they could deduce the number of records in the database or the increment of records by week.
Hashes are not unique, so maybe I need to use encryption like TripleDes or so, but I wanted to use something fast and simple. Also, TripleDes returns too many bytes too.
UPDATE 2:
I was talking about hashes and it is an error. In reality, I am trying to obfuscate it, and I tried it using hash algorithm, that it is not a good idea because they are not unique.
Update May 2017
Feel free to use (or modify) the library I developed, installable via Nuget with:
Install-Package Kent.Cryptography.Obfuscation
This converts a non-negative id such as 127 to 8-character string, e.g. xVrAndNb, and back (with some available options to randomize the sequence each time it's generated).
Example Usage
var obfuscator = new Obfuscator();
string maskedID = obfuscator.Obfuscate(15);
Full documentation at: Github.
Old Answer
I came across this problem way back and I couldn't find what I want in StackOverflow. So I made this obfuscation class and just shared it on github.
Obfuscation.cs - Github
You can use it by:
Obfuscation obfuscation = new Obfuscation();
string maskedValue = obfuscation.Obfuscate(5);
int? value = obfuscation.DeObfuscate(maskedValue);
Perhaps it can be of help to future visitor :)
Encrypt it with Skip32, which produces a 32 bit output. I found this C# implementation but can't vouch for its correctness. Skip32 is a relatively uncommon crypto choice and probably hasn't been analyzed much. Still it should be sufficient for your obfuscation purposes.
The strong choice would be format preserving encryption using AES in FFX mode. But that's pretty complicated and probably overkill for your application.
When encoded with Base32 (case insensitive, alphanumeric) a 32 bit value corresponds to 7 characters. When encoded in hex, it corresponds to 8 characters.
There is also the non cryptographic alternative of generating a random value, storing it in the database and handling collisions.
Xor the integer. Maybe with a random key that it is generated per user (stored in session). While it's not strictly a hash (as it is reversible), the advantages are that you don't need to store it anywhere, and the size will be the same.
For what you want, I'd recommend using GUIDs (or other kind of unique identifier where the probability of collision is either minimal or none) and storing them in the database row, then just never show the ID to the user.
IMHO, it's kind of bad practice to ever show the primary key in the database to the user (much less to let users do any kind of operations on them).
If they need to have raw access to the database for some reason, then just don't use ints as primary keys, and make them guids (but then your requirement loses importance since they can just access the number of records)
Edit
Based on your requirements, if you don't care the algorithm is potentially computationally expensive, then you can just generate a random 8 byte string every time a new row is added, and keep generating random strings until you find one that is not already in the database.
This is far from optimal, and -can- be computationally expensive, but taking you use a 16-bit id and the maximum number of rows is 65536, I'd not care too much about it (the possibility of an 8 byte random string to be in a 65536 possibility list is minimal, so you'll probably be good at first or as much as second try, if your pseudo-random generator is good).

Random string vs Guid

I need a random string of 32 characters to be used as salt for hashing some value. This random string is generated per user.
What is the difference between generating a guid per user and using the RNGCryptoServiceProvider?
It's the difference between generating a unique key and generating 32 random characters. That's about it. Do what you intend to do.
If you need some way of identifying that user uniquely, even if databases are merged, use a GUID. If you need a salt for hashing a password, then use a random byte[]. Neither of them works well in the other context.
After reading this, I understood the difference
http://blogs.msdn.com/b/oldnewthing/archive/2012/05/23/10309199.aspx
GUIDs are designed to be unique, not random
The GUID generation algorithm was designed for uniqueness. It was not designed for randomness or for unpredictability. Indeed, if you
look at an earlier discussion, you can see that so-called Algorithm 1
is non-random and totally predictable. If you use an Algorithm 1 GUID
generator to assign GUIDs to candidates, you'll find that the GUIDs
are assigned in numerically ascending order (because the timestamp
increases). The customer's proposed algorithm would most likely end up
choosing for jury duty the first N people entered into the system
after a 32-bit timer rollover. Definitely not random.
Similarly, the person who wanted to use a GUID for password generation would find that the passwords are totally predictable if
you know what time the GUID was generated and which computer generated
the GUID (which you can get by looking at the final six bytes from
some other password-GUID). Totally-predictable passwords are probably
not a good idea.

Random.Next() - finding the Nth .Next()

Given a consistently seeded Random:
Random r = new Random(0);
Calling r.Next() consistently produces the same series; so is there a way to quickly discover the N-th value in that series, without calling r.Next() N times?
My scenario is a huge array of values created via r.Next(). The app occasionally reads a value from the array at arbitrary indexes. I'd like to optimize memory usage by eliminating the array and instead, generating the values on demand. But brute-forcing r.Next() 5 million times to simulate the 5 millionth index of the array is more expensive than storing the array. Is it possible to short-cut your way to the Nth .Next() value, without / with less looping?
I don't know the details of the PRNG used in the BCL, but my guess is that you will find it extremely difficult / impossible to find a nice, closed-form solution for N-th value of the series.
How about this workaround:
Make the seed to the random-number generator the desired index, and then pick the first generated number. This is equally 'deterministic', and gives you a wide range to play with in O(1) space.
static int GetRandomNumber(int index)
{
return new Random(index).Next();
}
In theory if you knew the exact algorithm and the initial state you'd be able to duplicate the series but the end result would just be identical to calling r.next().
Depending on how 'good' you need your random numbers to be you might consider creating your own PRNG based on a Linear congruential generator which is relatively easy/fast to generate numbers for. If you can live with a "bad" PRNG there are likely other algorithms that may be better to use for your purpose. Whether this would be faster/better than just storing a large array of numbers from r.next() is another question.
No, I don't believe there is. For some RNG algorithms (such as linear congruential generators) it's possible in principle to get the n'th value without iterating through n steps, but the Random class doesn't provide a way of doing that.
I'm not sure whether the algorithm it uses makes it possible in principle -- it's a variant (details not disclosed in documentation) of Knuth's subtractive RNG, and it seems like the original Knuth RNG should be equivalent to some sort of polynomial-arithmetic thing that would allow access to the n'th value, but (1) I haven't actually checked that and (2) whatever tweaks Microsoft have made might break that.
If you have a good enough "scrambling" function f then you can use f(0), f(1), f(2), ... as your sequence of random numbers, instead of f(0), f(f(0)), f(f(f(0))), etc. (the latter being roughly what most RNGs do) and then of course it's trivial to start the sequence at any point you please. But you'll need to choose a good f, and it'll probably be slower than a standard RNG.
You could build your own on-demand dictionary of 'indexes' & 'random values'. This assumes that you will always 'demand' indexes in the same order each time the program runs or that you don't care if the results are the same each time the program runs.
Random rnd = new Random(0);
Dictionary<int,int> randomNumbers = new Dictionary<int,int>();
int getRandomNumber(int index)
{
if (!randomNumbers.ContainsKey(index))
randomNumbers[index] = rnd.Next();
return randomNumbers[index];
}

Is there a method to randomize integers so that visitors can't figure out the sequence of objects

I have an id in the url. So normally it will be an auto number and so it will be 1,2,3,4,5,.....
I don't want visitors to figure out the sequence and so i want to let the number be kinda of random. So i want 1 to be converted to 174891 and 2 to 817482 and so on. But i want this to be in a specique range like 1 to 1,000,000.
I figured out i can do this using xoring and shifting of the bits of the integer. But i was wondering if this already was implemented in some place.
Thanks
You could pass your integer as the seed to a random number generator. (Just make sure that it would be unique)
You could also generate the SHA-512c hash of the integer and use that instead.
However, the best thing to do here is to use a GUID instead of an integer.
EDIT: If it needs to be reversible, the correct way to do it is to encrypt the number using AES or a different encryption algorithm. However, this won't result in a number between one and a million.
Don't rely on obscurity -- i.e., non-sequential ids -- for security. Build your app so that even if someone does guess the next id, it's still secure.
If you do need non-sequential ids, though. Generate a new id each time randomly. Store that in your table as a indexed (uniquely) column along with your autogenerated primary key id. Then all you need to do is a look up on that column to get back the real id.
EDIT: In general, I prefer tvanfosson's approach on both scores. However, here's an answer to the question as stated...
These are fairly strange design constraints, to be honest - but they're reasonably easy to deal with:
Pick an arbitrary RNG seed which you will use on every execution of your program
Create an instance of Random using that seed
Create an array of integers 1..1000000
Shuffle the array using the Random instance
Create a "reverse mapping" array by going through the original array like this:
int[] reverseMapping = new int[mapping.Length];
for (int i = 0; i < mapping.Length; i++)
{
reverseMapping[mapping[i]] = i + 1;
}
Then you can map both ways. This does rely on the algorithm used by Random not changing, admittedly... if that's a concern, you could always generate this mapping once and save it somewhere.
If you're looking for a fairly simple pseudo-random integer sequence, the linear congruential method is pretty good:
ni+1 = (a×ni + k) mod m
Use prime numbers for a and k.

Categories

Resources