Is the Laravel str_random() function random enough so that I can use it for IDs?
For example:
str_random(32);
This produces a rando
you can use this
use Illuminate\Support\Str;
$random = Str::random(40);
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
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
. And as random_bytes became available in PHP 7 Laravel slowly shifted to use that function and uses only that without any fallback.
The default UUID library in Laravel is ramsey/uuid. By looking at the code we can find out the default random generator is RandomBytesGenerator
which uses random_bytes
the same method what 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 almost the same if you would use Str::random
with length equal to 16 or Uuid::uuid4
(without any modifying the randomGenerator
of Uuid
).
You can use this package.
For example:
Uuid::generate()