Hi, I'm new to this list so please tolerate my unfamiliarity with
protocol.
PHP does not in general allow access to the underlying system¹s
entropy source. I think it would be a good idea if it did.
It is routine for web developers to write code in PHP that stores
passwords in database tables or other persistent stores. In these
cases a one-way hash is generally used (and PHP¹s crypt()
is very
good here). In such schemes, the password must be salted to
protect against known hash lookups. But the salt must be a
cryptographically secure random value. (This is just one
example of when a CS random value is needed, but a very common
one.)
I recently attempted to write a function in PHP that would return
CS random bytes from the system¹s entropy source. I was unable to
do it.
-
/dev/random and /dev/urandom are unavailable on Windows and
cannot befopen()
¹ed in safe mode on *nix/nux -
openssl_random_pseudo_bytes()
requires openssl extension
installed and enabled. Most of the popular AMP packages for
Windows fail on this count. Many shared web hosts don¹t have it
either. -
mcrypt_create_iv() depends on mcrypt extension and so suffers
similar problems as openssl -
Another method is to set runtime config param
session.entropy_length followed by @session_start();
session_regenerate_id()
; after whichsession_id()
will return a
CS random string, but this is also foiled by safe mode. -
On Windows you could try COM('CAPICOM.Utilities.1')->GetRandom
but that API is obsolescent and not in many default Windows
installs. -
Last chance is new DOTNET('mscorlib',
'System.Security.Cryptography.RNGCryptoServiceProvider') etc
requires a working and compatible .NET framework.
At this point the best bet is probably to hash some bytes from
mt_rand()
with microtime()
and return that but trigger a warning
about security. This is a very poor substitute.
And given the routine need for CS random numbers in PHP
applications, it is, in my view, not satisfactory.
My proposal is to put a new function into basic_functions along
side mt_rand()
. I suggest naming it cs_rand(), cs being mnemonic
for crypto secure. It should appear in the same sections of the
manual as mt_rand()
and rand()
and both of those manual entries
should call out the fact that they are not crypto secure and refer
to cs_rand().
I propose an implementation broadly similar to mcrypt_create_iv(),
see php-5.3.8/ext/mcrypt/mcrypt.c lines 1373 thru 1434. (Even
though I haven¹t programmed in C since the 1980s, this doesn¹t
look hard.)
But I suggest a different signature. openssl_random_pseudo_bytes()
is a better model. mcrypt_create_iv()¹s $source argument should be
avoided, it just confuses the user.
openssl_random_pseudo_bytes()
¹s &$crypto_strong response is
valuable. I would also consider triggering a PHP warning when a
non-crypto strong value is returned.
I would be happy to help with the work. I¹m not sure I¹d do a good
job with the implementation because I haven¹t programmed inside
PHP before while an experienced internist could do it very
quickly. But I may be able to help with test cases and
documentation.
Warm regards
Tom
Tom,
First off, very detailed post! However, there are a few things I'd
disagree with.
- Salts for
crypt()
purposes need to be cryptographically secure
random numbers.
This is not true. The only requirement is that a salt be reasonably
unique (meaning that the chance of using the same one is pretty low
for the scale of the application. See this:
http://security.stackexchange.com/a/7195
CS random salts are needed for certain signing algorithms. But not
for password storage.
Now, there is a need for CS Random numbers in general. Things like
key generation (which shouldn't be done in PHP to begin with), Nonces
and One-Time Pads require secure random numbers. But in general, most
uses in PHP would suffice with a normal quality PRN.
- I was unable to do it.
I did it fine.
https://github.com/ircmaxell/PHP-CryptLib/tree/master/lib/CryptLib/Random
It's an RFC4086 compliant CSPRNG
(http://tools.ietf.org/html/rfc4086#section-5.2). It uses multiple
sources to generate the final number, and mixes them together using
cryptographically secure methods. Sure, in a perfect storm situation
(Linux, Safe Mode, without OpenSSL, without MCrypt, etc) it would only
use mt_rand()
+ rand()
+ uniqid()
+ microtime()
, which is still pretty
secure (in the sense that both bias and predictability are both
virtually non-existent due to the mixing step).
- My proposal is to put a new function into basic_functions along
sidemt_rand()
. I suggest naming it cs_rand()
I would be against this proposal. CS random numbers are something
that shouldn't be over used. Otherwise you can wind up either running
out of entropy on the system (causing blocking while more is
"gathered") or reducing the quality of the random numbers. I don't
think normal developers understand the difference and when each is
required.
I would be for a proposal to add a salt generation function though
(similar to BCrypt.gensalt()).
Thanks,
Anthony
Hi, I'm new to this list so please tolerate my unfamiliarity with
protocol.PHP does not in general allow access to the underlying system¹s
entropy source. I think it would be a good idea if it did.It is routine for web developers to write code in PHP that stores
passwords in database tables or other persistent stores. In these
cases a one-way hash is generally used (and PHP¹scrypt()
is very
good here). In such schemes, the password must be salted to
protect against known hash lookups. But the salt must be a
cryptographically secure random value. (This is just one
example of when a CS random value is needed, but a very common
one.)I recently attempted to write a function in PHP that would return
CS random bytes from the system¹s entropy source. I was unable to
do it.
/dev/random and /dev/urandom are unavailable on Windows and
cannot befopen()
¹ed in safe mode on *nix/nux
openssl_random_pseudo_bytes()
requires openssl extension
installed and enabled. Most of the popular AMP packages for
Windows fail on this count. Many shared web hosts don¹t have it
either.mcrypt_create_iv() depends on mcrypt extension and so suffers
similar problems as opensslAnother method is to set runtime config param
session.entropy_length followed by @session_start();
session_regenerate_id()
; after whichsession_id()
will return a
CS random string, but this is also foiled by safe mode.On Windows you could try COM('CAPICOM.Utilities.1')->GetRandom
but that API is obsolescent and not in many default Windows
installs.Last chance is new DOTNET('mscorlib',
'System.Security.Cryptography.RNGCryptoServiceProvider') etc
requires a working and compatible .NET framework.At this point the best bet is probably to hash some bytes from
mt_rand()
withmicrotime()
and return that but trigger a warning
about security. This is a very poor substitute.And given the routine need for CS random numbers in PHP
applications, it is, in my view, not satisfactory.My proposal is to put a new function into basic_functions along
sidemt_rand()
. I suggest naming it cs_rand(), cs being mnemonic
for crypto secure. It should appear in the same sections of the
manual asmt_rand()
andrand()
and both of those manual entries
should call out the fact that they are not crypto secure and refer
to cs_rand().I propose an implementation broadly similar to mcrypt_create_iv(),
see php-5.3.8/ext/mcrypt/mcrypt.c lines 1373 thru 1434. (Even
though I haven¹t programmed in C since the 1980s, this doesn¹t
look hard.)But I suggest a different signature.
openssl_random_pseudo_bytes()
is a better model. mcrypt_create_iv()¹s $source argument should be
avoided, it just confuses the user.
openssl_random_pseudo_bytes()
¹s &$crypto_strong response is
valuable. I would also consider triggering a PHP warning when a
non-crypto strong value is returned.I would be happy to help with the work. I¹m not sure I¹d do a good
job with the implementation because I haven¹t programmed inside
PHP before while an experienced internist could do it very
quickly. But I may be able to help with test cases and
documentation.Warm regards
Tom
- /dev/random and /dev/urandom are unavailable on Windows and
cannot befopen()
¹ed in safe mode on *nix/nux
Safe mode has been deprecated for two and a half years.. Adding features to
work around its limitations is (IMO) a bad idea..
Can't argue with it being unavailable on windows..
openssl_random_pseudo_bytes()
requires openssl extension
installed and enabled. Most of the popular AMP packages for
Windows fail on this count. Many shared web hosts don¹t have it
either.
As far as I remember, WAMP Server (Arguably the most popular AMP package
for windows) does include openssl support. Its simply disabled by default
like everything else! Some quick googling seems to confirm this..
Some more googling confirms XAMPP also includes OpenSSL out of the box..
- mcrypt_create_iv() depends on mcrypt extension and so suffers
similar problems as openssl
mcrypt again comes with both WAMP and XAMPP servers, but disabled by
default.
- Another method is to set runtime config param
session.entropy_length followed by @session_start();
session_regenerate_id()
; after whichsession_id()
will return a
CS random string, but this is also foiled by safe mode.
This is obviously not a solution, even if it worked... ;)
- On Windows you could try COM('CAPICOM.Utilities.1')->GetRandom
but that API is obsolescent and not in many default Windows
installs.
I can't speak for windows specific APIs So I'm going to ignore the rest!
It seems that the two preferable cross platform options (openssl and
mcrypt) are already both widely available on all platforms, I'm not sure I
see the need to be honest.
Kiall
hi,
Some short comments:
PHP does not in general allow access to the underlying system¹s
entropy source. I think it would be a good idea if it did.
It does on unix using the almost generally available random and
urandom. On Windows you can use the openssl_random_pseudo_bytes
function which does not rely on the OpenSSL API but the Windows native
Crypto APIs.
- /dev/random and /dev/urandom are unavailable on Windows and
cannot befopen()
¹ed in safe mode on *nix/nux
Well, bad admins forgot to allow access to these files. Maybe we
should add that to the documentations.
openssl_random_pseudo_bytes()
requires openssl extension
installed and enabled. Most of the popular AMP packages for
Windows fail on this count. Many shared web hosts don¹t have it
either.
See my previous comment about windows.
For shared hosts not providing openssl, I would suggest (strongly) to
look for better hosting solutions.
- mcrypt_create_iv() depends on mcrypt extension and so suffers
similar problems as openssl
How so? The entropy source on windows is the same than the one in
openssl and uses the windows crypto API.
- Another method is to set runtime config param
session.entropy_length followed by @session_start();
session_regenerate_id()
; after whichsession_id()
will return a
CS random string, but this is also foiled by safe mode.
Btw, entropy src on windows benefits from the same implementation than
mcrypt and openssl.
- On Windows you could try COM('CAPICOM.Utilities.1')->GetRandom
but that API is obsolescent and not in many default Windows
installs.
That's what the random bytes function uses. Or to be more exact,
CAPICOM uses the same same underlying API.
- Last chance is new DOTNET('mscorlib',
'System.Security.Cryptography.RNGCryptoServiceProvider') etc
requires a working and compatible .NET framework.
Same comment as in pt. 5
At this point the best bet is probably to hash some bytes from
mt_rand()
withmicrotime()
and return that but trigger a warning
about security. This is a very poor substitute.
They are by no way crypto safe. Openssl's random function on unix can
fail to be crypto safe as well. On windows, it is always crypto safe.
Cheers,
Pierre
@pierrejoye | http://blog.thepimp.net | http://www.libgd.org