- Will the OpenSSL ext remain as it currently stands?
There has been talk of replacing it with a more generic implementation that
can swap out the underlying components so we aren't dependent upon a single
library. The crypto extension in pecl is working on such an approach, but
AFAIK it's not yet stable. That said, ext/openssl already delegates to
Windows API functions to provide equivalent functionality as needed, so
this is already happening to some extent. Additionally, for better or worse
ext/openssl is tightly integrated into the current streams implementation
when crypto is required (i.e. the ssl stream wrapper). Any new solution
would need to provide equivalent functionality.
- What does
openssl_random_pseudo_bytes()
really do in PHP?
It's less about what it does in PHP and more about what it does in the
openssl lib itself with the exception being Windows environments.
In Windows
This function delegates to CryptGenRandom() which uses the general
system-wide RNG. It is possible for an application to add its own data to
the further randomize the internal seed, however, the current
openssl_random_pseudo_bytes()
does not expose this capability to userland.
Elsewhere
Openssl transparently seeds its entropy pool. Once the pool has been seeded
with enough data it will always have sufficient data to ensure an
unpredictable byte sequence is returned. So it now becomes a matter of
whether or not it has enough entropy at the time of your call to
openssl_random_pseudo_bytes()
.
Openssl actually exposes two separate APIs for this case, so let me explain
what each does:
- RAND_bytes()
Always return an error if there is insufficient data in the pool to ensure
unpredictability.
- RAND_pseudo_bytes()
Always return bytes, even if the entropy pool has not been sufficiently
seeded.
Currently PHP's openssl_random_pseudo_bytes()
uses the latter function and
allows users to pass a by-reference $crypto_strong out parameter to
determine if the result is cryptographically strong. This is fine if you
know all of the above and have read the manual for this function. However,
it may be desirable to add a new openssl_rand_bytes() function that uses
RAND_bytes() under the hood to make it less likely for someone to
accidentally use insufficiently random output. I don't think there would be
an analog to this functionality in Windows as the documentation for
CryptGenRandom() makes no mention of when/if this API can return a sequence
of bytes that is not cryptographically secure. So, a new
openssl_random_bytes() might only amount to an alias of the existing
openssl_random_pseudo_bytes()
function in this environment. Please provide
feedback if you think a new function should be added as this is a
relatively straightforward thing to do.
I would also like to propose a new optional $additionalSeed string
parameter that could be passed from userland to include in the entropy pool
since both the underlying Windows and Openssl APIs support this
functionality.
"Feature Freeze" for PHP 7 is coming soon. I, for one, would value a
summary of what's happening in PHP 7 with respect to security topics
like but not limited to these.
FYI I still plan to add both client-side and server-side support for OCSP
verification in encrypted streams. The other thing I plan to do is add
support for the (relatively new) TLSALPN extension in encrypted
client/server streams. This extension is required to establish encrypted
connections using the forthcoming h2 (HTTP/2.0) protocol.
Currently PHP's
openssl_random_pseudo_bytes()
uses the latter function and
allows users to pass a by-reference $crypto_strong out parameter to
determine if the result is cryptographically strong. This is fine if you
know all of the above and have read the manual for this function. However,
it may be desirable to add a new openssl_rand_bytes() function that uses
RAND_bytes() under the hood to make it less likely for someone to
accidentally use insufficiently random output.
Hi Daniel,
Just to clarify: OpenSSL automatically seeds its random pool from
crypto-safe system-specific sources (/dev/[u]random on Linux): it is just
impossible on modern systems to end up in the case of not having enough
entropy.
Damien
Thanks Damien and Daniel for the info.
I am not concerned about running out of entropy. I am concerned about
userspace RNGs such as OpenSSL
http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
Currently PHP's
openssl_random_pseudo_bytes()
uses the latter function
and
allows users to pass a by-reference $crypto_strong out parameter to
determine if the result is cryptographically strong. This is fine if you
know all of the above and have read the manual for this function.
However,
it may be desirable to add a new openssl_rand_bytes() function that uses
RAND_bytes() under the hood to make it less likely for someone to
accidentally use insufficiently random output.Hi Daniel,
Just to clarify: OpenSSL automatically seeds its random pool from
crypto-safe system-specific sources (/dev/[u]random on Linux): it is just
impossible on modern systems to end up in the case of not having enough
entropy.Damien
Thanks Damien and Daniel for the info.
I am not concerned about running out of entropy. I am concerned about
userspace RNGs such as OpenSSL
http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
Just to be clear (as Damien also mentioned): openssl is not a userspace
RNG. It uses the underlying system-specific resources. If your system's RNG
is good enough (/dev/[u]random in nix-like systems) for you,
openssl_random_pseudo_bytes()
is good enough for you.
Thanks Damien and Daniel for the info.
I am not concerned about running out of entropy. I am concerned about
userspace RNGs such as OpenSSL
http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/Just to be clear (as Damien also mentioned): openssl is not a userspace
RNG.
OpenSSL has an RNG that is not in the kernel memory space. Software that
is
in memory but not in the kernel space is in the user space.
Thanks Damien and Daniel for the info.
I am not concerned about running out of entropy. I am concerned about
userspace RNGs such as OpenSSL
http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/Just to be clear (as Damien also mentioned): openssl is not a userspace
RNG.OpenSSL has an RNG that is not in the kernel memory space. Software that
is
in memory but not in the kernel space is in the user space.
You're right, my mistake. I don't claim to be a crypto expert in any sense
of the word -- I simply implement APIs that real crypto experts create. I
don't believe it makes any sense for us to implement this in php-src
directly.
If you haven't compiled openssl with a different RNG engine it's going to
default to use RAND_SSLeay(). The explanation here explains the logic
involved:
https://www.openssl.org/docs/crypto/rand.html#internals
Dr. Henson is far smarter than I am; I'll take his word for it. The only
outstanding issue noted in the linked discussion is "An initial source of
random 'state'" which, as you can see by reading the subsequent RAND_add()
documentation is transparently retrieved from /dev/urandom for us:
On systems that provide /dev/urandom, the randomness device is used to
seed the PRNG transparently. However, on all other systems, the
application is responsible for seeding the PRNG by calling RAND_add()
If you're in Windows this is handled by a different API. And if not, I tend
to trust the openssl PRNG since it pulls its initial random state from
/dev/urandom. I honestly don't see the problem here. I'm happy to be wrong
if someone says, "no, we should come up with a different way to do this,"
and can provide logic to back that up. Personally, I have no reason to
believe the openssl implementation is inadequate. We could add the ability
to pass in your own initialization data but the only good option there is
pulling it from fread()
on /dev/urandom anyway ... a somewhat pointless
exercise as openssl already does this.