How to generate random 64-bit value as decimal string in PHP - php

Oauth requires a random 64-bit, unsigned number encoded as an ASCII string in decimal format. Can you guys help me achieve this with php?
Thanks

This was a really interesting problem (how to create the decimal representation of an arbitrary-length random number in PHP, using no optional extensions). Here's the solution:
Step 1: arbitrary-length random number
// Counts how many bits are needed to represent $value
function count_bits($value) {
for($count = 0; $value != 0; $value >>= 1) {
++$count;
}
return $count;
}
// Returns a base16 random string of at least $bits bits
// Actual bits returned will be a multiple of 4 (1 hex digit)
function random_bits($bits) {
$result = '';
$accumulated_bits = 0;
$total_bits = count_bits(mt_getrandmax());
$usable_bits = intval($total_bits / 8) * 8;
while ($accumulated_bits < $bits) {
$bits_to_add = min($total_bits - $usable_bits, $bits - $accumulated_bits);
if ($bits_to_add % 4 != 0) {
// add bits in whole increments of 4
$bits_to_add += 4 - $bits_to_add % 4;
}
// isolate leftmost $bits_to_add from mt_rand() result
$more_bits = mt_rand() & ((1 << $bits_to_add) - 1);
// format as hex (this will be safe)
$format_string = '%0'.($bits_to_add / 4).'x';
$result .= sprintf($format_string, $more_bits);
$accumulated_bits += $bits_to_add;
}
return $result;
}
At this point, calling random_bits(2048) will give you 2048 random bits as a hex-encoded string, no problem.
Step 2: arbitrary-precision base conversion
Math is hard, so here's the code:
function base_convert_arbitrary($number, $fromBase, $toBase) {
$digits = '0123456789abcdefghijklmnopqrstuvwxyz';
$length = strlen($number);
$result = '';
$nibbles = array();
for ($i = 0; $i < $length; ++$i) {
$nibbles[$i] = strpos($digits, $number[$i]);
}
do {
$value = 0;
$newlen = 0;
for ($i = 0; $i < $length; ++$i) {
$value = $value * $fromBase + $nibbles[$i];
if ($value >= $toBase) {
$nibbles[$newlen++] = (int)($value / $toBase);
$value %= $toBase;
}
else if ($newlen > 0) {
$nibbles[$newlen++] = 0;
}
}
$length = $newlen;
$result = $digits[$value].$result;
}
while ($newlen != 0);
return $result;
}
This function will work as advertised, for example try base_convert_arbitrary('ffffffffffffffff', 16, 10) == '18446744073709551615' and base_convert_arbitrary('10000000000000000', 16, 10) == '18446744073709551616'.
Putting it together
echo base_convert_arbitrary(random_bits(64), 16, 10);

You could use two 32-bit numbers, four 16-bit numbers, etc.
PHP has rand() and and mt_rand() but how many random bits they supply isn't specified by the standard (though they can be queried with the help of getrandmax() and mt_getrandmax(), respectively.)
So your safest simplest bet would be generating 64 random bits and setting them one by one.
As for working with 64-bit integers, I'd recommend using the GMP library as it has a good range of functions to help you out.
You could create a number, call 64 gmp_setbit()s on it with successive positions then convert it to a string using gmp_strval().

Are you building an OAuth adapter yourself? If so, you might want to reconsider. There are plenty of good OAuth libraries out there, including one from PECL, one in PEAR, another from the Zend Framework, and this other one hosted on Google Code. I've worked with the first three, and they're all pretty decent.
If you really want to do this yourself, you may face an issue. PHP can't think in 64-bit numbers unless it's compiled on a 64-bit platform or you have an advanced mathematics extension installed. This is going to make presenting a 64-bit number as a decimal very difficult. It looks like many of the libraries I linked above completely ignore the format requirement and simply work with a raw MD5 hash. Here's the code from ZF's adapter:
/**
* Generate nonce
*
* #return string
*/
public function generateNonce()
{
return md5(uniqid(rand(), true));
}
They look like they're getting away with this without interoperability issues.

Related

how can I generate 10 digit unique number that will be sent to user after registration on laravel [duplicate]

