views:

524

answers:

4

I want to create a token generator that generates tokens that cannot be guessed by the user and that are still unique (to be used for password resets and confirmation codes).

I often see this code; does it make sense?

md5(uniqid(rand(), true));

According to a comment uniqid($prefix, $moreEntopy = true) yields

first 8 hex chars = Unixtime, last 5 hex chars = microseconds.

I don't know how the $prefix-parameter is handled..

So if you don't set the $moreEntopy flag to true, it gives a predictable outcome.


QUESTION: But if we use uniqid with $moreEntopy, what does hashing it with md5 buy us? Is it better than:

md5(mt_rand())

edit1: I will store this token in an database column with a unique index, so I will detect columns. Might be of interest/

A: 

MD5 is a decent algorithm for producing data dependent IDs. But in case you have more than one item which has the same bitstream (content), you will be producing two similar MD5 "ids".

So if you are just applying it to a rand() function, which is guaranteed not to create the same number twice, you are quite safe.

But for a stronger distribution of keys, I'd personally use SHA1 or SHAx etc'... but you will still have the problem of similar data leads to similar keys.

Etamar L.
A: 

Define "unique". If you mean that two tokens cannot have the same value, then hashing isn't enough - it should be backed with a uniqueness test. The fact that you supply the hash algorithm with unique inputs does not guarantee unique outputs.

M.A. Hanin
unique = don't have the same value indeed. Each token is associated with a unique e-mail address. Maybe we could use this to make a random token unique. I am still unsure what the best way to do this.
Exception e
+1  A: 

To answer your question, the problem is you can't have a generator that is guaranteed random and unique as random by itself, i.e., md5(mt_rand()) can lead to duplicates. What you want is "random appearing" unique values. uniqid gives the unique id, rand() affixes a random number making it even harder to guess, md5 masks the result to make it yet even harder to guess. Nothing is unguessable. We just need to make it so hard that they wouldn't even want to try.

webbiedave
You say "md5 masks the result to make it yet even harder to guess". So uniqueid generates a somewhat random result that is unique. What do you precisely mean by masking? If I would follow this thought than `md5(md5(uniqid(rand(), true)` would mean even more masking, but it is worse right?
Exception e
@Excpetion e, a double md5() hash doesn't improve the secuirty of this system.
Rook
+1  A: 

rand() is a secuirty hazard and should never be used to generate a security token: rand() vs mt_rand() (Look at the "static" like images).

For most security purposes this is a good token:

md5(uniqid(mt_rand(), true));

uniqid will tack on the time, so the value return will unique every time it is called on the same system. If you need it to be unique for a specific system then you should tack on the ip address of the server.

md5() does not make it more random, in fact it introduces the possibility of a natural collision. Although this is a possibility it will not happen in our life times so its safe. Malicious people can generate collisions for md5 hashes and this is why it shouldn't be used for sanity checks or for password storage. In order for someone to generate a collision the attacker must have to have the original message and be able to control the prefix. This attack doesn't make your token less random, so don't worry abou t it. md5() in this case is being used to obscure the time that it was created which is a legitimate use.

Rook
`md5() in this case is being used to obscure the time that it was created which is a legitimate use` That sounds like the answer.
Exception e