What is the best way to generate a random key in PHP?

I want to create a reusable function that will generate a random key with printed ACSII characters of the selected length (from 2 to 1000+). I think the printed ASCII characters will be 33-126. They do not have to be completely unique, just unique if they are generated in the same millisecond (so uniqid() will not work).

I think the combination of chr() and mt_rand() might work.

Is this the way, or is something else a better method?

Edit: uniqid() will not work either, because it has no length parameter, this is just what PHP gives.

My idea . This is what I came up with:

 function GenerateKey($length = 16) { $key = ''; for($i = 0; $i < $length; $i ++) { $key .= chr(mt_rand(33, 126)); } return $key; } 

Are there any problems with this?

Other Edit:. Most other questions relate to password generation. I want a wider range of characters, and I don't care about 1 vs l . I want the maximum number of possible keys possible.

Note: the generated key does not have to be cryptographically secure.

+35
php random
Mar 12 '09 at 3:41
source share
8 answers

Update (12/2015): for PHP 7.0 you should use random_int() instead of mt_rand as it provides "cryptographically secure values"

Personally, I like to use sha1(microtime(true).mt_rand(10000,90000)) , but you are looking for a more custom approach, so try this function (which is a modification of your request for this answer ):

 function rand_char($length) { $random = ''; for ($i = 0; $i < $length; $i++) { $random .= chr(mt_rand(33, 126)); } return $random; } 

However, this is likely to be significantly slower than uniqid (), md5 () or sha1 ().

Edit: It looks like you got to it first, sorry .: D

Edit 2: I decided to do a little test on my Debian machine with PHP 5 and eAccelerator (sorry long code):

 function rand_char($length) { $random = ''; for ($i = 0; $i < $length; $i++) { $random .= chr(mt_rand(33, 126)); } return $random; } function rand_sha1($length) { $max = ceil($length / 40); $random = ''; for ($i = 0; $i < $max; $i ++) { $random .= sha1(microtime(true).mt_rand(10000,90000)); } return substr($random, 0, $length); } function rand_md5($length) { $max = ceil($length / 32); $random = ''; for ($i = 0; $i < $max; $i ++) { $random .= md5(microtime(true).mt_rand(10000,90000)); } return substr($random, 0, $length); } $a = microtime(true); for ($x = 0; $x < 1000; $x++) $temp = rand_char(1000); echo "Rand:\t".(microtime(true) - $a)."\n"; $a = microtime(true); for ($x = 0; $x < 1000; $x++) $temp = rand_sha1(1000); echo "SHA-1:\t".(microtime(true) - $a)."\n"; $a = microtime(true); for ($x = 0; $x < 1000; $x++) $temp = rand_md5(1000); echo "MD5:\t".(microtime(true) - $a)."\n"; 

Results:

 Rand: 2.09621596336 SHA-1: 0.611464977264 MD5: 0.618473052979 

So my suggestion, if you want speed (but not full encoding), should stick with MD5, SHA-1 or Uniqid (which I haven't tested yet).

+52
Mar 12 '09 at 4:05
source share

None of the answers here are sufficient if you need the cryptographic power of randomness (is there a certain intruder trying to guess what your random keys are?). Time hashing is not safe, an attacker can significantly speed up the search by guessing the time during which they think that your server generated the key and it is easy to view all milliseconds for a certain year, even on a commodity laptop (this is a 35 bit search space). Also, the dangerously dangerous assumption is that you simply run the results of uniqid() or another weak random source through a hash function to β€œexpand it” - this does not make finding an attacker more difficult if they find out that you did it.

If you really need crypto security, you should read / dev / random, the following code should work for you on any POSIX-compatible system (nothing but Windows):

 #Generate a random key from /dev/random function get_key($bit_length = 128){ $fp = @fopen('/dev/random','rb'); if ($fp !== FALSE) { $key = substr(base64_encode(@fread($fp,($bit_length + 7) / 8)), 0, (($bit_length + 5) / 6) - 2); @fclose($fp); return $key; } return null; } 

If you need a bit more speed, you can read "dev / urandom" instead.

+27
May 11 '11 at 12:04
source share

You can still use uniqid (), just do some extra processing to expand its value to the number of characters you need.

For example, to expand it to 32 characters, you can do

 $id = md5(uniqid()); 

To expand it to 64 characters, just add md5 from md5, for example

 $first = md5(uniqid()); $id = $first . md5($first); 

Then, summarize as necessary if you need less than a few multiples of 32.

You may have encountered collisions, but this is unlikely. If you are paranoid about this, just use the same idea, but chug uniqid() through a symmetric cipher like AES, instead of hashing it.

+7
Mar 12 '09 at 4:11
source share
+3
Dec 02 '13 at 12:12
source share

My previous answer took the uniqid () hash combined with the salt obtained from the system variables, but this does not generate a random key, only the one that is most likely to be unique. Similarly, the output from rand () or mt_rand () is not random enough for cryptographic purposes.

To create a random key, you need to go to a good random data source, and the openssl_random_pseudo_bytes () function is designed for this:

 $randkey = base64_encode(openssl_random_pseudo_bytes(32)); 

Base64_encode () should make it printable. A.

The reason that other answers do not recommend openssl_random_pseudo_bytes () is probably because it was introduced in PHP 5.3, and this question is almost 6 years old.

+1
Mar 03 '15 at 23:13
source share

Could you be interested in this question ?

I'm not sure why uniqid() does not work for you, and in which case you will need a unique number for one millisecond, but not necessarily otherwise; what do you generate so fast that in the same millisecond you could run into? I am wondering how long it takes uniqid() to generate its number. If you want, use the uniqid() function uniqid() with a few random letters, and you should be safe.

If it's for creating a file, you can look at tmpfile() or tempname() .

In any case, depending on what you are trying to achieve, you can simply run a loop and check if a unique identifier has already been selected (in the array, with file_files, etc.) and just generate another one, if so.




Also, since I'm not sure that I understand your question exactly, I would point you to those other questions that sound pretty similar as long as I get the difference:

  • Generate (pseudo) random alphanumeric strings
  • How many random elements before MD5 cause collisions?

The first will be interesting if you want to make a unique identifier that is read by a person. The second one can be useful if you want to play with random numbers and md5 / sha1. Although, again, I think uniqid() may already be what you are looking for.

0
Mar 12 '09 at 3:54
source share

$ key = md5 (microtime (). rand ());

Microtime itself is unsafe because it leaves only a 1/1000 chance of guessing.

Rand itself is also not very safe, but hashing them concatenating them together gives a pretty solid randomization.

0
Apr 10 '14 at 18:02
source share

You can also create a random key and check the key in your database, if the key comes out, you can generate another key using this method.

  function activation($lengt=20){ $modalpage =new Modal;//you can call your modal page and check the key $characters = "1234567890abcdefghijklmnopqrstuvwxyz"; for($i=0;$i<$lengt;$i++) { $key .= $characters{rand(0,35)}; $check= array( ":key" => $key, ); $result = $modalpage->findkey($check); if($result==true){ //if the key is exits return the function and generate another key ! return activation($lengt); }else //if the key is not exits return the key return $key; } } $mykey=activation(15); 
-one
Apr 20 '15 at 20:54
source share



All Articles