How would it be possible to generate a random, unique string using numbers and letters for use in a verify link? Like when you create an account on a website, and it sends you an email with a link, and you have to click that link in order to verify your account
How can I generate one of those using PHP?
PHP 7 standard library provides the random_bytes($length) function that generate cryptographically secure pseudo-random bytes.
Example:
$bytes = random_bytes(20);
var_dump(bin2hex($bytes));
The above example will output something similar to:
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
More info: http://php.net/manual/en/function.random-bytes.php
PHP 5 (outdated)
I was just looking into how to solve this same problem, but I also want my function to create a token that can be used for password retrieval as well. This means that I need to limit the ability of the token to be guessed. Because uniqid is based on the time, and according to php.net "the return value is little different from microtime()", uniqid does not meet the criteria. PHP recommends using openssl_random_pseudo_bytes() instead to generate cryptographically secure tokens.
A quick, short and to the point answer is:
bin2hex(openssl_random_pseudo_bytes($bytes))
which will generate a random string of alphanumeric characters of length = $bytes * 2. Unfortunately this only has an alphabet of [a-f][0-9], but it works.
Below is the strongest function I could make that satisfies the criteria (This is an implemented version of Erik's answer).
function crypto_rand_secure($min, $max)
{
$range = $max - $min;
if ($range < 1) return $min; // not so random...
$log = ceil(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";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
}
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.
Source: http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
Security Notice: This solution should not be used in situations where the quality of your randomness can affect the security of an application. In particular, rand() and uniqid() are not cryptographically secure random number generators. See Scott's answer for a secure alternative.
If you do not need it to be absolutely unique over time:
md5(uniqid(rand(), true))
Otherwise (given you have already determined a unique login for your user):
md5(uniqid($your_user_login, true))
Object-oriented version of the most up-voted solution
I've created an object-oriented solution based on Scott's answer:
<?php
namespace Utils;
/**
* Class RandomStringGenerator
* #package Utils
*
* Solution taken from here:
* http://stackoverflow.com/a/13733588/1056679
*/
class RandomStringGenerator
{
/** #var string */
protected $alphabet;
/** #var int */
protected $alphabetLength;
/**
* #param string $alphabet
*/
public function __construct($alphabet = '')
{
if ('' !== $alphabet) {
$this->setAlphabet($alphabet);
} else {
$this->setAlphabet(
implode(range('a', 'z'))
. implode(range('A', 'Z'))
. implode(range(0, 9))
);
}
}
/**
* #param string $alphabet
*/
public function setAlphabet($alphabet)
{
$this->alphabet = $alphabet;
$this->alphabetLength = strlen($alphabet);
}
/**
* #param int $length
* #return string
*/
public function generate($length)
{
$token = '';
for ($i = 0; $i < $length; $i++) {
$randomKey = $this->getRandomInteger(0, $this->alphabetLength);
$token .= $this->alphabet[$randomKey];
}
return $token;
}
/**
* #param int $min
* #param int $max
* #return int
*/
protected function getRandomInteger($min, $max)
{
$range = ($max - $min);
if ($range < 0) {
// Not so random...
return $min;
}
$log = log($range, 2);
// Length in bytes.
$bytes = (int) ($log / 8) + 1;
// Length in bits.
$bits = (int) $log + 1;
// Set all lower bits to 1.
$filter = (int) (1 << $bits) - 1;
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
// Discard irrelevant bits.
$rnd = $rnd & $filter;
} while ($rnd >= $range);
return ($min + $rnd);
}
}
Usage
<?php
use Utils\RandomStringGenerator;
// Create new instance of generator class.
$generator = new RandomStringGenerator;
// Set token length.
$tokenLength = 32;
// Call method to generate random string.
$token = $generator->generate($tokenLength);
Custom alphabet
You can use custom alphabet if required.
Just pass a string with supported chars to the constructor or setter:
<?php
$customAlphabet = '0123456789ABCDEF';
// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);
// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);
Here's the output samples
SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa
I hope it will help someone. Cheers!
I'm here with some good research data based on the functions provided by Scott's answer. So I set up a Digital Ocean droplet just for this 5-day long automated test and stored the generated unique strings in a MySQL database.
During this test period, I used 5 different lengths (5, 10, 15, 20, 50) and +/-0.5 million records were inserted for each length. During my test, only the length 5 generated +/-3K duplicates out of 0.5 million and the remaining lengths didn't generate any duplicates. So we can say that if we use a length of 15 or above with Scott's functions, then we can generate highly reliable unique strings. Here is the table showing my research data:
Update
I created a simple Heroku app using these functions that returns the token as a JSON response. The app can be accessed at https://uniquestrings.herokuapp.com/api/token?length=15
You can use UUID(Universally Unique Identifier), it can be used for any purpose, from user authentication string to payment transaction id.
A UUID is a 16-octet (128-bit) number. In its canonical form, a UUID is represented by 32 hexadecimal digits, displayed in five groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 alphanumeric characters and four hyphens).
function generate_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0C2f ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
);
}
//calling funtion
$transationID = generate_uuid();
some example outputs will be like:
E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2
hope it helps someone in future :)
This function will generate a random key using numbers and letters:
function random_string($length) {
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
echo random_string(50);
Example output:
zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
I use this one-liner:
base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));
where length is the length of the desired string (divisible by 4, otherwise it gets rounded down to the nearest number divisible by 4)
Use the code below to generate the random number of 11 characters or change the number as per your requirement.
$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);
or we can use custom function to generate the random number
function randomNumber($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $length;$i++)
$digits .= $numbers[$i];
return $digits;
}
//generate random number
$randomNum=randomNumber(11);
Generate a random number using
your favourite random-number
generator
Multiply and divide it
to get a number matching the number
of characters in your code alphabet
Get the item at that index in
your code alphabet.
Repeat from 1) until you have the length you
want
e.g (in pseudo code)
int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
For really random strings, you can use
<?php
echo md5(microtime(true).mt_Rand());
outputs :
40a29479ec808ad4bcff288a48a25d5c
so even if you try to generate string multiple times at exact same time, you will get different output.
This is a simple function that allows you to generate random strings containing Letters and Numbers (alphanumeric). You can also limit the string length.
These random strings can be used for various purposes, including: Referral Code, Promotional Code, Coupon Code.
Function relies on following PHP functions:
base_convert, sha1, uniqid, mt_rand
function random_code($length)
{
return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
}
echo random_code(6);
/*sample output
* a7d9e8
* 3klo93
*/
When trying to generate a random password you are trying to :
First generate a cryptographically secure set of random bytes
Second is turning those random bytes into a printable string
Now, there are multiple way to generate random bytes in php like :
$length = 32;
//PHP 7+
$bytes= random_bytes($length);
//PHP < 7
$bytes= openssl_random_pseudo_bytes($length);
Then you want to turn these random bytes into a printable string :
You can use bin2hex :
$string = bin2hex($bytes);
or base64_encode :
$string = base64_encode($bytes);
However, note that you do not control the length of the string if you use base64.
You can use bin2hex to do that, using 32 bytes will turn into a 64 char string.
But it will only work like so in an EVEN string.
So basically you can just do :
$length = 32;
if(PHP_VERSION>=7){
$bytes= random_bytes($length);
}else{
$bytes= openssl_random_pseudo_bytes($length);
}
$string = bin2hex($bytes);
Here is what I use:
md5(time() . rand());
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
This people choking on a glass of water...
$random= substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*.-_"), 0, 10);
Simple.
The posibility to this random string repeat is 0,000000000000000000000000000001^70
Here is ultimate unique id generator for you. made by me.
<?php
$d=date ("d");
$m=date ("m");
$y=date ("Y");
$t=time();
$dmt=$d+$m+$y+$t;
$ran= rand(0,10000000);
$dmtran= $dmt+$ran;
$un= uniqid();
$dmtun = $dmt.$un;
$mdun = md5($dmtran.$un);
$sort=substr($mdun, 16); // if you want sort length code.
echo $mdun;
?>
you can echo any 'var' for your id as you like. but $mdun is better, you can replace md5 to sha1 for better code but that will be very long which may you dont need.
Thank you.
I like to use hash keys when dealing verification links. I would recommend using the microtime and hashing that using MD5 since there should be no reason why the keys should be the same since it hashes based off of the microtime.
$key = md5(rand());
$key = md5(microtime());
function random_string($length = 8) {
$alphabets = range('A','Z');
$numbers = range('0','9');
$additional_characters = array('_','=');
$final_array = array_merge($alphabets,$numbers,$additional_characters);
while($length--) {
$key = array_rand($final_array);
$password .= $final_array[$key];
}
if (preg_match('/[A-Za-z0-9]/', $password))
{
return $password;
}else{
return random_string();
}
}
Simple 'one line' string hash generator like
77zd43-7bc495-64cg9a-535548 (1byte = 2chars)
$hash = implode('-', [
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
]);
after reading previous examples I came up with this:
protected static $nonce_length = 32;
public static function getNonce()
{
$chars = array();
for ($i = 0; $i < 10; $i++)
$chars = array_merge($chars, range(0, 9), range('A', 'Z'));
shuffle($chars);
$start = mt_rand(0, count($chars) - self::$nonce_length);
return substr(join('', $chars), $start, self::$nonce_length);
}
I duplicate 10 times the array[0-9,A-Z] and shuffle the elements, after I get a random start point for substr() to be more 'creative' :)
you can add [a-z] and other elements to array, duplicate more or less, be more creative than me
<?php
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
above function will generate you a random string which is length of 11 characters.
If you want to generate a unique string in PHP, try following.
md5(uniqid().mt_rand());
In this,
uniqid() - It will generate unique string. This function returns timestamp based unique identifier as a string.
mt_rand() - Generate random number.
md5() - It will generate the hash string.
A simple solution is to convert base 64 to alphanumeric by discarding the non-alphanumeric characters.
This one uses random_bytes() for a cryptographically secure result.
function random_alphanumeric(int $length): string
{
$result='';
do
{
//Base 64 produces 4 characters for each 3 bytes, so most times this will give enough bytes in a single pass
$bytes=random_bytes(($length+3-strlen($result))*2);
//Discard non-alhpanumeric characters
$result.=str_replace(['/','+','='],['','',''],base64_encode($bytes));
//Keep adding characters until the string is long enough
//Add a few extra because the last 2 or 3 characters of a base 64 string tend to be less diverse
}while(strlen($result)<$length+3);
return substr($result,0,$length);
}
Edit: I just revisited this because I need something a bit more flexible. Here is a solution that performs a bit better than the above and gives the option to specify any subset of the ASCII character set:
<?php
class RandomText
{
protected
$allowedChars,
//Maximum index to use
$allowedCount,
//Index values will be taken from a pool of this size
//It is a power of 2 to keep the distribution of values even
$distributionSize,
//This many characters will be generated for each output character
$ratio;
/**
* #param string $allowedChars characters to choose from
*/
public function __construct(string $allowedChars)
{
$this->allowedCount = strlen($allowedChars);
if($this->allowedCount < 1 || $this->allowedCount > 256) throw new \Exception('At least 1 and no more than 256 allowed character(s) must be specified.');
$this->allowedChars = $allowedChars;
//Find the power of 2 equal or greater than the number of allowed characters
$this->distributionSize = pow(2,ceil(log($this->allowedCount, 2)));
//Generating random bytes is the expensive part of this algorithm
//In most cases some will be wasted so it is helpful to produce some extras, but not too many
//On average, this is how many characters needed to produce 1 character in the allowed set
//50% of the time, more characters will be needed. My tests have shown this to perform well.
$this->ratio = $this->distributionSize / $this->allowedCount;
}
/**
* #param int $length string length of required result
* #return string random text
*/
public function get(int $length) : string
{
if($length < 1) throw new \Exception('$length must be >= 1.');
$result = '';
//Keep track of result length to prevent having to compute strlen()
$l = 0;
$indices = null;
$i = null;
do
{
//Bytes will be used to index the character set. Convert to integers.
$indices = unpack('C*', random_bytes(ceil(($length - $l) * $this->ratio)));
foreach($indices as $i)
{
//Reduce to the smallest range that gives an even distribution
$i %= $this->distributionSize;
//If the index is within the range of characters, add one char to the string
if($i < $this->allowedCount)
{
$l++;
$result .= $this->allowedChars[$i];
}
if($l >= $length) break;
}
}while($l < $length);
return $result;
}
}
one can use this code. i tested with 35,000,00 IDs no duplicates.
<?php
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_';
$result = '';
for ($i = 0; $i < 11; $i++)
$result .= $characters[mt_rand(0, 63)];?>
you are free to modify it as your need. and if you have any suggestions feel free to comment.it is recommended that you should check every id in your database before using this ids by doing that you have 100% unique ids in your database.
function codeGenerate() {
$randCode = (string)mt_rand(1000,9999);
$randChar = rand(65,90);
$randInx = rand(0,3);
$randCode[$randInx] = chr($randChar);
return $randCode;
}
echo codeGenerate();
OUTPUT
38I7
33V7
E836
736U
I always use this my function to generate a custom random alphanumeric string... Hope this help.
<?php
function random_alphanumeric($length) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
$my_string = '';
for ($i = 0; $i < $length; $i++) {
$pos = random_int(0, strlen($chars) -1);
$my_string .= substr($chars, $pos, 1);
}
return $my_string;
}
echo random_alphanumeric(50); // 50 characters
?>
It generates for example: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g
If you want compare with another string to be sure that is a unique sequence you can use this trick...
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
if ($string_1 != $string_2) {
break;
}
}
echo $string_1;
echo "<br>\n";
echo $string_2;
it generate two unique strings:
qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi
Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF
Hope this is what you are looking for...
Scott, yes you are very write and good solution! Thanks.
I am also required to generate unique API token for my each user. Following is my approach, i used user information (Userid and Username):
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;
}
Please have a look and let me know if any improvement i can do. Thanks
Here is what I'm using on one of my projects, it's working great and it generates a UNIQUE RANDOM TOKEN:
$timestampz=time();
function generateRandomString($length = 60) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$tokenparta = generateRandomString();
$token = $timestampz*3 . $tokenparta;
echo $token;
Please note that I multiplied the timestamp by three to create a confusion for whoever user might be wondering how this token is generated ;)
I hope it helps :)
I think this is the best method to use.
str_shuffle(md5(rand(0,100000)))
Here is a fun one
public function randomStr($length = 16) {
$string = '';
while (($len = strlen($string)) < $length) {
$size = $length - $len;
$bytes = random_bytes($size);
$string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
}
return $string;
}
Stolen from laravel here
I believe the problem with all the existing ideas is that they are probably unique, but not definitely unique (as pointed out in Dariusz Walczak's reply to loletech). I have a solution that actually is unique. It requires that your script have some sort of memory. For me this is a SQL database. You could also simply write to a file somewhere. There are two implementations:
First method: have TWO fields rather than 1 that provide uniqueness. The first field is an ID number that is not random but is unique (The first ID is 1, the second 2...). If you are using SQL, just define the ID field with the AUTO_INCREMENT property. The second field is not unique but is random. This can be generated with any of the other techniques people have already mentioned. Scott's idea was good, but md5 is convenient and probably good enough for most purposes:
$random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());
Second method: Basically the same idea, but initially pick a maximum number of strings that will ever be generated. This could just be a really big number like a trillion. Then do the same thing, generate an ID, but zero pad it so that all IDs are the same number of digits. Then just concatenate the ID with the random string. It will be random enough for most purposes, but the ID section will ensure that it is also unique.

