1

I need to generate random numbers for a student homework in cryptography.

At first I wanted to use

srand(time(NULL));
int r = rand();

But I read that shouldn't use it for cryptography. I'd like if possible to not write my own pseudo-random number generator.

What is the fastest/easiest way to generate pseudo-random numbers in C for cryptographic purposes?

I'm on Linux and I don't mind if the answer isn't cross-platform.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Olivier Lasne
  • 679
  • 6
  • 12
  • 2
    Read from /dev/urandom – paj28 Apr 12 '14 at 14:17
  • 3
    This is a trick question. There are easy ways and there are good ways but there no good easy ways. A cryptographic RNG is __hard__. – david.pfx Apr 12 '14 at 14:18
  • Unless there are demands being made on your solution that you've not mentioned, using `/dev/random` is likely to be good enough for student homework, whereas using `srand(time)` (and, indeed, `rand()`) is not. – Jonathan Leffler Apr 12 '14 at 14:23
  • @JonathanLeffler Please write that as an answer so that the current only “answer” does not get accepted through unfamiliarity with StackOverflow. – Pascal Cuoq Apr 12 '14 at 15:12
  • @JonathanLeffler Bad idea, you should not be using `/dev/random` directly if you only want pseudo random numbers. `/dev/random` provides entropy gathered by the system to feed other PRNG's, it is not a good idea for a application to use it directly (as it may block and therefore stall not just your application but others as well). Use `/dev/urandom` instead or use a well seeded PRNG within a cryptographic library. – Maarten Bodewes Apr 12 '14 at 15:28
  • @david.pfx PRNG methods are well known. Testing the implementation is very tricky however and getting enough entropy can be tricky as well, especially without OS support. – Maarten Bodewes Apr 12 '14 at 15:31
  • @owlstead: Agreed, but a quick answer for a student project that will meet cryptographic standards? What do you choose? Why? – david.pfx Apr 12 '14 at 15:40
  • `/dev/urandom` can be used directly by implementations instead. It won't block and will not deplete `/dev/random` so easily. For the rest, see my answer, – Maarten Bodewes Apr 12 '14 at 15:44
  • 1
    On Linux, `/dev/random` is basically intended for seed material, while `/dev/urandom` is a ready-to-use PRNG. On other platforms (say, FreeBSD or OS X), they are the same (one is simply symlinked to the other). – ntoskrnl Apr 12 '14 at 16:42

2 Answers2

3

There is no cross-platform solution. On Linux, read from /dev/urandom (with fread, or with read if you have a taste for complexity). The bytes read from /dev/urandom are suitable for cryptographic use except from a freshly-started embedded system or server lacking entropy.

The documentation is overly conservative (stemming from a theoretical notion of security where the attacker has infinite computation power rather than merely the use of all the computers int he world); in most situations, it is perfectly fine to use /dev/urandom to generate cryptographic keys.

If you need to generate a lot of random bytes, you may want to implement a pseudo-random number generator inside your code, and use /dev/urandom only to seed it with entropy. If you're just generating a few keys and similar small amounts of material, or if you need to generate a lot of random numbers but the speed of /dev/urandom isn't a bottleneck, or if this is a school exercise and implementing a PRNG is not the point of the exercise, then just reading from /dev/urandom is fine.

Community
  • 1
  • 1
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
2

Only having a Pseudo Random Number Generator is not enough. You need to seed it with enough entropy to start it up. You do this by setting a seed generally retrieved from one of the operating system calls. Which one you should use depends on the method that you use it. You can mix in seed later if you want even higher quality random numbers.

For Linux systems: /dev/random returns the most entropy, /dev/urandom is itself a seeded PRNG and may be used directly by applications. /dev/random however blocks if not enough entropy is available, I would advice /dev/urandom for most purposes. Reading too much from /dev/random/ can bring down an entire machine as anything that requests entropy from it may stall. On other operating systems both /dev/random /dev/urandom simply link to a seeded PRNG.

For Windows take a look at this article on MSDN.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Added another answer, I read that you wanted to program your own PRNG, apologies. Removed Java SHA1PRNG sample code. Rest of answer is still valid, although I would recommend OpenSSL for as an API instead. – Maarten Bodewes Apr 12 '14 at 18:30
  • I've deleted my other post because of the continuing problems with OpenSSL. – Maarten Bodewes Apr 14 '14 at 00:48