Use case: the "I forgot my password" button. We can't find the user's original password because it's stored in hashed form, so the only thing to do is generate a new random password and e-mail it to him. This requires cryptographically unpredictable random numbers, for which mt_rand is not good enough, and in general we can't assume a hosting service will provide access to the operating system to install a cryptographic random number module etc. so I'm looking for a way to generate secure random numbers in PHP itself.
The solution I've come up with so far involves storing an initial seed, then for each call,
result = seed
seed = sha512(seed . mt_rand())
This is based on the security of the sha512 hash function (the mt_rand call is just to make life a little more difficult for an adversary who obtains a copy of the database).
Am I missing something, or are there better known solutions?
I strongly recommend targeting /dev/urandom on unix systems or the crypto-api on the windows platform as an entropy source for passwords.
I can't stress enough the importance of realizing hashes are NOT magical entropy increasing devices. Misusing them in this manner is no more secure than using the seed and rand() data before it had been hashed and I'm sure you recognize that is not a good idea. The seed cancels out (deterministic mt_rand()) and so there is no point at all in even including it.
People think they are being smart and clever and the result of their labor are fragile systems and devices which put the security of their systems and the security of other systems (via poor advice) in unecessary jeopardy.
Two wrongs don't make a right. A system is only as strong as its weakest part. This is not a license or excuse to accept making even more of it insecure.
Here is some PHP code to obtain a secure random 128-bit string, from this comment at php.net by Mark Seecof:
You can also consider using OpenSSL openssl_random_pseudo_bytes, it's available since PHP 5.3.
http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php
Since PHP 7 there is also
random_bytes
function availablehttp://php.net/manual/en/function.random-bytes.php
PHP ships with a new set of CSPRNG functions (
random_bytes()
andrandom_int()
). It's trivial to turn the latter function into a string generator function:If you need to use this in a PHP 5 project, feel free to grab a copy of random_compat, which is a polyfill for these functions.