How to generate randomized name for image file after resizing it [duplicate]

How would it be possible to generate a random, unique string using numbers and letters for use in a verify link? Like when you create an account on a website, and it sends you an email with a link, and you have to click that link in order to verify your account
How can I generate one of those using PHP?
PHP 7 standard library provides the random_bytes($length) function that generate cryptographically secure pseudo-random bytes.
Example:
$bytes = random_bytes(20);
var_dump(bin2hex($bytes));
The above example will output something similar to:
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
More info: http://php.net/manual/en/function.random-bytes.php
PHP 5 (outdated)
I was just looking into how to solve this same problem, but I also want my function to create a token that can be used for password retrieval as well. This means that I need to limit the ability of the token to be guessed. Because uniqid is based on the time, and according to php.net "the return value is little different from microtime()", uniqid does not meet the criteria. PHP recommends using openssl_random_pseudo_bytes() instead to generate cryptographically secure tokens.
A quick, short and to the point answer is:
bin2hex(openssl_random_pseudo_bytes($bytes))
which will generate a random string of alphanumeric characters of length = $bytes * 2. Unfortunately this only has an alphabet of [a-f][0-9], but it works.
Below is the strongest function I could make that satisfies the criteria (This is an implemented version of Erik's answer).
function crypto_rand_secure($min, $max)
{
$range = $max - $min;
if ($range < 1) return $min; // not so random...
$log = ceil(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";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
}
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.
Source: http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
Security Notice: This solution should not be used in situations where the quality of your randomness can affect the security of an application. In particular, rand() and uniqid() are not cryptographically secure random number generators. See Scott's answer for a secure alternative.
If you do not need it to be absolutely unique over time:
md5(uniqid(rand(), true))
Otherwise (given you have already determined a unique login for your user):
md5(uniqid($your_user_login, true))
Object-oriented version of the most up-voted solution
I've created an object-oriented solution based on Scott's answer:
<?php
namespace Utils;
/**
* Class RandomStringGenerator
* #package Utils
*
* Solution taken from here:
* http://stackoverflow.com/a/13733588/1056679
*/
class RandomStringGenerator
{
/** #var string */
protected $alphabet;
/** #var int */
protected $alphabetLength;
/**
* #param string $alphabet
*/
public function __construct($alphabet = '')
{
if ('' !== $alphabet) {
$this->setAlphabet($alphabet);
} else {
$this->setAlphabet(
implode(range('a', 'z'))
. implode(range('A', 'Z'))
. implode(range(0, 9))
);
}
}
/**
* #param string $alphabet
*/
public function setAlphabet($alphabet)
{
$this->alphabet = $alphabet;
$this->alphabetLength = strlen($alphabet);
}
/**
* #param int $length
* #return string
*/
public function generate($length)
{
$token = '';
for ($i = 0; $i < $length; $i++) {
$randomKey = $this->getRandomInteger(0, $this->alphabetLength);
$token .= $this->alphabet[$randomKey];
}
return $token;
}
/**
* #param int $min
* #param int $max
* #return int
*/
protected function getRandomInteger($min, $max)
{
$range = ($max - $min);
if ($range < 0) {
// Not so random...
return $min;
}
$log = log($range, 2);
// Length in bytes.
$bytes = (int) ($log / 8) + 1;
// Length in bits.
$bits = (int) $log + 1;
// Set all lower bits to 1.
$filter = (int) (1 << $bits) - 1;
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
// Discard irrelevant bits.
$rnd = $rnd & $filter;
} while ($rnd >= $range);
return ($min + $rnd);
}
}
Usage
<?php
use Utils\RandomStringGenerator;
// Create new instance of generator class.
$generator = new RandomStringGenerator;
// Set token length.
$tokenLength = 32;
// Call method to generate random string.
$token = $generator->generate($tokenLength);
Custom alphabet
You can use custom alphabet if required.
Just pass a string with supported chars to the constructor or setter:
<?php
$customAlphabet = '0123456789ABCDEF';
// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);
// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);
Here's the output samples
SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa
I hope it will help someone. Cheers!
I'm here with some good research data based on the functions provided by Scott's answer. So I set up a Digital Ocean droplet just for this 5-day long automated test and stored the generated unique strings in a MySQL database.
During this test period, I used 5 different lengths (5, 10, 15, 20, 50) and +/-0.5 million records were inserted for each length. During my test, only the length 5 generated +/-3K duplicates out of 0.5 million and the remaining lengths didn't generate any duplicates. So we can say that if we use a length of 15 or above with Scott's functions, then we can generate highly reliable unique strings. Here is the table showing my research data:
Update
I created a simple Heroku app using these functions that returns the token as a JSON response. The app can be accessed at https://uniquestrings.herokuapp.com/api/token?length=15
You can use UUID(Universally Unique Identifier), it can be used for any purpose, from user authentication string to payment transaction id.
A UUID is a 16-octet (128-bit) number. In its canonical form, a UUID is represented by 32 hexadecimal digits, displayed in five groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 alphanumeric characters and four hyphens).
function generate_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0C2f ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
);
}
//calling funtion
$transationID = generate_uuid();
some example outputs will be like:
E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2
hope it helps someone in future :)
This function will generate a random key using numbers and letters:
function random_string($length) {
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
echo random_string(50);
Example output:
zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
I use this one-liner:
base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));
where length is the length of the desired string (divisible by 4, otherwise it gets rounded down to the nearest number divisible by 4)
Use the code below to generate the random number of 11 characters or change the number as per your requirement.
$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);
or we can use custom function to generate the random number
function randomNumber($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $length;$i++)
$digits .= $numbers[$i];
return $digits;
}
//generate random number
$randomNum=randomNumber(11);
Generate a random number using
your favourite random-number
generator
Multiply and divide it
to get a number matching the number
of characters in your code alphabet
Get the item at that index in
your code alphabet.
Repeat from 1) until you have the length you
want
e.g (in pseudo code)
int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
For really random strings, you can use
<?php
echo md5(microtime(true).mt_Rand());
outputs :
40a29479ec808ad4bcff288a48a25d5c
so even if you try to generate string multiple times at exact same time, you will get different output.
This is a simple function that allows you to generate random strings containing Letters and Numbers (alphanumeric). You can also limit the string length.
These random strings can be used for various purposes, including: Referral Code, Promotional Code, Coupon Code.
Function relies on following PHP functions:
base_convert, sha1, uniqid, mt_rand
function random_code($length)
{
return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
}
echo random_code(6);
/*sample output
* a7d9e8
* 3klo93
*/
When trying to generate a random password you are trying to :
First generate a cryptographically secure set of random bytes
Second is turning those random bytes into a printable string
Now, there are multiple way to generate random bytes in php like :
$length = 32;
//PHP 7+
$bytes= random_bytes($length);
//PHP < 7
$bytes= openssl_random_pseudo_bytes($length);
Then you want to turn these random bytes into a printable string :
You can use bin2hex :
$string = bin2hex($bytes);
or base64_encode :
$string = base64_encode($bytes);
However, note that you do not control the length of the string if you use base64.
You can use bin2hex to do that, using 32 bytes will turn into a 64 char string.
But it will only work like so in an EVEN string.
So basically you can just do :
$length = 32;
if(PHP_VERSION>=7){
$bytes= random_bytes($length);
}else{
$bytes= openssl_random_pseudo_bytes($length);
}
$string = bin2hex($bytes);
Here is what I use:
md5(time() . rand());
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
This people choking on a glass of water...
$random= substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*.-_"), 0, 10);
Simple.
The posibility to this random string repeat is 0,000000000000000000000000000001^70
Here is ultimate unique id generator for you. made by me.
<?php
$d=date ("d");
$m=date ("m");
$y=date ("Y");
$t=time();
$dmt=$d+$m+$y+$t;
$ran= rand(0,10000000);
$dmtran= $dmt+$ran;
$un= uniqid();
$dmtun = $dmt.$un;
$mdun = md5($dmtran.$un);
$sort=substr($mdun, 16); // if you want sort length code.
echo $mdun;
?>
you can echo any 'var' for your id as you like. but $mdun is better, you can replace md5 to sha1 for better code but that will be very long which may you dont need.
Thank you.
I like to use hash keys when dealing verification links. I would recommend using the microtime and hashing that using MD5 since there should be no reason why the keys should be the same since it hashes based off of the microtime.
$key = md5(rand());
$key = md5(microtime());
function random_string($length = 8) {
$alphabets = range('A','Z');
$numbers = range('0','9');
$additional_characters = array('_','=');
$final_array = array_merge($alphabets,$numbers,$additional_characters);
while($length--) {
$key = array_rand($final_array);
$password .= $final_array[$key];
}
if (preg_match('/[A-Za-z0-9]/', $password))
{
return $password;
}else{
return random_string();
}
}
Simple 'one line' string hash generator like
77zd43-7bc495-64cg9a-535548 (1byte = 2chars)
$hash = implode('-', [
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
]);
after reading previous examples I came up with this:
protected static $nonce_length = 32;
public static function getNonce()
{
$chars = array();
for ($i = 0; $i < 10; $i++)
$chars = array_merge($chars, range(0, 9), range('A', 'Z'));
shuffle($chars);
$start = mt_rand(0, count($chars) - self::$nonce_length);
return substr(join('', $chars), $start, self::$nonce_length);
}
I duplicate 10 times the array[0-9,A-Z] and shuffle the elements, after I get a random start point for substr() to be more 'creative' :)
you can add [a-z] and other elements to array, duplicate more or less, be more creative than me
<?php
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
above function will generate you a random string which is length of 11 characters.
If you want to generate a unique string in PHP, try following.
md5(uniqid().mt_rand());
In this,
uniqid() - It will generate unique string. This function returns timestamp based unique identifier as a string.
mt_rand() - Generate random number.
md5() - It will generate the hash string.
A simple solution is to convert base 64 to alphanumeric by discarding the non-alphanumeric characters.
This one uses random_bytes() for a cryptographically secure result.
function random_alphanumeric(int $length): string
{
$result='';
do
{
//Base 64 produces 4 characters for each 3 bytes, so most times this will give enough bytes in a single pass
$bytes=random_bytes(($length+3-strlen($result))*2);
//Discard non-alhpanumeric characters
$result.=str_replace(['/','+','='],['','',''],base64_encode($bytes));
//Keep adding characters until the string is long enough
//Add a few extra because the last 2 or 3 characters of a base 64 string tend to be less diverse
}while(strlen($result)<$length+3);
return substr($result,0,$length);
}
Edit: I just revisited this because I need something a bit more flexible. Here is a solution that performs a bit better than the above and gives the option to specify any subset of the ASCII character set:
<?php
class RandomText
{
protected
$allowedChars,
//Maximum index to use
$allowedCount,
//Index values will be taken from a pool of this size
//It is a power of 2 to keep the distribution of values even
$distributionSize,
//This many characters will be generated for each output character
$ratio;
/**
* #param string $allowedChars characters to choose from
*/
public function __construct(string $allowedChars)
{
$this->allowedCount = strlen($allowedChars);
if($this->allowedCount < 1 || $this->allowedCount > 256) throw new \Exception('At least 1 and no more than 256 allowed character(s) must be specified.');
$this->allowedChars = $allowedChars;
//Find the power of 2 equal or greater than the number of allowed characters
$this->distributionSize = pow(2,ceil(log($this->allowedCount, 2)));
//Generating random bytes is the expensive part of this algorithm
//In most cases some will be wasted so it is helpful to produce some extras, but not too many
//On average, this is how many characters needed to produce 1 character in the allowed set
//50% of the time, more characters will be needed. My tests have shown this to perform well.
$this->ratio = $this->distributionSize / $this->allowedCount;
}
/**
* #param int $length string length of required result
* #return string random text
*/
public function get(int $length) : string
{
if($length < 1) throw new \Exception('$length must be >= 1.');
$result = '';
//Keep track of result length to prevent having to compute strlen()
$l = 0;
$indices = null;
$i = null;
do
{
//Bytes will be used to index the character set. Convert to integers.
$indices = unpack('C*', random_bytes(ceil(($length - $l) * $this->ratio)));
foreach($indices as $i)
{
//Reduce to the smallest range that gives an even distribution
$i %= $this->distributionSize;
//If the index is within the range of characters, add one char to the string
if($i < $this->allowedCount)
{
$l++;
$result .= $this->allowedChars[$i];
}
if($l >= $length) break;
}
}while($l < $length);
return $result;
}
}
one can use this code. i tested with 35,000,00 IDs no duplicates.
<?php
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_';
$result = '';
for ($i = 0; $i < 11; $i++)
$result .= $characters[mt_rand(0, 63)];?>
you are free to modify it as your need. and if you have any suggestions feel free to comment.it is recommended that you should check every id in your database before using this ids by doing that you have 100% unique ids in your database.
function codeGenerate() {
$randCode = (string)mt_rand(1000,9999);
$randChar = rand(65,90);
$randInx = rand(0,3);
$randCode[$randInx] = chr($randChar);
return $randCode;
}
echo codeGenerate();
OUTPUT
38I7
33V7
E836
736U
I always use this my function to generate a custom random alphanumeric string... Hope this help.
<?php
function random_alphanumeric($length) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
$my_string = '';
for ($i = 0; $i < $length; $i++) {
$pos = random_int(0, strlen($chars) -1);
$my_string .= substr($chars, $pos, 1);
}
return $my_string;
}
echo random_alphanumeric(50); // 50 characters
?>
It generates for example: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g
If you want compare with another string to be sure that is a unique sequence you can use this trick...
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
if ($string_1 != $string_2) {
break;
}
}
echo $string_1;
echo "<br>\n";
echo $string_2;
it generate two unique strings:
qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi
Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF
Hope this is what you are looking for...
Scott, yes you are very write and good solution! Thanks.
I am also required to generate unique API token for my each user. Following is my approach, i used user information (Userid and Username):
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;
}
Please have a look and let me know if any improvement i can do. Thanks
Here is what I'm using on one of my projects, it's working great and it generates a UNIQUE RANDOM TOKEN:
$timestampz=time();
function generateRandomString($length = 60) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$tokenparta = generateRandomString();
$token = $timestampz*3 . $tokenparta;
echo $token;
Please note that I multiplied the timestamp by three to create a confusion for whoever user might be wondering how this token is generated ;)
I hope it helps :)
I think this is the best method to use.
str_shuffle(md5(rand(0,100000)))
Here is a fun one
public function randomStr($length = 16) {
$string = '';
while (($len = strlen($string)) < $length) {
$size = $length - $len;
$bytes = random_bytes($size);
$string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
}
return $string;
}
Stolen from laravel here
I believe the problem with all the existing ideas is that they are probably unique, but not definitely unique (as pointed out in Dariusz Walczak's reply to loletech). I have a solution that actually is unique. It requires that your script have some sort of memory. For me this is a SQL database. You could also simply write to a file somewhere. There are two implementations:
First method: have TWO fields rather than 1 that provide uniqueness. The first field is an ID number that is not random but is unique (The first ID is 1, the second 2...). If you are using SQL, just define the ID field with the AUTO_INCREMENT property. The second field is not unique but is random. This can be generated with any of the other techniques people have already mentioned. Scott's idea was good, but md5 is convenient and probably good enough for most purposes:
$random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());
Second method: Basically the same idea, but initially pick a maximum number of strings that will ever be generated. This could just be a really big number like a trillion. Then do the same thing, generate an ID, but zero pad it so that all IDs are the same number of digits. Then just concatenate the ID with the random string. It will be random enough for most purposes, but the ID section will ensure that it is also unique.

