Predicting the rand() and using Cryptographic Random Numbers
Subscribe To Our Feed | Follow Us On Twitter | Get Updates on Email
Everyone must have used rand() sometime or the other while writing C code. The problem with rand() in most of the platforms is that it is easy to predict the output. Being based on unsigned int, it is just a simple function using a seed which is always the last randomly generated some number. This seed is not very tough to guess for an advanced hacker. once this seed is guessed,, any password or information based on random number generation can be easilt cracked and maligned.
following code is abridged code of rand() function implementation referenced from the book The C programming Language written by Brian Kernighan and Dennis Ritchie
unsigned long int next = 1; int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next / 65536) % 32768; }
This type of function is generally called linear congruential function. As you can notice yourself, that these type of linear congruential functions are very much predictable and are not recommended for security sensitive applications. If you look at the above given code, it is obvious that if the underlying environment does not change, then the random number generation can easily be guessed as it will generate same random number on running the application again and again.
Any type of good random number generator should adhere to three basic properties:
- Generate evenly distributed numbers
- The generated number should be unpredictable
- It should use a long cycle of range of numbers
Linear congruential functions just suffice the first property but fail miserably in the other two, thus, making themselves unusable for secure random number generation.In the early era of internet, people have used the rand() function, and hackers have exploited it at leisure.
To Solve this problem, most of the platforms support Cryptographic Random Numbers these days. For example, CryptGenRandom is provided by almost all the Windows platforms. These type of Cryptographic Random numbers are completely random as the seed used in them is also unknown to the programmer. It is completely random because it uses the system properties(system entropy) to generate the seed, which is then hashed used a hashing algorithm like SHA-1/MD4/MD5 etc. This implementation is completely platform dependent. For example: quite a few parameters used by Windows platforms are like
- Current Process ID
- Current Thread ID
- GetLocalTime()
- CPU counters
- Allocated Process Memmory at initial time
- Page Fault count
- etc etc etc….
Due to these large number of parameters and then, applying the hashing algorithms, the seed becomes almost random and unpredictable, thus, making it next to impossible to be decrypted.
Crypt Random Numbers and algorithms are part of FIPS (Federal Information Processing Standard) standard. The above mentioned function is a part of FIPS 186-2 standard.
Talking about Cryptographic Random numbers is a fairly vast topic and I would like to continue in my next post.
© Safer Code | Predicting the rand() and using Cryptographic Random Numbers
|
Liked this post? Get FREE Updates Subscribe to RSS feed |
Related posts
Tags: C, Concepts, CryptGenRandom, Cryptography, Efficiency, rand, Random Numbers, Security, security holes






Really interesting, thanks for pointing it out,as I’ve never programmed security and so I’m willing to learn some pointers.
Could you possibly include Linux/BSD/MacOS in this thing too?
Nice post though.
Very enjoyable to read.
@gedece,
Thanks a lot.
@Paul_one,
I’ll definitely add it as soon as I get some time.
http://www.zedwood.com/article/121/cpp-md5-function has a good md5 function you might be interested in.
You are missing a property that a random number generator must have: the ability to force the library reproduce random number sequences (either from the same or an earlier run).
This is indispensable during development, as it allows one to verify that a rarely occurring issue really is fixed.
Someone: No, this is just nice to have and can be useful but it is certainly no requirement. For testing you can use a PRNG with reproducable output. It isn’t possible to test your code with any possible sequence anyway. It might not even be possible to test it for each possible input value, if your code has high complexity. Basically, you shouldn’t write your code in a way that requires more than tests of corner-case to deduce that it’s correct. Easier said than done, no doubt.
By the way, rand() and cryptography is similar to drinking and driving. They don’t belong together, ever.