João Freitas

The following is a teardown on UUIDs history, their different versions, when they should be used, and how they are constructed. The author also shares the probability of collision, for a specific UUID usage scenario.

https://duo.com/labs/tech-notes/breaking-down-uuids


Universally Unique Identifiers, or UUIDS, are 128 bit numbers, composed of 16 octets and represented as 32 base-16 characters, that can be used to identify information across a computer system. This specification was originally created by Microsoft and standardized by both the IETF and ITU.

UUIDs are generally used for identifying information that needs to be unique within a system or network thereof. Their uniqueness and low probability in being repeated makes them useful for being associative keys in databases and identifiers for physical hardware within an organization. One of the benefits to UUIDs is that they don’t need to be issued by a central authority, but can be generated independently and then used across a given system without suspicion that a duplicate. or colliding, UUID has been generated elsewhere. Apple, Microsoft, Samsung, and others use UUIDs, either defined by the IETF spec or a proprietary variant, to identify and track hardware both internally and sold to consumers.

There are 5 different versions of UUIDs, excluding the Nil UUID version, which is a special case UUID where all its bytes are set to 0, and most contain some variants that allow for special cases specific to vendors like Microsoft. Version 1 and 2 use time-based sources (a 60 bit timestamp sourced from the system clock) for its randomness. Versions 1 and 2 are effectively the same, except in the latter version the least significant bits of the of the clock sequence are replaced with an identifier specific to the system. Most implementations, because of this and other reasons, omit version 2. Version 1 is the most commonly used of the UUID versions.

Versions 3 and 5 are generated by hashing a name or namespace identifier and using the resultant hash, MD5 or SHA-1 respectively, as the source of uniqueness instead of the time-based sources like in versions 1 and 2. They are meant for generating UUIDs from names that are drawn from, and unique within, some name space. The concept of name and name space should be broadly construed, and not limited to textual names. For example, some name spaces are the domain name system, URLs, ISO Object IDs (OIDs), X.500 Distinguished Names (DNs), and reserved words in a programming language.

Version 4 uses random or pseudo-random sources rather than time or namespace-derived sources for its uniqueness. Versions 3, 4, and 5 use their respective sources to generate 60 bits of unique output that is used in lieu of the timestamp bits used in versions 1 and 2.

01. UUID Generation

To show how the UUID is derived, we’ll go through how a version 1 UUID is created. For versions 3 through 5, the clock sequence sources mentioned below should be replaced with their respective sources. The V1 UUID string is derived into an ordered sequence of 6 fields from that give the ID a great (but not non-zero) chance of being completely unique. UUID records are derived from the following sources, in big-endian fashion, as follows:

This yields a string that would look like this for example:

123e4567-e89b-12d3-a456-426655440000

02. What makes UUIDs Versions unique?

To further break down what gives us faith in why a given UUID is most likely unique, let’s look at the sources of UUID data for the different UUID versions a bit more:

Versions 1 & 2

For these versions we have 74 bits of time data, 60 bits from the timestamp and 14 from the clock sequence. Along with that we have the 48-bit Node ID, which could be the MAC or, in some cases where we may not want to expose it or the Node does not have a MAC, a 48 random or pseudo-random bits. Ideally (for the UUID version, not for us) however if we have the MAC and, in combination with the timestamp and clock sequence, we are given an ID that correlates to a single point in space (the node MAC) and time (timestamp and clock sequence). If the ideal case holds true, a node is capable of generating 274 (18 Sextillion), but if no MAC is given we have an additional 48 bits of uniqueness, yielding 2122 (5.3 undecillion) possible UUIDs for a node.

Versions 3 & 5

If you want to have unique identifiers for “name-able” information and data within a namespace of your system stored in a UUID format and make sure that duplicate resource names do not occur across your system, this is the version to use. According to the spec, Version 5 is preferred, since it uses SHA-1.

Version 4

The most “unique” of the versions. As with the other versions, 4 bits are used to indicate the version, and 2 or 3 bits depending on the variant are used to indicate the variant of the UUID. this leaves either 2122 (5.3 × 1036) or, for v4 variant 2, half as many possible unique IDs there is one less random bit. Still the chances of collision are extremely small.

03. Chances of Collision

The chance of a collision occurring where two identical UUIDS are generated at the same time on the same node is incredibly small, and the probability of collision can be calculated using the Birthday Problem. For example, if we have 68,719,476,736 UUIDs with 74 random bits , the probability of a duplicate would be 0.1175030974154045 but If we have 122 random bits the probability would be 0.0000000000000004. If a user was generating all UUIDs for a system using a single node, they may want to consider using UUID version 4 rather than 1, since the chance of collision is much greater.

#reads #nick steele #uuid