How to generate unique codes in PHP? [duplicate]

How would it be possible to generate a random, unique string using numbers and letters for use in a verify link? Like when you create an account on a website, and it sends you an email with a link, and you have to click that link in order to verify your account
How can I generate one of those using PHP?
PHP 7 standard library provides the random_bytes($length) function that generate cryptographically secure pseudo-random bytes.
Example:
$bytes = random_bytes(20);
var_dump(bin2hex($bytes));
The above example will output something similar to:
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
More info: http://php.net/manual/en/function.random-bytes.php
PHP 5 (outdated)
I was just looking into how to solve this same problem, but I also want my function to create a token that can be used for password retrieval as well. This means that I need to limit the ability of the token to be guessed. Because uniqid is based on the time, and according to php.net "the return value is little different from microtime()", uniqid does not meet the criteria. PHP recommends using openssl_random_pseudo_bytes() instead to generate cryptographically secure tokens.
A quick, short and to the point answer is:
bin2hex(openssl_random_pseudo_bytes($bytes))
which will generate a random string of alphanumeric characters of length = $bytes * 2. Unfortunately this only has an alphabet of [a-f][0-9], but it works.
Below is the strongest function I could make that satisfies the criteria (This is an implemented version of Erik's answer).
function crypto_rand_secure($min, $max)
{
$range = $max - $min;
if ($range < 1) return $min; // not so random...
$log = ceil(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";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
}
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.
Source: http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
Security Notice: This solution should not be used in situations where the quality of your randomness can affect the security of an application. In particular, rand() and uniqid() are not cryptographically secure random number generators. See Scott's answer for a secure alternative.
If you do not need it to be absolutely unique over time:
md5(uniqid(rand(), true))
Otherwise (given you have already determined a unique login for your user):
md5(uniqid($your_user_login, true))
Object-oriented version of the most up-voted solution
I've created an object-oriented solution based on Scott's answer:
<?php
namespace Utils;
/**
* Class RandomStringGenerator
* #package Utils
*
* Solution taken from here:
* http://stackoverflow.com/a/13733588/1056679
*/
class RandomStringGenerator
{
/** #var string */
protected $alphabet;
/** #var int */
protected $alphabetLength;
/**
* #param string $alphabet
*/
public function __construct($alphabet = '')
{
if ('' !== $alphabet) {
$this->setAlphabet($alphabet);
} else {
$this->setAlphabet(
implode(range('a', 'z'))
. implode(range('A', 'Z'))
. implode(range(0, 9))
);
}
}
/**
* #param string $alphabet
*/
public function setAlphabet($alphabet)
{
$this->alphabet = $alphabet;
$this->alphabetLength = strlen($alphabet);
}
/**
* #param int $length
* #return string
*/
public function generate($length)
{
$token = '';
for ($i = 0; $i < $length; $i++) {
$randomKey = $this->getRandomInteger(0, $this->alphabetLength);
$token .= $this->alphabet[$randomKey];
}
return $token;
}
/**
* #param int $min
* #param int $max
* #return int
*/
protected function getRandomInteger($min, $max)
{
$range = ($max - $min);
if ($range < 0) {
// Not so random...
return $min;
}
$log = log($range, 2);
// Length in bytes.
$bytes = (int) ($log / 8) + 1;
// Length in bits.
$bits = (int) $log + 1;
// Set all lower bits to 1.
$filter = (int) (1 << $bits) - 1;
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
// Discard irrelevant bits.
$rnd = $rnd & $filter;
} while ($rnd >= $range);
return ($min + $rnd);
}
}
Usage
<?php
use Utils\RandomStringGenerator;
// Create new instance of generator class.
$generator = new RandomStringGenerator;
// Set token length.
$tokenLength = 32;
// Call method to generate random string.
$token = $generator->generate($tokenLength);
Custom alphabet
You can use custom alphabet if required.
Just pass a string with supported chars to the constructor or setter:
<?php
$customAlphabet = '0123456789ABCDEF';
// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);
// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);
Here's the output samples
SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa
I hope it will help someone. Cheers!
I'm here with some good research data based on the functions provided by Scott's answer. So I set up a Digital Ocean droplet just for this 5-day long automated test and stored the generated unique strings in a MySQL database.
During this test period, I used 5 different lengths (5, 10, 15, 20, 50) and +/-0.5 million records were inserted for each length. During my test, only the length 5 generated +/-3K duplicates out of 0.5 million and the remaining lengths didn't generate any duplicates. So we can say that if we use a length of 15 or above with Scott's functions, then we can generate highly reliable unique strings. Here is the table showing my research data:
Update
I created a simple Heroku app using these functions that returns the token as a JSON response. The app can be accessed at https://uniquestrings.herokuapp.com/api/token?length=15
You can use UUID(Universally Unique Identifier), it can be used for any purpose, from user authentication string to payment transaction id.
A UUID is a 16-octet (128-bit) number. In its canonical form, a UUID is represented by 32 hexadecimal digits, displayed in five groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 alphanumeric characters and four hyphens).
function generate_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0C2f ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
);
}
//calling funtion
$transationID = generate_uuid();
some example outputs will be like:
E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2
hope it helps someone in future :)
This function will generate a random key using numbers and letters:
function random_string($length) {
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
echo random_string(50);
Example output:
zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
I use this one-liner:
base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));
where length is the length of the desired string (divisible by 4, otherwise it gets rounded down to the nearest number divisible by 4)
Use the code below to generate the random number of 11 characters or change the number as per your requirement.
$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);
or we can use custom function to generate the random number
function randomNumber($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $length;$i++)
$digits .= $numbers[$i];
return $digits;
}
//generate random number
$randomNum=randomNumber(11);
Generate a random number using
your favourite random-number
generator
Multiply and divide it
to get a number matching the number
of characters in your code alphabet
Get the item at that index in
your code alphabet.
Repeat from 1) until you have the length you
want
e.g (in pseudo code)
int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
For really random strings, you can use
<?php
echo md5(microtime(true).mt_Rand());
outputs :
40a29479ec808ad4bcff288a48a25d5c
so even if you try to generate string multiple times at exact same time, you will get different output.
This is a simple function that allows you to generate random strings containing Letters and Numbers (alphanumeric). You can also limit the string length.
These random strings can be used for various purposes, including: Referral Code, Promotional Code, Coupon Code.
Function relies on following PHP functions:
base_convert, sha1, uniqid, mt_rand
function random_code($length)
{
return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
}
echo random_code(6);
/*sample output
* a7d9e8
* 3klo93
*/
When trying to generate a random password you are trying to :
First generate a cryptographically secure set of random bytes
Second is turning those random bytes into a printable string
Now, there are multiple way to generate random bytes in php like :
$length = 32;
//PHP 7+
$bytes= random_bytes($length);
//PHP < 7
$bytes= openssl_random_pseudo_bytes($length);
Then you want to turn these random bytes into a printable string :
You can use bin2hex :
$string = bin2hex($bytes);
or base64_encode :
$string = base64_encode($bytes);
However, note that you do not control the length of the string if you use base64.
You can use bin2hex to do that, using 32 bytes will turn into a 64 char string.
But it will only work like so in an EVEN string.
So basically you can just do :
$length = 32;
if(PHP_VERSION>=7){
$bytes= random_bytes($length);
}else{
$bytes= openssl_random_pseudo_bytes($length);
}
$string = bin2hex($bytes);
Here is what I use:
md5(time() . rand());
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
This people choking on a glass of water...
$random= substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*.-_"), 0, 10);
Simple.
The posibility to this random string repeat is 0,000000000000000000000000000001^70
Here is ultimate unique id generator for you. made by me.
<?php
$d=date ("d");
$m=date ("m");
$y=date ("Y");
$t=time();
$dmt=$d+$m+$y+$t;
$ran= rand(0,10000000);
$dmtran= $dmt+$ran;
$un= uniqid();
$dmtun = $dmt.$un;
$mdun = md5($dmtran.$un);
$sort=substr($mdun, 16); // if you want sort length code.
echo $mdun;
?>
you can echo any 'var' for your id as you like. but $mdun is better, you can replace md5 to sha1 for better code but that will be very long which may you dont need.
Thank you.
I like to use hash keys when dealing verification links. I would recommend using the microtime and hashing that using MD5 since there should be no reason why the keys should be the same since it hashes based off of the microtime.
$key = md5(rand());
$key = md5(microtime());
function random_string($length = 8) {
$alphabets = range('A','Z');
$numbers = range('0','9');
$additional_characters = array('_','=');
$final_array = array_merge($alphabets,$numbers,$additional_characters);
while($length--) {
$key = array_rand($final_array);
$password .= $final_array[$key];
}
if (preg_match('/[A-Za-z0-9]/', $password))
{
return $password;
}else{
return random_string();
}
}
Simple 'one line' string hash generator like
77zd43-7bc495-64cg9a-535548 (1byte = 2chars)
$hash = implode('-', [
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
]);
after reading previous examples I came up with this:
protected static $nonce_length = 32;
public static function getNonce()
{
$chars = array();
for ($i = 0; $i < 10; $i++)
$chars = array_merge($chars, range(0, 9), range('A', 'Z'));
shuffle($chars);
$start = mt_rand(0, count($chars) - self::$nonce_length);
return substr(join('', $chars), $start, self::$nonce_length);
}
I duplicate 10 times the array[0-9,A-Z] and shuffle the elements, after I get a random start point for substr() to be more 'creative' :)
you can add [a-z] and other elements to array, duplicate more or less, be more creative than me
<?php
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
above function will generate you a random string which is length of 11 characters.
If you want to generate a unique string in PHP, try following.
md5(uniqid().mt_rand());
In this,
uniqid() - It will generate unique string. This function returns timestamp based unique identifier as a string.
mt_rand() - Generate random number.
md5() - It will generate the hash string.
A simple solution is to convert base 64 to alphanumeric by discarding the non-alphanumeric characters.
This one uses random_bytes() for a cryptographically secure result.
function random_alphanumeric(int $length): string
{
$result='';
do
{
//Base 64 produces 4 characters for each 3 bytes, so most times this will give enough bytes in a single pass
$bytes=random_bytes(($length+3-strlen($result))*2);
//Discard non-alhpanumeric characters
$result.=str_replace(['/','+','='],['','',''],base64_encode($bytes));
//Keep adding characters until the string is long enough
//Add a few extra because the last 2 or 3 characters of a base 64 string tend to be less diverse
}while(strlen($result)<$length+3);
return substr($result,0,$length);
}
Edit: I just revisited this because I need something a bit more flexible. Here is a solution that performs a bit better than the above and gives the option to specify any subset of the ASCII character set:
<?php
class RandomText
{
protected
$allowedChars,
//Maximum index to use
$allowedCount,
//Index values will be taken from a pool of this size
//It is a power of 2 to keep the distribution of values even
$distributionSize,
//This many characters will be generated for each output character
$ratio;
/**
* #param string $allowedChars characters to choose from
*/
public function __construct(string $allowedChars)
{
$this->allowedCount = strlen($allowedChars);
if($this->allowedCount < 1 || $this->allowedCount > 256) throw new \Exception('At least 1 and no more than 256 allowed character(s) must be specified.');
$this->allowedChars = $allowedChars;
//Find the power of 2 equal or greater than the number of allowed characters
$this->distributionSize = pow(2,ceil(log($this->allowedCount, 2)));
//Generating random bytes is the expensive part of this algorithm
//In most cases some will be wasted so it is helpful to produce some extras, but not too many
//On average, this is how many characters needed to produce 1 character in the allowed set
//50% of the time, more characters will be needed. My tests have shown this to perform well.
$this->ratio = $this->distributionSize / $this->allowedCount;
}
/**
* #param int $length string length of required result
* #return string random text
*/
public function get(int $length) : string
{
if($length < 1) throw new \Exception('$length must be >= 1.');
$result = '';
//Keep track of result length to prevent having to compute strlen()
$l = 0;
$indices = null;
$i = null;
do
{
//Bytes will be used to index the character set. Convert to integers.
$indices = unpack('C*', random_bytes(ceil(($length - $l) * $this->ratio)));
foreach($indices as $i)
{
//Reduce to the smallest range that gives an even distribution
$i %= $this->distributionSize;
//If the index is within the range of characters, add one char to the string
if($i < $this->allowedCount)
{
$l++;
$result .= $this->allowedChars[$i];
}
if($l >= $length) break;
}
}while($l < $length);
return $result;
}
}
one can use this code. i tested with 35,000,00 IDs no duplicates.
<?php
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_';
$result = '';
for ($i = 0; $i < 11; $i++)
$result .= $characters[mt_rand(0, 63)];?>
you are free to modify it as your need. and if you have any suggestions feel free to comment.it is recommended that you should check every id in your database before using this ids by doing that you have 100% unique ids in your database.
function codeGenerate() {
$randCode = (string)mt_rand(1000,9999);
$randChar = rand(65,90);
$randInx = rand(0,3);
$randCode[$randInx] = chr($randChar);
return $randCode;
}
echo codeGenerate();
OUTPUT
38I7
33V7
E836
736U
I always use this my function to generate a custom random alphanumeric string... Hope this help.
<?php
function random_alphanumeric($length) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
$my_string = '';
for ($i = 0; $i < $length; $i++) {
$pos = random_int(0, strlen($chars) -1);
$my_string .= substr($chars, $pos, 1);
}
return $my_string;
}
echo random_alphanumeric(50); // 50 characters
?>
It generates for example: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g
If you want compare with another string to be sure that is a unique sequence you can use this trick...
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
if ($string_1 != $string_2) {
break;
}
}
echo $string_1;
echo "<br>\n";
echo $string_2;
it generate two unique strings:
qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi
Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF
Hope this is what you are looking for...
Scott, yes you are very write and good solution! Thanks.
I am also required to generate unique API token for my each user. Following is my approach, i used user information (Userid and Username):
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;
}
Please have a look and let me know if any improvement i can do. Thanks
Here is what I'm using on one of my projects, it's working great and it generates a UNIQUE RANDOM TOKEN:
$timestampz=time();
function generateRandomString($length = 60) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$tokenparta = generateRandomString();
$token = $timestampz*3 . $tokenparta;
echo $token;
Please note that I multiplied the timestamp by three to create a confusion for whoever user might be wondering how this token is generated ;)
I hope it helps :)
I think this is the best method to use.
str_shuffle(md5(rand(0,100000)))
Here is a fun one
public function randomStr($length = 16) {
$string = '';
while (($len = strlen($string)) < $length) {
$size = $length - $len;
$bytes = random_bytes($size);
$string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
}
return $string;
}
Stolen from laravel here
I believe the problem with all the existing ideas is that they are probably unique, but not definitely unique (as pointed out in Dariusz Walczak's reply to loletech). I have a solution that actually is unique. It requires that your script have some sort of memory. For me this is a SQL database. You could also simply write to a file somewhere. There are two implementations:
First method: have TWO fields rather than 1 that provide uniqueness. The first field is an ID number that is not random but is unique (The first ID is 1, the second 2...). If you are using SQL, just define the ID field with the AUTO_INCREMENT property. The second field is not unique but is random. This can be generated with any of the other techniques people have already mentioned. Scott's idea was good, but md5 is convenient and probably good enough for most purposes:
$random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());
Second method: Basically the same idea, but initially pick a maximum number of strings that will ever be generated. This could just be a really big number like a trillion. Then do the same thing, generate an ID, but zero pad it so that all IDs are the same number of digits. Then just concatenate the ID with the random string. It will be random enough for most purposes, but the ID section will ensure that it is also unique.

