Created
February 17, 2017 16:52
-
-
Save jpitoniak/e03505a292854eb2285ad18235ec61aa to your computer and use it in GitHub Desktop.
Generate a cryptographically-secure universally unique identifier (UUID) in PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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