Reputation: 507
I am developing a site in php 5.4 and i was wondering which is better to use to gen a random salt for password security?
$salt = sha1(openssl_random_pseudo_bytes(23));
or
$seed = '';
$a = @fopen('/dev/urandom','rb');
$seed .= @fread($a,23);
$salt = sha1(seed);
or should i just go with:
$salt = openssl_random_pseudo_bytes(40);
or
$salt = '';
$a = @fopen('/dev/urandom','rb');
$salt .= @fread($a,23);
Upvotes: 9
Views: 10631
Reputation: 121
I know this is an old post but if anyone stumbles into this here is an easy solution:
compat_random.php
https://gist.github.com/anzz1/29a787fac8ef6d693b41779911287505
<?php
require_once(dirname(__FILE__) . '/compat_random.php');
$salt = random_bytes(40);
?>
Done.
The compat_random.php is only 2KB, 62 lines of code.
You should be able to use it with any PHP version.
It checks for these functions in this order:
It's very likely you do have one of these available, but if you do not, it will fall finally fall back to
Upvotes: 0
Reputation: 18960
For security purposes you are better off using openssl_random_pseudo_bytes
. OpenSSL takes care of gathering enough entropy to serve you good randomness. /dev/urandom
is devised to never block and could be tricked into giving you not so random bytes.
With random bytes you do not need to run them through SHA1.
To sum it all, do:
$salt = openssl_random_pseudo_bytes(40, $cstrong);
if (! $cstrong) {
exit('This should not happen');
}
Upvotes: 10
Reputation: 50368
In practice, there is almost certainly no difference.
Both openssl_random_pseudo_bytes
and /dev/urandom
provide a cryptographically secure source of pseudorandom bytes. Neither is guaranteed to be truly random, but in practice, both are expected to be indistinguishable from true randomness by any known or foreseeable techniques.
Kmkaplan is technically correct in noting that /dev/urandom
could return theoretically predictable output under certain conditions, as noted in man unrandom
:
"A read from the /dev/urandom device will not block waiting for more entropy. As a result, if there is not sufficient entropy in the entropy pool, the returned values are theoretically vulnerable to a cryptographic attack on the algorithms used by the driver. Knowledge of how to do this is not available in the current unclassified literature, but it is theoretically possible that such an attack may exist. If this is a concern in your application, use /dev/random instead."
However, the same is actually true of openssl_random_pseudo_bytes
(which calls the OpenSSL function RAND_pseudo_bytes
internally), as noted in the OpenSSL documentation:
"
RAND_pseudo_bytes()
puts num pseudo-random bytes into buf. Pseudo-random byte sequences generated byRAND_pseudo_bytes()
will be unique if they are of sufficient length, but are not necessarily unpredictable. They can be used for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation etc."
Neither of these warnings should actually scare you from using these methods — the weaknesses they describe are only theoretical, except possibly under certain contrived circumstances (such as on a diskless embedded device with no hardware RNG immediately after boot-up), and should not be of practical concern in situations where PHP is normally deployed.
The upshot is, neither of these random number generation methods is going to be the weakest link in your cryptosystem, so you can safely choose either one. If you're feeling paranoid, you could even use both.
Ps. One advantage of openssl_random_pseudo_bytes
is that it works on Windows, too. On the other hand, /dev/urandom
is available on Unix even if the OpenSSL PHP extension is not installed. Thus, for maximum portability, you should indeed implement support for both.
Also, always check that you indeed received as many bytes as you expected; for example, the /dev/urandom
based code in your question above could silently return an empty string on systems like Windows where /dev/urandom
does not exist.
Upvotes: 10