Skip to content

Instantly share code, notes, and snippets.

@jpitoniak
Created February 17, 2017 16:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpitoniak/e03505a292854eb2285ad18235ec61aa to your computer and use it in GitHub Desktop.
Save jpitoniak/e03505a292854eb2285ad18235ec61aa to your computer and use it in GitHub Desktop.
Generate a cryptographically-secure universally unique identifier (UUID) in PHP
<?php
/**
* Generate a universally unique identifier (UUID)
*
* Generates a universally unique identifier (UUID), also referred to as a globally
* unique identifier (GUID) using the best-available source of cryptographically-secure
* random data. If no adequate source of random data is available, an exception is thrown.
*
* Possible sources of random data include:
* * random_bytes() function, available in PHP7+
* * openssl_random_pseudo_bytes() function, available in the OpenSSL extension
* * com_create_guid() function, available in Windows versions of PHP
* * reading data from /dev/urandom, available in *nix operating systems
* * calling the external 'uuidgen' command, mainly available in *nix systems
* @author Jason R. Pitoniak <jason~interbrite.com>
* @throws Exception thrown if no suitable source of random data is available
* @return string a properly formatted UUID string
* @license MIT
*/
function getUUID()
{
if(function_exists('random_bytes')) {
//random_bytes is the preferred CSPRNG method for PHP >= 7
$r = random_bytes(16);
}
else if(function_exists('openssl_random_pseudo_bytes')) {
//this will work if the openssl library is available
$r = openssl_random_pseudo_bytes(16);
}
else if(function_exists('com_create_guid')) {
//this will work on Windows machines
$r = com_create_guid();
//it reurns a GUID (a UUID wrapped in cury braces) rather than random bytes,
//so just strip out the braces and return the result
return substr($r, 1, -1);
}
else if(file_exists('/dev/urandom')) {
//if none of the above worked, we can read random data from /dev/urandom on *nix machines
$r = fread(fopen('/dev/urandom', 'r'),16);
}
if(empty($r)) {
//wow...all that and still nothing? let's see if the machine has the uuidgen command
$uuid = exec('uuidgen', $out, $rtn);
if($rtn == 0) {
//looks like it worked
return trim($uuid);
}
else {
//still no UUID...I give up
throw new Exception('Cannot generate UUID: Unable to find a suitable source of random data.');
}
}
$r = unpack('v*', $r);
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
$r[1], $r[2], $r[3], $r[4] & 0x0fff | 0x4000,
$r[5] & 0x3fff | 0x8000, $r[6], $r[7], $r[8]);
return $uuid;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment