6

I came across an application which needs to generate a random token for each user. It is very important that each generated token is unique. Application code was as follows:

$token = md5(open_ssl_random_pseudo_bytes(64));

I don't know exactly how open_ssl_random_pseudo_bytes works or why the number "64" was chosen, nor how those bytes play together with MD5 hashing.

So how random is this token really? If the code is ran 1 billion times, will the tokens be unique?

  • If the code is ran 1 billion times, will the tokens be unique? For this something like 8 bytes would be more then enough, IF openssl_random_pseudo_bytes works correctly on your system. – Cthulhu Sep 25 '15 at 11:24
8

open_ssl_random_pseudo_bytes is a cryptographically secure pseudo random number generator (CSPRNG).

In layman's terms, this means that it can generate an unpredictable, uniformly distributed sequence, that is suitable for key generation. The unpredictable property is important, because even if the full state of the random number generator is known, an attacker cannot recreate previously generated sequences, and it is unfeasible for an external observer to guess the state in order to predict future sequences.

This is in contrast to say a random number generator that takes its seed from the number of seconds past midnight and then generates predictable sequences based on this seed. In this case an attacker can simply set their own system to generate numbers using the same seed and can effectively guess token values in order to use them for their own nefarious purposes.

64 bytes will give you 512 bits of entropy. Since MD5 outputs hashes of 128 bits, there is no advantage of having the entropy generated being greater than 128. If the code is ran one billion times then there is a statistically probable chance of it always being unique because you have an output keyspace of 2128 (3.4 * 1038). The collision rate of MD5 is about 264 which is about 18 billion billion.

  • Let's say the system uses number that gives more than 128 bits (64 for example), how does it affect collision rate? Is there a greater or smaller probability then? Or it simply doesn't matter? – Boring person Sep 25 '15 at 11:33
  • For all practical purposes I'd say it doesn't matter - you're still getting a 128 bit hash output - the chances of an accidental clash (even with MD5) on input greater than 128 bits are improbable, even though the collision resistance property of MD5 is broken. The code above looks like it is only generating an MD5 so it has a fixed length string to work with. It could simply do this with the bin2hex function over 16 bytes in order to remove the need for hashing completely. – SilverlightFox Sep 25 '15 at 13:00
  • To be exact, CSPRNG only guarantees that previous output cannot be reconstructed even if current state is known. If you know full state of any CSPRNG you can predict all future output unless that CSRPNG has additional entropy input. And in that case, the quality of output is strictly limited by quality of entropy input. Initial state / seeding or real entropy input are crusial for all CSRPNG implementations. "Random Number Generation Is Too Important to Be Left to Chance". – Mikko Rantalainen Apr 25 '16 at 6:29
  • @MikkoRantalainen: Thanks for pointing that out. Updated. – SilverlightFox May 20 '16 at 7:43
7

You should be aware of PHP bug #70014 which was pretty recent and affects the reliability of openssl_random_pseudo_bytes().

I've been working on paragonie/random_compat, which backports random_bytes() from PHP 7 into PHP 5. One of the fallbacks it supports is openssl_random_pseudo_bytes(), but if it can read directly from /dev/urandom it will prefer that instead.

1

There's another bug with openssl_random_pseudo_bytes (71915), which can result in duplicate values when you run it multiple times with the same process ID. Looks like it's fixed in 5.6.24.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.