Skip to content

SecureRandom security #10759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
timoh6 opened this issue Apr 22, 2014 · 6 comments
Closed

SecureRandom security #10759

timoh6 opened this issue Apr 22, 2014 · 6 comments
Labels

Comments

@timoh6
Copy link

timoh6 commented Apr 22, 2014

The SecureRandom class (from Symfony\Component\Security\Core\Util) falls back to a home made crypto construction if openssl_random_pseudo_bytes() is not available.

This should not be the case, but instead we should try to gather secure random bytes from the OS (via reading from /dev/urandom or using mcrypt_create_iv() with MCRYPT_DEV_URANDOM).

The current implementation tries to use secure random bytes from OpenSSL (before falling back to the home made construction), but this is also questionable, because of the added complexity that the OpenSSL extension has (and OpenSSL has had its share of security issues).

We should follow "the standard" and gather the random bytes straight from the OS (no need to use OpenSSL as a middleman). This way there is no added surface for implementation errors and bugs, and we can benefit from the security audits that the OS level random number generatos has had.

With that said, I suggest we update the current nextBytes() method to try first mcrypt_create_iv and then /dev/urandom. If both attempts fail, exit immediately with an error (otherwise it is probably just a false sense of security).

@timoh6
Copy link
Author

timoh6 commented Apr 22, 2014

Here is a quick mockup about secure random number generation: https://gist.github.com/timoh6/11169328

@realityking
Copy link
Contributor

I'd wager openssl is much more commonly installed than mcrypt. We'll definitively need one of these two for Windows support (BTW openssl_random_pseudo_bytes() is always available under Windows). Beyond that I don't think there's too much difference.

Maybe @ircmaxell could offer a more informed opinion.

@timoh6
Copy link
Author

timoh6 commented Apr 22, 2014

The difference between mcrypt_create_iv and openssl_random_pseudo_bytes is that mcrypt_create_iv is not a userspace CSPRNG and openssl_random_pseudo_bytes is. Ideally we should indeed avoid userspace CSPRNGs.

It is a shame there is no universal functionality in PHP core to gather secure random bytes, but we can do pretty good with mcrypt_create_iv or reading straight from /dev/urandom.

I'm not too happy to recommend the use of openssl_random_pseudo_bytes, but maybe if we must satisfy broader compatibility the openssl_random_pseudo_bytes might come to question. This needs more discussion.

@ircmaxell
Copy link
Contributor

@realityking first off, @timoh6's opinion is typically quite informed (to say the least), so ;-).

With that said, I've found that the typical case is that mcrypt/openssl support is typically pretty co-related. As in users typically have either neither or both of them installed.

The internal method that's used is actually quite significantly weak, as it only ever uses a minimal amount of entropy. See The "php security book"'s chapter on insufficient entropy. Basically, the problem comes that mt_rand() is quite predictable (it has a moderate-sized state, but without suhosin installed is seeded purely off of time, which only offers a handful of bits of actual entropy). And uniqid is the same (it's using a time based LCG, which only offers a handful of bits of actual random entropy). So at best, a complete generation of the internal system is only going to provide less than 5 bits of actual entropy per block generated as each clock read only provides approximately 2.5 bits of entropy.

That means the actual entropy contained in the "seed file" will be trivially small.

My suggestion would be to either:

  1. Throw an exception if there's no secure random source available (as in @timoh6's mockup)

OR

  1. Pull from as many possible sources as you can as I do in RandomLib. If you need to support that many systems.

As far as the "mcrypt vs openssl" debate, mcrypt is a very thin proxy over /dev/(u)random. Which is a good thing. Openssl is much more complicated internally (and was MASSIVELY broken on several operating systems for several years). I would go with mcrypt as the first option, and then fallback to openssl. (Or as I did, just use as many as possible)...

@realityking
Copy link
Contributor

Just to preemptively prevent any bad blood, I meant more informed than my opinion, not @timoh6's.

@fabpot
Copy link
Member

fabpot commented Oct 6, 2015

Closing as we are now using random_bytes (see #15875)

@fabpot fabpot closed this as completed Oct 6, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants