Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What makes openssl_random_pseudo_bytes "cryptographically secure"?

I've always been told that I should use openssl_random_pseudo_bytes when giving passwords a salt.

But what I would really love to know, is what makes it cryptographically secure. What is the internal difference between rand, mt_rand and openssl_random_pseudo_bytes?

Thanks in advance.

like image 321
thephpdev Avatar asked Dec 14 '14 15:12

thephpdev


1 Answers

The differences are in short:

  • rand uses the libc random number generator (source), which depends on the system and is usually not cryptographically secure
  • mt_rand uses a known algorithm, the Mersenne Twister, hence the name; this is a fast algorithm that produces well distributed but not cryptographically-secure randoms
  • openssl_random_pseudo_bytes directly calls the OpenSSL system for cryptographically-secure randoms (but see the warning in the full description)

The properties are also listed in the table below:

enter image description here

rand

For rand it is stated in mt_rand:

Many random number generators of older libcs have dubious or unknown characteristics and are slow.

So for rand you'll have to take a look at your libc to figure out which random is actually used. It's stated on the Mersenne Twister site that it should have comparable speed nowadays, but it's characteristics depends on the system. It doesn't state how it is seeded either, meaning that you could use it for a game or such, but not for much else.

mt_rand

The Mersenne Twister is a well known algorithm that produces rather well distributed random numbers. It has a very long period, which means that it takes a long time before a previous state is encountered (if this happens it stays in loop, the size of the loop is called the period). MT is not secure because it is possible to reconstruct its secure state given enough data. This means that if you first generate a key, and then use the algorithm for something else, then an attacker may recreate the key given enough output. Furthermore, a non-secure seed as the system time is used upon creation.

openssl_random_pseudo_bytes

OpenSSL's random number generator is usually cryptographically secure (see note below); this means that it is not possible to re-calculate the internal state given the output of the generator.

OpenSSL's pseudo random number generator is constructed using a hash function, currently MD5, which should still be secure for generating random numbers. It is well distributed and - like the MT algorithm - has a high period. OpenSSL's rand is much slower than MT, but it should still get a rather good speed.

It has the advantage over OS random number generators that it does not need additional threads or system calls. OpenSSL uses the operating system random number generator (+ possible other sources) to create the initial seed. The OS random generators are normally the best possible random number generators available, as the OS has access to sources of entropy not directly available to libraries and applications.

Warning: on the Wiki of OpenSSL it is stated that:

RAND_pseudo_bytes returns pseudo-random bytes which can be cryptographically strong. The function returns 1 if the bytes are cryptographically strong, and 0 otherwise. If your application has high integrity requirements, it should not use RAND_pseudo_bytes.

Which is reflected by the PHP function:

If passed into the function, this will hold a boolean value that determines if the algorithm used was "cryptographically strong", e.g., safe for usage with GPG, passwords, etc. TRUE if it did, otherwise FALSE

This means it may still be insecure for e.g. long term keys.

Warning #2: additional insight shows that the PRNG of OpenSSL may not always be secure regardless of the return value. So additional care should be taken before choosing OpenSSL.

like image 98
Maarten Bodewes Avatar answered Nov 04 '22 13:11

Maarten Bodewes