Can hash be used to create very good random strings?

I’m wondering if using a good hash algorithm (for example sha-2) can be used to generate random strings that are more random and unpredictable than rand() or mt_rand() functions (which are vulnerable to small seed entropy and other potential weaknesses). My idea is to get a number of always changing data, concatenate them and then hash them. I could be using:

  • sytem time with microseconds
  • result of uniqid() with more entropy
  • a salt string created with traditional mt_rand()
  • execution time of the current script (there are always some differences in microseconds)

My reasoning is that the more data sources I use to feed the hash function the less predictable (more random) the result will be even if the data sources are not truly random. I found this idea somewhere in a discussion under an article and I tend to agree with it, however I’m not an expert on randomness or hash algorithms so that’s why I’m asking if anyone can validate this is true.

For some more extreme randomness I could also add more data sources to the string to be hashed:

  • a string from /dev/urandom if available
  • a string from an external true random number generator like random.org
  • if the random string were to be generated after a user submits a form then I could use javascript to measure time between keystrokes or even capture mouse movements

My goal is to create random numbers that are random enough for secure systems so that no one can break the pattern and predict any random strings. I could simply use random numbers from random.org, but then there is the problem of fetching the data from a remote server securely and probably storing it on the server since I don’t want to rely on all-the-time availability of an external service.

Here is sample php code:


$start_time = microtime(true);

$time = microtime(true);
$uniqid = uniqid('', true);

$salt = '';
for ($i=0; $i<128; $i++) {
	$salt .= chr(mt_rand(0, 255));
}

$duration = microtime(true) - $start_time;  // e.g. 0.0017452239990234

$random_string = hash('sha256', $time.$uniqid.$salt.$duration);

Is this a good random string generator?

Use mcrypt for this. That is if you need a real strong random value, a cryptographically secure pseudorandom number generator. By using “mcrypt_create_iv” in this case, since version 5.3 it also uses a CSPRNG on Windows.


$r = mcrypt_create_iv( 4096, MCRYPT_DEV_RANDOM );

// Anything extra you would like to add.
$r = hash( ... );

It’s not clear from your example - do you suggest getting the random string directly from mcrypt_create_iv or add it to the string to be hashed?

Generating 400 bytes in this way on one of my shared hosts took one minute, very very slow… MCRYPT_DEV_URANDOM is faster but possibly a bit worse?

You can do what you like with it, use it directly or add it to something else. The point is that it uses an CSPRNG, some cases gets its entropy from the hardware (or mixtures of hardware and software). Depending on your needs, using URANDOM would be fine, it sacrifices some entropy for non-blocking.

Okay, I’ll be adding it to the hash then. What would be the minimum length of the string needed? If I’m hashing the string with sha256 then it looks like I need to extract at least 256 bits (32 bytes) from mcrypt_create_iv() to take advantage of maximum entropy, am I right? I suppose getting more bits wouldn’t hurt but will they be of any value?