UUID, GUID notes

From Helpful
Revision as of 19:41, 26 February 2013 by Helpful (Talk | contribs)

Jump to: navigation, search
This article/section is a stub — probably a pile of half-sorted notes and is probably a first version, is not well-checked, somay have incorrect bits. (Feel free to ignore, or tell me)


For UUIDs used in filesystems, see Fstab#Device)


A UUID is a standardized way of generating a universally unique identifier. (There are a few variants -- see versions and variants).

You may have seen these in windows, mozilla, various RPC mechanisms, and other places.


Why

Say you want to use an identifier on something -- on a lot of things, and distributed among many computers. The most robust way to do that is to check with a central authority that knows about everything previously identified. And, probably, to ask it for a new identifier.

It may be inconvenient to have to use such a service, intractable to host one, and/or be a distributed system's primary bottleneck (though there are ways of making it scale rather better than the simple-and-stupid implementation).


You can use UUIDs when you want independently generated identifiers that have a high probability of being unique. This can be both more convenient and more scalable, and is arguably the primary use case for UUIDs.

UUIDs refer to a mostly-standardized way of generating such identifiers -- a few different methods, some more anonymous (adding hashing, or simply being random) than others.


There are a few different ways of ensuring a value is unlikely to be generated twice.

One idea is to use your network card's MAC address (itself unique), add the current time (preferably in high resolution), and perhaps a (pseudo)random number or incremental counter for good measure. This is pretty simple and cheap to generate.

...but also makes it possible to extract information about its place and time of generation, which isn't ideal in some situations, so there are versions of UUID that are more anonymous.


How

Use a UUID library. In most cases it's easier, and more likely to stick to the standard.


For example:

In Python: Use the uuid module (in the standard library since 2.5), for example
random_uuid = uuid.uuid4()
...which is still an object. You can use str(), or use one of the get_*() functions.


In Java, use java.util.UUID, for example
UUID random_uuid = UUID.randomUUID();
, quite possibly followed by toString().


In .NET, use System.Guid, for example:
random_uuid = System.Guid.NewGuid()
, quite possibly followed by a .ToString()


When you have or want to do it yourself, the simplest (and probably most common) to generate are random UUIDs, i.e. version 4. You can generate a large random number, then twiddle the bits to have it be an RFC-compliant version 4 UUID.

For example, JavaScript has no standard-library function. Perhaps the simplest implementation to generate a random UUID is something like this, but there is a potentially quite real problem in Math.random() not giving randomness guarantees, which is why there are better libraries (with their own PRNGs) which you might as well use. They include:

Layout

A UUID is a 128-bit number, conventionally grouped and dashed as 32-16-16-16-48 bits (8-4-4-4-12 hex characters, 4-2-2-2-6 octets), which reflects the way it is parsed.

The bit layout (from RFC 4122 ):

   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                          time_low                             |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |       time_mid                |         time_hi_and_version   |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |clk_seq_hi_res |  clk_seq_low  |         node (0-1)            |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                         node (2-5)                            |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


Note that various fields are multi-purpose. For example, the 60-bit time value can also be used to store a pseudorandom number, while the node field can be a MAC or a hash of something. (verify)



Versions and variants, a few layout details

This article/section is a stub — probably a pile of half-sorted notes and is probably a first version, is not well-checked, somay have incorrect bits. (Feel free to ignore, or tell me)


The version specifies the means of generation, and is stored in the most significant four bits of time_hi_and_version (octet 6).

...which also means that, in hex representation, you can see the version right after the second dash. For example:

  • 6e8bc430-9c3a-11d9-9669-0800200c9a66 is a version 1 UUID,
  • 550e8400-e29b-41d4-a716-446655440000 is a version 4.


It seems there are currently:

  • 0001: Version 1: Based on time + node (MAC address of any of the cards present)
  • 0010: Version 2: DCE Security version (with embedded POSIX UIDs)
  • 0011: Version 3: Name-based (MD5 hash)
  • 0100: version 4: random
  • 0101: Version 5: Name-based (SHA1 hash)

Versions 1, 3, 4, and 5 are defined in RFC 4122. If the UUID variant is not RFC4122 based, the version value need not necessarily comply to the above.


The variant is specified by the most significant three bits in clk_seq_hi_res (octet 8), and controls the meaning/layout of the rest of the number. Apparently:

  • 001 ?
  • 000 NCS (reserved for backward compatibility)
  • 010 Current variant
  • 011 ?
  • 100 ?
  • 101 ?
  • 110 Microsoft (reserved for backward compatibility)
  • 111 Reserved for future use





See also

  • RFC 4122 (A Universally Unique IDentifier (UUID) URN Namespace)