While creating API for Android App, i came across with very simple but difficult (for me) problem.
How would it be possible to generate a random, unique string using numbers and letters for verfiy user, Something like api_key which is unique to user but at the same time it shuold be safe and it will always associate with user.
Now second problem is how will i generate this kind of api_key using PHP. While Googling, i found this is very interesting subject at least for Developers.
So thought to share my finding and they are: (My approach is at the end)
Very first thing i found is “uniqid()”.
Description
string uniqid ([ string $prefix = "" [, bool $more_entropy = false ]] )
It’s a PHP function that generates a unique identifier based on the current time in microseconds. Returns the unique identifier, as a string.
I think I’ll use that. But This function 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().
Then i two found very good, points on Stackoverflow, which catch my eyes.
if do not need it to be absolutely unique over time then we can use:
md5(uniqid(rand(), true));
Or for user login if need to generate unique value we can use:
md5(uniqid($your_user_login, true));
Why are common hashing functions such as md5() and sha1() unsuitable for passwords?
Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be very fast and efficient. With modern techniques and computer equipment, it has become trivial to “brute force” the output of these algorithms, in order to determine the original input.
Because of how quickly a modern computer can “reverse” these hashing algorithms, many security professionals strongly suggest against their use for password hashing.
Both methods do not guarantee uniqueness – length of the input of the md5 function is greater than length of its output and according to the en.wikipedia.org/wiki/Pigeonhole_principle the collision is guaranteed. On the other hand, the greater the population relying on hashes to achieve the “unique” id, the greater the probability of occurring at least one collision (see en.wikipedia.org/wiki/Birthday_problem). The probability may be tiny for most of solutions but it still exists.
Following also one the very good function i have found:
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){
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
for($i=0;$i<$length;$i++){
$token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))];
}
return $token;
}
crypto_rand_secure($min, $max) works as a drop in replacement for rand() or mt_rand. It uses openssl_random_pseudo_bytes to help create a random number between $min and $max.
getToken($length) creates an alphabet to use within the token and then creates a string of length $length.
After all R&D, i used something different, simple (using username and userid) and it is working for me perfectly. Please suggest me any improvement in following code:
public function generateUniqueToken($userid, $username){
$rand = mt_rand(100,999);
$md5 = md5($userid.'!(&^ 532567_465 ///'.$username);
$md53 = substr($md5,0,3);
$md5_remaining = substr($md5,3);
$md5 = $md53. $rand. $userid. $md5_remaining;
return $md5;
}