Laravel str_random() or custom function?

StringFunctionRandomLaravelUuid

String Problem Overview


Is the Laravel str_random() function random enough so that I can use it for IDs?

For example:

str_random(32);

This produces a random string of length 32 made up of alphanumeric characters [a-zA-z0-9] (62 characters in total).

Which equates to 2272657884496751345355241563627544170162852933518655225856 possibilities.

However, my question is, is this going to be good enough? Or should I consider using UUIDs or another custom function.

String Solutions


Solution 1 - String

str_random (Str::random()) tries to use openssl_random_pseudo_bytes which is a pseudo random number generator optimized for cryptography, not uniqueness. If openssl_random_pseudo_bytes is not available, it falls back to quickRandom():

public static function quickRandom($length = 16)
{
	$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

	return substr(str_shuffle(str_repeat($pool, 5)), 0, $length);
}

In my opinion quickRandom code is not reliable for uniqueness nor cryptography.

Yes, having openssl_random_pseudo_bytes and using 32 bytes is almost impossible to see a collision, but it's still possible. If you want to make sure your strings/numbers will be unique (99.99%), you better use a UUID function. This is what I normally use:

/**
 * 
 * Generate v4 UUID
 * 
 * Version 4 UUIDs are pseudo-random.
 */
public static function v4() 
{
	return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',

	// 32 bits for "time_low"
	mt_rand(0, 0xffff), mt_rand(0, 0xffff),

	// 16 bits for "time_mid"
	mt_rand(0, 0xffff),

	// 16 bits for "time_hi_and_version",
	// four most significant bits holds version number 4
	mt_rand(0, 0x0fff) | 0x4000,

	// 16 bits, 8 bits for "clk_seq_hi_res",
	// 8 bits for "clk_seq_low",
	// two most significant bits holds zero and one for variant DCE1.1
	mt_rand(0, 0x3fff) | 0x8000,

	// 48 bits for "node"
	mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
	);
}

It generates a VALID RFC 4211 COMPLIANT version 4 UUID.

Check this: https://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions

Solution 2 - String

you can use this

use Illuminate\Support\Str;

$random = Str::random(40);

Solution 3 - String

The accepted answer was true in April of 2014. It is not accurate anymore. In November of 2014 there was a commit which removed the use of quickRandom. As random_bytes became available in PHP 7 Laravel slowly shifted to that function and uses that one only without any fallback.

ramsey/uuid is the default UUID library in Laravel. By looking at the code we can find out the default random generator is RandomBytesGenerator which uses random_bytes. The same method Str::random uses.

The Wikipedia page about UUID states the following about UUID v4:

> [...] version-4 UUID will have 6 predetermined variant and version bits, leaving 122 bits for the randomly generated part, [...]

https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)

128 bits = 122 random bits + 6 version bits. 128 bits is exactly 16 bytes. Most of the UUID implementations reads 16 bytes of random bytes and then replaces the version at the specified position (in case of v4).

All in all, as of now it is almost the same if you would use Str::random with length equal to 16 or Uuid::uuid4 (without modifying the randomGenerator of Uuid).

Solution 4 - String

To make it more unique use TIMESTAMP and concat row id with it simple and zero possibility to repeat number

Solution 5 - String

You can use this package.

For example:

Uuid::generate()

Solution 6 - String

I'm using Laravel 6 version, on that Illuminate\Support\Str::random works well however neither str_random nor Illuminate\Support\Str::str_random works for me using Laravel 6.

Bellow you can see the function's documentation

/**
* Generate a more truly "random" alpha-numeric string.
*
* @param  int  $length
* @return string
*/
public static function random($length = 16)

Solution 7 - String

the easier one is:

$random = str_random(3).substr(time(), 6,8).str_random(3);

It will generate a 10 digit true unique number.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichaelView Question on Stackoverflow
Solution 1 - StringAntonio Carlos RibeiroView Answer on Stackoverflow
Solution 2 - Stringhashem sheikhypourView Answer on Stackoverflow
Solution 3 - StringNergalView Answer on Stackoverflow
Solution 4 - Stringhu7syView Answer on Stackoverflow
Solution 5 - Stringhosein azimiView Answer on Stackoverflow
Solution 6 - StringLucas GuimaraesView Answer on Stackoverflow
Solution 7 - StringAbdur RahimView Answer on Stackoverflow