views:

991

answers:

6

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?

A: 

I think sha512 is too much for it, if you use:

$secureHash = sha1(uniqid($seed . mt_rand()));

Should perform faster, and still very secure.

Nathan
A: 

There's a whole bunch of them right here, in the comments section.

Sneakyness
+2  A: 

Take a look at Random.org if you feel that your application warrants true random numbers.

They have client interfaces for many languages:

http://www.random.org/clients/http/archive/

Dave Forgac
+2  A: 

That's perfectly adequate.

The weak link here is not your generated password, but the security of the email account the password is sent to.

See: recent Twitter attack

thedz
+1  A: 

I do not think you need a crypto-strong RNG to generate a one-time, temporary reset-password.

If the RNG is seeded with the current time at the time of the Reset-Password request, then the seed will be unpredictable due to unknown and variable latency in the internet and processing of the request.

While an attacker could know the seed to within a second or so, there are 1000 ms (ie potential seeds) in that window.

If you throttle the number of password resets per day to a reasonable number, say, 5 per user, I don't see how an attack could hope to succeed.

abelenky
+2  A: 

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.

Einstein