Hi,
I'm not a cryptographer and therefore I might be missing something
here, but I've read quite a lot about this recently and ALL sources
say that /dev/urandom is both widely used and considered safe for
cryptography. Only a select few mention that it could be a bit weaker
in specific cases, in theory.
AFAIK, that's even what every crypto-related functionality in PHP uses
for randomness, except maybe for mcrypt_create_iv() which by default
uses /dev/random, but has the option to switch. So why the 2 options?
And then there are some issues with it being an ini setting (or two) ...
Somebody mentioned that because this is sensitive, it must not be
changeable during runtime - I agree with that to some extent, but
unless I'm administrating the server:
- what if it is set to a weak source and I want to switch to a stronger?
- what if I need a non-blocking one and it is set to /dev/random?
- what's the point of default values, if they are to be somehow
detected depending on the OS?
If it was up to me, I'd just introduce a function, i.e. prng(bool
$crypto, bool $blocking) and auto-detect the strongest possible
source. Other stuff like session ID generation surely can use that
under the hood.
Regards,
Andrey Andreev.
ALL sources
say that /dev/urandom is both widely used and considered safe for
cryptography. Only a select few mention that it could be a bit weaker
in specific cases, in theory.
No urandom (and similar) are not crypto safe. Totally not. They are however
good enough for most usages but crypto safe related tasks like key
generation and the likes. Any (good) paper mentions this.
Cheers,
Pierre
ALL sources
say that /dev/urandom is both widely used and considered safe for
cryptography. Only a select few mention that it could be a bit weaker
in specific cases, in theory.No urandom (and similar) are not crypto safe. Totally not. They are however
good enough for most usages but crypto safe related tasks like key
generation and the likes. Any (good) paper mentions this.Cheers,
Pierre
So how does openssl_random_pseudo_bytes()
work without blocking then?
$ cat test.php
<?php
$crypto_strong = NULL;
$orandom = openssl_random_pseudo_bytes(32, $crypto_strong);
var_dump(bin2hex($orandom), $crypto_strong);
$mrandom = mcrypt_create_iv(32, MCRYPT_DEV_RANDOM);
var_dump($mrandom);
$ php test.php
string(64) "bc10fe2a302039bc0b1ff85b1da53d1b2dc73be515bc1ab9a4a1f8895da7357b"
bool(true)
(blocks)
If it doesn't block, it obviously doesn't use (only) /dev/random, yet
it says that the output is crypto-safe. Or is that a bug?
Cheers,
Andrey.
ALL sources
say that /dev/urandom is both widely used and considered safe for
cryptography. Only a select few mention that it could be a bit weaker
in specific cases, in theory.No urandom (and similar) are not crypto safe. Totally not. They are
however
good enough for most usages but crypto safe related tasks like key
generation and the likes. Any (good) paper mentions this.Cheers,
PierreSo how does
openssl_random_pseudo_bytes()
work without blocking then?$ cat test.php <?php $crypto_strong = NULL; $orandom = openssl_random_pseudo_bytes(32, $crypto_strong); var_dump(bin2hex($orandom), $crypto_strong); $mrandom = mcrypt_create_iv(32, MCRYPT_DEV_RANDOM); var_dump($mrandom); $ php test.php string(64)
"bc10fe2a302039bc0b1ff85b1da53d1b2dc73be515bc1ab9a4a1f8895da7357b"
bool(true)
(blocks)If it doesn't block, it obviously doesn't use (only) /dev/random, yet
it says that the output is crypto-safe. Or is that a bug?
OpenSSL uses their PRNG where /dev/urandom is used as a default source on
Unix for seeding. See
https://github.com/openssl/openssl/blob/master/e_os.h#L82
https://github.com/openssl/openssl/blob/master/crypto/rand/rand_unix.c#L246
and
https://github.com/openssl/openssl/blob/master/crypto/rand/md_rand.c
for PRNG implementation
I think that they are considering the source strong enough for seeding but
you can still add entropy if you want to. I have covered the complete
OpenSSL API in my crypto ext. See the readme in
https://github.com/bukka/php-crypto for more details (scroll down to see
the the API for Crypto\Rand class)
Regards
Jakub
So how does
openssl_random_pseudo_bytes()
work without blocking then?
Because it tells you if the result is crypto safe or not:
string openssl_random_pseudo_bytes (int $length [, bool &$crypto_strong] )
If you want only crypto safe result another function has to be used (on
opennssl).
So how does
openssl_random_pseudo_bytes()
work without blocking then?Because it tells you if the result is crypto safe or not:
string openssl_random_pseudo_bytes (int $length [, bool &$crypto_strong]
)If you want only crypto safe result another function has to be used (on
opennssl).
That's not the way how it works in md_rand. The ssleay_rand_pseudo_bytes
(Rand_psedobytes called in openssl_random_pseudo_bytes) is just a wrapper
for ssleay_rand_bytes with pseudo flag set to 1. ssleay_rand_bytes first
calls Rand_poll that adds the entropy. The thing is that the entropy is
taken from /dev/urandom on Unix. It means you will always have enough
entropy on Linux and the functions returns 1 ($crypto_strong is set to
true). You won't get false on Linux though. The reason of the flag in
OpenSSL is if you run it in on some platform that can't provide enough
entropy which is not the case on Linux. Please see the sources for more
details.
Thanks
Jakub
So how does
openssl_random_pseudo_bytes()
work without blocking then?Because it tells you if the result is crypto safe or not:
string openssl_random_pseudo_bytes (int $length [, bool &$crypto_strong]
)If you want only crypto safe result another function has to be used (on
opennssl).
And my test.php that was pasted shows that it dumps TRUE
for
$crypto_strong, while mcrypt_create_iv() blocks.
That's not the way how it works in md_rand. The ssleay_rand_pseudo_bytes
(Rand_psedobytes called in openssl_random_pseudo_bytes) is just a wrapper
for ssleay_rand_bytes with pseudo flag set to 1. ssleay_rand_bytes first
calls Rand_poll that adds the entropy. The thing is that the entropy is
taken from /dev/urandom on Unix. It means you will always have enough
entropy on Linux and the functions returns 1 ($crypto_strong is set to
true). You won't get false on Linux though. The reason of the flag in
OpenSSL is if you run it in on some platform that can't provide enough
entropy which is not the case on Linux. Please see the sources for more
details.
Sorry, I'm not really sure what this means, but 2 few bits that I spot are:
- on UNIX(-like), it uses /dev/urandom
- $crypto_strong will always be true on Linux (UNIX-whatever)
And Pierre Joye says that /dev/urandom is not crypto-safe, so this
kind of gets us in a conflict ... which one is it?
The way I understand it, only /dev/whatever (meaning that it should be
hardware input) could be considered crypto-safe and so if OpenSSL
always returns without blocking, yet sets $crypto_strong to TRUE, then
the same should be possible for PHP itself to do.
That is, unless $crypto_strong is set to TRUE
without the output
actually being crypto-safe, in which case we have a bug.
P.S.: Sorry folks, I didn't want to turn this into a "how OpenSSL works" thread.
Cheers,
Andrey.
On Fri, Feb 14, 2014 at 1:53 PM, Pierre Joye pierre.php@gmail.com
wrote:So how does
openssl_random_pseudo_bytes()
work without blocking then?Because it tells you if the result is crypto safe or not:
string openssl_random_pseudo_bytes (int $length [, bool
&$crypto_strong]
)If you want only crypto safe result another function has to be used (on
opennssl).And my test.php that was pasted shows that it dumps
TRUE
for
$crypto_strong, while mcrypt_create_iv() blocks.That's not the way how it works in md_rand. The ssleay_rand_pseudo_bytes
(Rand_psedobytes called in openssl_random_pseudo_bytes) is just a wrapper
for ssleay_rand_bytes with pseudo flag set to 1. ssleay_rand_bytes first
calls Rand_poll that adds the entropy. The thing is that the entropy is
taken from /dev/urandom on Unix. It means you will always have enough
entropy on Linux and the functions returns 1 ($crypto_strong is set to
true). You won't get false on Linux though. The reason of the flag in
OpenSSL is if you run it in on some platform that can't provide enough
entropy which is not the case on Linux. Please see the sources for more
details.Sorry, I'm not really sure what this means, but 2 few bits that I spot are:
- on UNIX(-like), it uses /dev/urandom
It uses /dev/urandom for seeding PRNG. It means that it reads only 32 bytes
(256 bits) from it. If you call openssl_random_pseudo_bytes you will get
bytes generated by PRNG
- $crypto_strong will always be true on Linux (UNIX-whatever)
Yes. The reason is that /dev/urandom is non-blocking and you will always
get enough entropy from it. You don't have to check the flag on Linux
because it will be always true!
The point is that OpenSSL considers /dev/urandom strong enough for seeding
CSPRNG.
Jakub
The point is that OpenSSL considers /dev/urandom strong enough for
seeding CSPRNG.
The point here is about whether /Dev/urandom is cs or not. It is not. It
may be (on recent updated systems) enough to be used as seed but not to
actually generate cs random data.
Also it is important to keep mind that openssl does more than simply read
from urandom or random to generate data. That's outside the scope of what
is proposed here.
Cheers,
Pierre
Hi,
It uses /dev/urandom for seeding PRNG. It means that it reads only 32 bytes
(256 bits) from it. If you call openssl_random_pseudo_bytes you will get
bytes generated by PRNG
- $crypto_strong will always be true on Linux (UNIX-whatever)
Yes. The reason is that /dev/urandom is non-blocking and you will always
get enough entropy from it. You don't have to check the flag on Linux
because it will be always true!The point is that OpenSSL considers /dev/urandom strong enough for seeding
CSPRNG.Jakub
There are the three categories:
- Non-Cryptographically Deterministic PRNG
- Entropy Input PRNG
- Cryptographically Secure PRNG
OpenSSL is the second. /dev/urandom is also the second. /dev/random is
the third (after a warmup period!). Something like rand()
would be in
the first under the assumption that time is predictable.
Those are the technical categories anyway... In reality, you can use a
non-CSPRNG for cryptographic needs over the short term. If you can't,
it means the damn thing is broken ;). If you have something like a
long term or high value cryptographic product, you wont want to stint
on entropy and you won't want to run afoul of any future issue with
the entropy collection or mixing, and you're probably not going to
even use a machine remotely susceptible in inactivity (which may limit
the entropy sources).
Be careful of taking claims at face value where definitions are in doubt.
Paddy
--
Pádraic Brady
http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team
Zend Framework PHP-FIG Representative
On Sat, Feb 15, 2014 at 11:59 AM, Pádraic Brady padraic.brady@gmail.comwrote:
Hi,
It uses /dev/urandom for seeding PRNG. It means that it reads only 32
bytes
(256 bits) from it. If you call openssl_random_pseudo_bytes you will get
bytes generated by PRNG
- $crypto_strong will always be true on Linux (UNIX-whatever)
Yes. The reason is that /dev/urandom is non-blocking and you will always
get enough entropy from it. You don't have to check the flag on Linux
because it will be always true!The point is that OpenSSL considers /dev/urandom strong enough for
seeding
CSPRNG.Jakub
There are the three categories:
- Non-Cryptographically Deterministic PRNG
- Entropy Input PRNG
- Cryptographically Secure PRNG
OpenSSL is the second. /dev/urandom is also the second. /dev/random is
the third (after a warmup period!). Something likerand()
would be in
the first under the assumption that time is predictable.Those are the technical categories anyway... In reality, you can use a
non-CSPRNG for cryptographic needs over the short term. If you can't,
it means the damn thing is broken ;). If you have something like a
long term or high value cryptographic product, you wont want to stint
on entropy and you won't want to run afoul of any future issue with
the entropy collection or mixing, and you're probably not going to
even use a machine remotely susceptible in inactivity (which may limit
the entropy sources).Be careful of taking claims at face value where definitions are in doubt.
Paddy
Thanks for the explanation. It makes sense.
I thought that they considers the PRNG as Cryptographically Secure because
the documentation states that it produces cryptographically strong
pseudo-random bytes
http://www.openssl.org/docs/crypto/RAND_bytes.html
(RAND_bytes is equal to RAND_pseudo_bytes on Linux)
Jakub
So how does
openssl_random_pseudo_bytes()
work without blocking then?Because it tells you if the result is crypto safe or not:
string openssl_random_pseudo_bytes (int $length [, bool
&$crypto_strong] )If you want only crypto safe result another function has to be used (on
opennssl).That's not the way how it works in md_rand. The ssleay_rand_pseudo_bytes
(Rand_psedobytes called in openssl_random_pseudo_bytes) is just a wrapper
for ssleay_rand_bytes with pseudo flag set to 1. ssleay_rand_bytes first
calls Rand_poll that adds the entropy. The thing is that the entropy is
taken from /dev/urandom on Unix. It means you will always have enough
entropy on Linux and the functions returns 1 ($crypto_strong is set to
true). You won't get false on Linux though. The reason of the flag in
OpenSSL is if you run it in on some platform that can't provide enough
entropy which is not the case on Linux. Please see the sources for more
details.
I referred to the php function. You have to check this arg if you need
crypto safe.
Jakub