Some further thoughts about the uniqueness of constructs like
md5(uniqid(microtime(), true));
I will only cover uniqueness and leave out security completely.
First, a definition of "collision": A behaviour where a function returns an identical output R for two different inputs V1 and V2 is defined as collision.
Now on to the thoughts:
1) The beginning:
uniqid()
The PHP manual states "uniqid() returns a [...] unique identifier based on the current time in microseconds."
Judging from the output of uniqid() (without parameters) it seems to be doing nothing more than a rather simple transformation of some kind.
So: uniqid() might (!) return the same result for the same microsecond. Without diving into PHP sources I don't know but from an educated guess I'm pretty sure of it.
In other words, uniqid() might have the same uniqueness as microtime(). For the further thoughts however, this is irrelevant.
2) Next:
uniqid('prefix')
The prefix is not merged with the microtime that uniqid() internally uses, but it merely prefixes it.
So: For a fixed prefix, the uniquess is identical to 1)
For a variable prefix however, the uniqueness increases. This is what you do with uniqid(microtime()).
By what amount it increases is unclear. Sadly this is significant for an evaluation. But again, for the further thoughts this is irrelevant.
3)
uniqid(microtime(), true)
Added entropy. Extract from the manual "...which should make the results more unique.". Hmm, rather vague. Maybe the entropy parameter increases the entropy by factors, maybe not. Most likely it will. But since I don't have enough time to read and understand the internals of the combined linear congruential generator I'm thinking worst-case and assume that it won't.
4) Hashing.
The characteristics of any hash function can be summarized as follows: For a given input string of arbitrary length the hash function will generate a string-representation of fixed length. For MD5() the length is 128 bits, which is 32 byte in hex-representation.
Read it again. A fixed string will always return the same output. That's the whole point of hashing.
Since MD5() (and most other hash functions) uses a finite charset and a fixed length for the returned values, the number of different outputs that MD5() can return is limited. To be precise, MD5() can return 2128 different hashes.
Since it is very easily possible (I don't say it's fast) to generate more than 2128 different strings, MD5() will collide at some point. SHA1() by the way will too, but later.
Now a look at the code:
md5(uniqid(microtime(), true));
Lets make it simpler:
$vector = uniqid(microtime(), true);
$hash = md5($vector);
As long as $vector does not change, $hash won't change as well. Remember, that's the whole point of hashing. In short: The uniqueness of $hash is roughly equal to the uniqueness of $vector. You're not gaining anything.
5) Further thoughts:
In 4) I state "The uniqueness of $hash is roughly equal to the uniqueness of $vector.". Why only roughly? Because to be precise it will be lower than the uniqueness of $vector. Why? Because I believe (and please correct me) that we're adding probabilities for collisions.
Lets say $vector has a likeliness of X to collide. For two out of X different inputs, identical outputs will be generated.
Lets further say that $hash has a likelyness of Y to collide.
This means:
If $vector1 and $vector2 are identical, then both hashes from those vectors will be identical. Again: This is the whole point of hashing.
But if $vector1 and $vector3 are not identical, the two hashes from those vectors might still be identical, due to a collision of MD5().
Conclusions:
Basically you might be worsening things by hashing a string that is already considered to be unique. I'm not saying that hashing is a bad thing, all I say is that you have to be careful when to use it. Again, if you feel I might be mistaken please correct me.
What might remain is the desire to keep the string at a fixed-length. For that, it might not look as good as hashing but from a uniqueness point of view you might as well use sprintf() to pad the string.
Regards,
Dominique