PHP: Big integer base 10 represented as string to binary string

I need to convert a really big integer that is represented as a string to a binary string (aka normal integer, but it is always bigger as normal php integer can hold) to efficiently store it in database and have a unique index on it.
The number comes from GMP (gmp_strval()) and may have different lengths, usually about 200-300 "characters" in it, so it never fits into PHP integer. The idea is to convert it into a binary string representing an integer, kind of big integer. Can I do it with PHP?
Sure you can do this.
Remember how to convert a decimal number to binary by hand.
look if the last digit is even (gives a 0) or odd (gives a 1)
subtract the 1, if you get one.
divide by 2. This have to be done digit by digit as in elementary school :-)
repeat this until your decimalnumber become zero.
I wrote a function for this
function strMod2(array $dec)
{
return ((int)end($dec)) % 2;
}
function strDivBy2(array $dec)
{
$res = [];
$carry = 0;
if($dec[0] == '0')
array_shift($dec);
$len = count($dec);
for($i = 0; $i < $len; $i++)
{
$num = $carry*10 + ((int)$dec[$i]);
$carry = $num % 2;
$num -= $carry;
$res[] = $num / 2;
}
return $res;
}
function dec2bin_str($dec)
{
$dec_arr = str_split($dec);
$bin_arr = [];
while(count($dec_arr) > 1 || $dec_arr[0] != 0)
{
array_unshift($bin_arr, strMod2($dec_arr));
$dec_arr = strDivBy2($dec_arr);
}
return implode($bin_arr);
}
You can use it as
echo dec2bin_str('5'); // '101'
echo dec2bin_str('146456131894613465451'); // '1111111000001111100101101000000000000010100001100010101100101101011'
Maybe this can be done faster by using a library for big integers.
Found Math_BigInteger library that can do it:
$a = new Math_BigInteger($intString);
$base256IntString = $a->toBytes();
https://github.com/pear/Math_BigInteger

How to generate a random, unique, alphanumeric string?

How would it be possible to generate a random, unique string using numbers and letters for use in a verify link? Like when you create an account on a website, and it sends you an email with a link, and you have to click that link in order to verify your account
How can I generate one of those using PHP?
PHP 7 standard library provides the random_bytes($length) function that generate cryptographically secure pseudo-random bytes.
Example:
$bytes = random_bytes(20);
var_dump(bin2hex($bytes));
The above example will output something similar to:
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
More info: http://php.net/manual/en/function.random-bytes.php
PHP 5 (outdated)
I was just looking into how to solve this same problem, but I also want my function to create a token that can be used for password retrieval as well. This means that I need to limit the ability of the token to be guessed. Because uniqid is based on the time, and according to php.net "the return value is little different from microtime()", uniqid does not meet the criteria. PHP recommends using openssl_random_pseudo_bytes() instead to generate cryptographically secure tokens.
A quick, short and to the point answer is:
bin2hex(openssl_random_pseudo_bytes($bytes))
which will generate a random string of alphanumeric characters of length = $bytes * 2. Unfortunately this only has an alphabet of [a-f][0-9], but it works.
Below is the strongest function I could make that satisfies the criteria (This is an implemented version of Erik's answer).
function crypto_rand_secure($min, $max)
{
$range = $max - $min;
if ($range < 1) return $min; // not so random...
$log = ceil(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";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
}
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.
Source: http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
Security Notice: This solution should not be used in situations where the quality of your randomness can affect the security of an application. In particular, rand() and uniqid() are not cryptographically secure random number generators. See Scott's answer for a secure alternative.
If you do not need it to be absolutely unique over time:
md5(uniqid(rand(), true))
Otherwise (given you have already determined a unique login for your user):
md5(uniqid($your_user_login, true))
Object-oriented version of the most up-voted solution
I've created an object-oriented solution based on Scott's answer:
<?php
namespace Utils;
/**
* Class RandomStringGenerator
* #package Utils
*
* Solution taken from here:
* http://stackoverflow.com/a/13733588/1056679
*/
class RandomStringGenerator
{
/** #var string */
protected $alphabet;
/** #var int */
protected $alphabetLength;
/**
* #param string $alphabet
*/
public function __construct($alphabet = '')
{
if ('' !== $alphabet) {
$this->setAlphabet($alphabet);
} else {
$this->setAlphabet(
implode(range('a', 'z'))
. implode(range('A', 'Z'))
. implode(range(0, 9))
);
}
}
/**
* #param string $alphabet
*/
public function setAlphabet($alphabet)
{
$this->alphabet = $alphabet;
$this->alphabetLength = strlen($alphabet);
}
/**
* #param int $length
* #return string
*/
public function generate($length)
{
$token = '';
for ($i = 0; $i < $length; $i++) {
$randomKey = $this->getRandomInteger(0, $this->alphabetLength);
$token .= $this->alphabet[$randomKey];
}
return $token;
}
/**
* #param int $min
* #param int $max
* #return int
*/
protected function getRandomInteger($min, $max)
{
$range = ($max - $min);
if ($range < 0) {
// Not so random...
return $min;
}
$log = log($range, 2);
// Length in bytes.
$bytes = (int) ($log / 8) + 1;
// Length in bits.
$bits = (int) $log + 1;
// Set all lower bits to 1.
$filter = (int) (1 << $bits) - 1;
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
// Discard irrelevant bits.
$rnd = $rnd & $filter;
} while ($rnd >= $range);
return ($min + $rnd);
}
}
Usage
<?php
use Utils\RandomStringGenerator;
// Create new instance of generator class.
$generator = new RandomStringGenerator;
// Set token length.
$tokenLength = 32;
// Call method to generate random string.
$token = $generator->generate($tokenLength);
Custom alphabet
You can use custom alphabet if required.
Just pass a string with supported chars to the constructor or setter:
<?php
$customAlphabet = '0123456789ABCDEF';
// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);
// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);
Here's the output samples
SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa
I hope it will help someone. Cheers!
I'm here with some good research data based on the functions provided by Scott's answer. So I set up a Digital Ocean droplet just for this 5-day long automated test and stored the generated unique strings in a MySQL database.
During this test period, I used 5 different lengths (5, 10, 15, 20, 50) and +/-0.5 million records were inserted for each length. During my test, only the length 5 generated +/-3K duplicates out of 0.5 million and the remaining lengths didn't generate any duplicates. So we can say that if we use a length of 15 or above with Scott's functions, then we can generate highly reliable unique strings. Here is the table showing my research data:
Update
I created a simple Heroku app using these functions that returns the token as a JSON response. The app can be accessed at https://uniquestrings.herokuapp.com/api/token?length=15
You can use UUID(Universally Unique Identifier), it can be used for any purpose, from user authentication string to payment transaction id.
A UUID is a 16-octet (128-bit) number. In its canonical form, a UUID is represented by 32 hexadecimal digits, displayed in five groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 alphanumeric characters and four hyphens).
function generate_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0C2f ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
);
}
//calling funtion
$transationID = generate_uuid();
some example outputs will be like:
E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2
hope it helps someone in future :)
This function will generate a random key using numbers and letters:
function random_string($length) {
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
echo random_string(50);
Example output:
zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
I use this one-liner:
base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));
where length is the length of the desired string (divisible by 4, otherwise it gets rounded down to the nearest number divisible by 4)
Use the code below to generate the random number of 11 characters or change the number as per your requirement.
$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);
or we can use custom function to generate the random number
function randomNumber($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $length;$i++)
$digits .= $numbers[$i];
return $digits;
}
//generate random number
$randomNum=randomNumber(11);
Generate a random number using
your favourite random-number
generator
Multiply and divide it
to get a number matching the number
of characters in your code alphabet
Get the item at that index in
your code alphabet.
Repeat from 1) until you have the length you
want
e.g (in pseudo code)
int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
For really random strings, you can use
<?php
echo md5(microtime(true).mt_Rand());
outputs :
40a29479ec808ad4bcff288a48a25d5c
so even if you try to generate string multiple times at exact same time, you will get different output.
This is a simple function that allows you to generate random strings containing Letters and Numbers (alphanumeric). You can also limit the string length.
These random strings can be used for various purposes, including: Referral Code, Promotional Code, Coupon Code.
Function relies on following PHP functions:
base_convert, sha1, uniqid, mt_rand
function random_code($length)
{
return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
}
echo random_code(6);
/*sample output
* a7d9e8
* 3klo93
*/
When trying to generate a random password you are trying to :
First generate a cryptographically secure set of random bytes
Second is turning those random bytes into a printable string
Now, there are multiple way to generate random bytes in php like :
$length = 32;
//PHP 7+
$bytes= random_bytes($length);
//PHP < 7
$bytes= openssl_random_pseudo_bytes($length);
Then you want to turn these random bytes into a printable string :
You can use bin2hex :
$string = bin2hex($bytes);
or base64_encode :
$string = base64_encode($bytes);
However, note that you do not control the length of the string if you use base64.
You can use bin2hex to do that, using 32 bytes will turn into a 64 char string.
But it will only work like so in an EVEN string.
So basically you can just do :
$length = 32;
if(PHP_VERSION>=7){
$bytes= random_bytes($length);
}else{
$bytes= openssl_random_pseudo_bytes($length);
}
$string = bin2hex($bytes);
Here is what I use:
md5(time() . rand());
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
This people choking on a glass of water...
$random= substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*.-_"), 0, 10);
Simple.
The posibility to this random string repeat is 0,000000000000000000000000000001^70
Here is ultimate unique id generator for you. made by me.
<?php
$d=date ("d");
$m=date ("m");
$y=date ("Y");
$t=time();
$dmt=$d+$m+$y+$t;
$ran= rand(0,10000000);
$dmtran= $dmt+$ran;
$un= uniqid();
$dmtun = $dmt.$un;
$mdun = md5($dmtran.$un);
$sort=substr($mdun, 16); // if you want sort length code.
echo $mdun;
?>
you can echo any 'var' for your id as you like. but $mdun is better, you can replace md5 to sha1 for better code but that will be very long which may you dont need.
Thank you.
I like to use hash keys when dealing verification links. I would recommend using the microtime and hashing that using MD5 since there should be no reason why the keys should be the same since it hashes based off of the microtime.
$key = md5(rand());
$key = md5(microtime());
function random_string($length = 8) {
$alphabets = range('A','Z');
$numbers = range('0','9');
$additional_characters = array('_','=');
$final_array = array_merge($alphabets,$numbers,$additional_characters);
while($length--) {
$key = array_rand($final_array);
$password .= $final_array[$key];
}
if (preg_match('/[A-Za-z0-9]/', $password))
{
return $password;
}else{
return random_string();
}
}
Simple 'one line' string hash generator like
77zd43-7bc495-64cg9a-535548 (1byte = 2chars)
$hash = implode('-', [
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
bin2hex(random_bytes(3)),
]);
after reading previous examples I came up with this:
protected static $nonce_length = 32;
public static function getNonce()
{
$chars = array();
for ($i = 0; $i < 10; $i++)
$chars = array_merge($chars, range(0, 9), range('A', 'Z'));
shuffle($chars);
$start = mt_rand(0, count($chars) - self::$nonce_length);
return substr(join('', $chars), $start, self::$nonce_length);
}
I duplicate 10 times the array[0-9,A-Z] and shuffle the elements, after I get a random start point for substr() to be more 'creative' :)
you can add [a-z] and other elements to array, duplicate more or less, be more creative than me
<?php
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
above function will generate you a random string which is length of 11 characters.
If you want to generate a unique string in PHP, try following.
md5(uniqid().mt_rand());
In this,
uniqid() - It will generate unique string. This function returns timestamp based unique identifier as a string.
mt_rand() - Generate random number.
md5() - It will generate the hash string.
A simple solution is to convert base 64 to alphanumeric by discarding the non-alphanumeric characters.
This one uses random_bytes() for a cryptographically secure result.
function random_alphanumeric(int $length): string
{
$result='';
do
{
//Base 64 produces 4 characters for each 3 bytes, so most times this will give enough bytes in a single pass
$bytes=random_bytes(($length+3-strlen($result))*2);
//Discard non-alhpanumeric characters
$result.=str_replace(['/','+','='],['','',''],base64_encode($bytes));
//Keep adding characters until the string is long enough
//Add a few extra because the last 2 or 3 characters of a base 64 string tend to be less diverse
}while(strlen($result)<$length+3);
return substr($result,0,$length);
}
Edit: I just revisited this because I need something a bit more flexible. Here is a solution that performs a bit better than the above and gives the option to specify any subset of the ASCII character set:
<?php
class RandomText
{
protected
$allowedChars,
//Maximum index to use
$allowedCount,
//Index values will be taken from a pool of this size
//It is a power of 2 to keep the distribution of values even
$distributionSize,
//This many characters will be generated for each output character
$ratio;
/**
* #param string $allowedChars characters to choose from
*/
public function __construct(string $allowedChars)
{
$this->allowedCount = strlen($allowedChars);
if($this->allowedCount < 1 || $this->allowedCount > 256) throw new \Exception('At least 1 and no more than 256 allowed character(s) must be specified.');
$this->allowedChars = $allowedChars;
//Find the power of 2 equal or greater than the number of allowed characters
$this->distributionSize = pow(2,ceil(log($this->allowedCount, 2)));
//Generating random bytes is the expensive part of this algorithm
//In most cases some will be wasted so it is helpful to produce some extras, but not too many
//On average, this is how many characters needed to produce 1 character in the allowed set
//50% of the time, more characters will be needed. My tests have shown this to perform well.
$this->ratio = $this->distributionSize / $this->allowedCount;
}
/**
* #param int $length string length of required result
* #return string random text
*/
public function get(int $length) : string
{
if($length < 1) throw new \Exception('$length must be >= 1.');
$result = '';
//Keep track of result length to prevent having to compute strlen()
$l = 0;
$indices = null;
$i = null;
do
{
//Bytes will be used to index the character set. Convert to integers.
$indices = unpack('C*', random_bytes(ceil(($length - $l) * $this->ratio)));
foreach($indices as $i)
{
//Reduce to the smallest range that gives an even distribution
$i %= $this->distributionSize;
//If the index is within the range of characters, add one char to the string
if($i < $this->allowedCount)
{
$l++;
$result .= $this->allowedChars[$i];
}
if($l >= $length) break;
}
}while($l < $length);
return $result;
}
}
one can use this code. i tested with 35,000,00 IDs no duplicates.
<?php
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_';
$result = '';
for ($i = 0; $i < 11; $i++)
$result .= $characters[mt_rand(0, 63)];?>
you are free to modify it as your need. and if you have any suggestions feel free to comment.it is recommended that you should check every id in your database before using this ids by doing that you have 100% unique ids in your database.
function codeGenerate() {
$randCode = (string)mt_rand(1000,9999);
$randChar = rand(65,90);
$randInx = rand(0,3);
$randCode[$randInx] = chr($randChar);
return $randCode;
}
echo codeGenerate();
OUTPUT
38I7
33V7
E836
736U
I always use this my function to generate a custom random alphanumeric string... Hope this help.
<?php
function random_alphanumeric($length) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
$my_string = '';
for ($i = 0; $i < $length; $i++) {
$pos = random_int(0, strlen($chars) -1);
$my_string .= substr($chars, $pos, 1);
}
return $my_string;
}
echo random_alphanumeric(50); // 50 characters
?>
It generates for example: Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86g
If you want compare with another string to be sure that is a unique sequence you can use this trick...
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
if ($string_1 != $string_2) {
break;
}
}
echo $string_1;
echo "<br>\n";
echo $string_2;
it generate two unique strings:
qsBDs4JOoVRfFxyLAOGECYIsWvpcpMzAO9pypwxsqPKeAmYLOi
Ti3kE1WfGgTNxQVXtbNNbhhvvapnaUfGMVJecHkUjHbuCb85pF
Hope this is what you are looking for...
Scott, yes you are very write and good solution! Thanks.
I am also required to generate unique API token for my each user. Following is my approach, i used user information (Userid and Username):
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;
}
Please have a look and let me know if any improvement i can do. Thanks
Here is what I'm using on one of my projects, it's working great and it generates a UNIQUE RANDOM TOKEN:
$timestampz=time();
function generateRandomString($length = 60) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$tokenparta = generateRandomString();
$token = $timestampz*3 . $tokenparta;
echo $token;
Please note that I multiplied the timestamp by three to create a confusion for whoever user might be wondering how this token is generated ;)
I hope it helps :)
I think this is the best method to use.
str_shuffle(md5(rand(0,100000)))
Here is a fun one
public function randomStr($length = 16) {
$string = '';
while (($len = strlen($string)) < $length) {
$size = $length - $len;
$bytes = random_bytes($size);
$string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
}
return $string;
}
Stolen from laravel here
I believe the problem with all the existing ideas is that they are probably unique, but not definitely unique (as pointed out in Dariusz Walczak's reply to loletech). I have a solution that actually is unique. It requires that your script have some sort of memory. For me this is a SQL database. You could also simply write to a file somewhere. There are two implementations:
First method: have TWO fields rather than 1 that provide uniqueness. The first field is an ID number that is not random but is unique (The first ID is 1, the second 2...). If you are using SQL, just define the ID field with the AUTO_INCREMENT property. The second field is not unique but is random. This can be generated with any of the other techniques people have already mentioned. Scott's idea was good, but md5 is convenient and probably good enough for most purposes:
$random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());
Second method: Basically the same idea, but initially pick a maximum number of strings that will ever be generated. This could just be a really big number like a trillion. Then do the same thing, generate an ID, but zero pad it so that all IDs are the same number of digits. Then just concatenate the ID with the random string. It will be random enough for most purposes, but the ID section will ensure that it is also unique.

Categories