PHP UUID generator function

Universally Unique Identifier is an identifier standard which is used in a varieties of software construction. When I was writing the RSS Writer class for Orchid, I needed to generate UUID to implement with ATOM id. I searched the web for a simple solution but didn’t find any that suffices my need. Then I wrote the following function to generate it. I’ve use the standard of canonical format here.

Let’s take a look what Wikipedia has to say about the format of UUID :

A UUID is a 16-byte (128-bit) number. The number of theoretically possible UUIDs is therefore 216*8 = 2128 = 25616 or about 3.4 × 1038. This means that 1 trillion UUIDs would have to be created every nanosecond for 10 billion years to exhaust the number of UUIDs.

In its canonical form, a UUID consists of 32 hexadecimal digits, displayed in 5 groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters.

Enough said 🙂 Here is the function.

/**
  * Generates an UUID
  *
  * @author     Anis uddin Ahmad
  * @param      string  an optional prefix
  * @return     string  the formatted uuid
  */
function uuid($prefix = '')
{
    $chars = md5(uniqid(mt_rand(), true));
    $parts = [substr($chars,0,8), substr($chars,8,4), substr($chars,12,4), substr($chars,16,4), substr($chars,20,12)];

    return $prefix . implode($parts, '-');;
}

Example of using the function –

//Using without prefix.
//Returns like: 1225c695-cfb8-4ebb-aaaa-80da344e8352
echo uuid();

//Using with prefix
//Returns like: urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344e8352
echo uuid('urn:uuid:');

See you.

UPDATE : The PHP Universal Feed Generator class, for which I wrote this function is released.

UPDATE: The method of getting random string changed based on Davids comment. (Thanks to David)

UPDATE: Updated syntax. Made more concise using features of recent PHP versions.

22 Comments

  1. the guys posting on the php docs for uniqid() function (http://php.net/uniqid) raise a good point that it might be better to feed the output from md5 into uniqid() rather than the other way around. md5() generates hashes and therefore you are taking a chance of a collision by accident.

    just a quick fix:
    – $chars = md5(uniqid(rand()));
    + $chars = uniqid(md5(rand()));

    thanks for a quick function to make uuids.

  2. @Chris

    Thanks for the heads up, but the poster at php.net has fundametally misunserstood what a hash collision is or means – a hash collision is where the chances of finding two different input strings which produce the same hash are reduced enough to (arguably, in theory only) warrant implementing the vast computing power necessary to do so, and offers no guarantees as to the clashing string’s usefulness in any security context. As security holes go, md5 clashes receive rather more press than they deserve.

    A UUID (wikipedia) is a 16-byte (128-bit) number. The number of theoretically possible UUIDs is therefore 216*8 = 2128 = 25616 or about 3.4 × 1038. This means that 1 trillion UUIDs would have to be created every nanosecond for slightly more than 10 billion years to exhaust the number of UUIDs.

    Whilst a Crptographicall Secure Pseudo Random number Generator is recommended for generating UUIDs, I’d hedge a bet that if you were to make up the UUIDS for a database of 100M entries yourself from imagination alone, we’d be pretty safe against clashes 🙂

  3. *Use this function at your own risk*

    To quote Wikipedia:

    “The probability [of generating a duplicate UUID] also depends on the quality of the random number generator. A cryptographically secure pseudorandom number generator must be used to generate the values, otherwise the probability of duplicates may be significantly higher.”

    This function has no proof that it meets the standards for a “cryptographically secure pseudorandom number generator”. It also doesn’t conform to any of the Version 1 thru 5 method of generating a string with sufficient randomness.

    In other words, the chances of generating duplicate UUIDs may be unacceptably high when using this function.

  4. Thnaks david,
    I’ve tried to update the method of getting random string based on you comment.
    Hope it’s stronger at the point of randomaization now.

    Thanks again for your comment

  5. You missed to include proper markers for the version of UUIDs you’re generating. Probably most systems might ignore this, but some might reject to work with e.g. version 1 UUID. So here is another approach to properly generate version 4 UUIDs:

    mt_srand( intval( microtime( true ) * 1000 ) );
    $b = md5( uniqid( mt_rand(), true ), true );
    $b[6] = chr( ( ord( $b[6] ) & 0x0F ) | 0x40 );
    $b[8] = chr( ( ord( $b[8] ) & 0x3F ) | 0x80 );
    return implode( ‘-‘, unpack( ‘H8a/H4b/H4c/H4d/H12e’, $b ) );

    I’ve included a time-based seeding of RNG, which might be relocated to a separate method as it isn’t intended to be done that frequently as on each call for generating another UUID but once a runtime …

  6. I recently used a UUID generation scheme for a project which is described:

    http://roshankulkarni.info/?p=3

    This was used on a distributed application with about 4 PHP servers and a few million database records. The application was not very mission critical.

    While this scheme is not cryptographically secure – it worked well in our scenario and offered a good key distribution and a low collision probability.

  7. When I need to guarantee uniqueness, I append a userID number to the output of uniqid. A single user can’t submit data more than once in a microsecond. A computer could, but I’m developing solely for human input.

  8. Wonderful blog! I actually love how it’s easy on my eyes and also the facts are well written. I am wondering how I can be notified whenever a new post has been made. I have subscribed to your rss feed which ought to do the trick! Have a nice day!

Leave a Comment

Your email address will not be published. Required fields are marked *