How to generate unique secure random string in PHP?

3.1k views Asked by At

I want to add random string as token for form submission which is generated unique forever. I have spent to much time with Google but I am confused which combination to use?

I found so many ways to do this when I googled:

1) Combination of character and number.

2) Combination of character, number and special character.

3) Combination of character, number, special character and date time.

Which combination may i use?

How many character of random string may I generate.?

Any other method which is secure then please let me know.?

7

There are 7 answers

0
Grokify On BEST ANSWER

Here are some considerations:

Alphabet

The number of characters can be considered the alphabet for the encoding. It doesn't affect the string strength by itself but a larger alphabet (numbers, non-alpha-number characters, etc.) does allow for shorter strings of similar strength (aka keyspace) so it's useful if you are looking for shorter strings.

Input Values

To guarantee your string to be unique, you need to add something which is guaranteed to be unique.

  • Random value is a good seed value if you have a good random number generator
  • Time is a good seed value to add but it may not be unique in a high traffic environment
  • User ID is a good seed value if you assume a user isn't going to create sessions at the exact same time
  • Unique ID is something the system guarantees is unique. This is often something that the server will guarantee / verify is unique, either in a single server deployment or distributed deployment. A simple way to do this is to add a machine ID and machine unique ID. A more complicated way to do this is to assign key ranges to machines and have each machine manage their key range.

Systems that I've worked with that require absolute uniqueness have added a server unique id which guarantees a item is unique. This means the same item on different servers would be seen as different, which was what was wanted here.

Approach

Pick one more input values that matches your requirement for uniqueness. If you need absolute uniqueness forever, you need something that you control that you are sure is unique, e.g. a machine associated number (that won't conflict with others in a distributed system). If you don't need absolute uniqueness, you can use a random number with other value such as time. If you need randomness, add a random number.

Use an alphabet / encoding that matches your use case. For machine ids, encodings like hexadecimal and base 64 are popular. For machine-readable ids, for case-insensitive encodings, I prefer base32 (Crockford) or base36 and for case-sensitive encodings, I prefer base58 or base62. This is because these base32, 36, 58 and 62 produce shorter strings and (vs. base64) are safe across multiple uses (e.g. URLs, XML, file names, etc.) and don't require transformation between different use cases.

0
Vivek Patel On

You should go for 3 option. Because it has date and time so it become every time unique. And for method have you tried

str_shuffle($string)

Every time it generates random string from $string. End then use substr

($string , start , end)

to cut it down. End if you want date and time then concatenate the result string with it.

0
Eaten by a Grue On

You can definitely get a lot fancier depending on your needs, but I'll just throw this out there since it's what I use frequently for stuff like what you are describing:

md5(rand());

It's quick, simple and easy to remember. And since it's hexadecimal it plays nicely with others.

0
AddWeb Solution Pvt Ltd On

Try the code, for function getUniqueToken() which returns you unique string of length 10 (default).

/*
    This function will return unique token string...
*/
function getUniqueToken($tokenLength = 10){
    $token = "";
    //Combination of character, number and special character...
    $combinationString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*#&$^";
    for($i=0;$i<$tokenLength;$i++){
        $token .= $combinationString[uniqueSecureHelper(0,strlen($combinationString))];
    }
    return $token;
}

/*
    This helper function will return unique and secure string...
*/
function uniqueSecureHelper($minVal, $maxVal) {
        $range = $maxVal - $minVal;
        if ($range < 0) return $minVal; // 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 $minVal + $rnd;
}

Use this code (two function), you can increase string length by passing int parameter like getUniqueToken(15).

I use your 2nd idea (Combination of character, number and special character), which you refine after googling. I hope my example will help you.

0
Abhinav On

Refer to this SO Protected Question. This might be what you are looking.

I think its better to redirect you to a previously asked question which has more substantive answers.You will find a lot of options.

1
Himanshu Bhardiya On

For unique string use uniqid().

And to make it secure, use hashing algorithms

for example :

echo md5(uniqid())

0
Hanne P On

An easily understandable and effective code to generate random strings in PHP. I do not consider predictability concerns important in this connection.

<?php

$d = str_shuffle('0123456789');
$C = str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
$m = str_shuffle('abcdefghijklmnopqrstuvwxyz');
$s = str_shuffle('@!$&()*+-_~');



$l=9; //min 4
$r=substr(str_shuffle($d.$C.$m.$s),0,$l);echo $r.'<br>';


$safe=substr($d,0,1).substr($C,0,1).substr($m,0,1).mb_substr($s,0,1);

$r=str_shuffle($safe.substr($r,0,$l-4));//always at least one digit, special, small and capital
                                       // this also allows for 0,1 or 2 of each available characters in string

echo $r;

exit;
?>