Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

md5(uniqid) makes sense for random unique tokens?

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/

like image 897
Exception e Avatar asked Apr 07 '10 15:04

Exception e


2 Answers

rand() is a security hazard and should never be used to generate a security token: rand() vs mt_rand() (Look at the "static" like images). But neither of these methods of generating random numbers is cryptographically secure. To generate secure secerts an application will needs to access a CSPRNG provided by the platform, operating system or hardware module.

In a web application a good source for secure secrets is non-blocking access to an entropy pool such as /dev/urandom. As of PHP 5.3, PHP applications can use openssl_random_pseudo_bytes(), and the Openssl library will choose the best entropy source based on your operating system, under Linux this means the application will use /dev/urandom. This code snip from Scott is pretty good:

function crypto_rand_secure($min, $max) {         $range = $max - $min;         if ($range < 0) return $min; // not so random...         $log = log($range, 2);         $bytes = (int) ($log / 8) + 1; // length in bytes         $bits = (int) $log + 1; // length in bits         $filter = (int) (1 << $bits) - 1; // set all lower bits to 1         do {             $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));             $rnd = $rnd & $filter; // discard irrelevant bits         } while ($rnd >= $range);         return $min + $rnd; }  function getToken($length=32){     $token = "";     $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";     $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";     $codeAlphabet.= "0123456789";     for($i=0;$i<$length;$i++){         $token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))];     }     return $token; } 
like image 183
rook Avatar answered Sep 28 '22 10:09

rook


This is a copy of another question I found that was asked a few months before this one. Here is a link to the question and my answer: https://stackoverflow.com/a/13733588/1698153.

I do not agree with the accepted answer. According to PHPs own website "[uniqid] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()."

I do not think the answer could be clearer than this, uniqid is not secure.

like image 44
Scott Avatar answered Sep 28 '22 11:09

Scott