Guide to UUID in Java

1. Overview

UUID (Universally Unique Identifier), also known as GUID (Globally Unique Identifier) represents a 128-bit long value that is unique for all practical purposes. The standard representation of the UUID uses hex digits (octets):

123e4567-e89b-12d3-a456-556642440000

A UUID is made of up of hex digits  (4 chars each) along with 4 “-” symbols which make its length equal to 36 characters.

The Nil UUID is a special form of UUID in which all bits are set to zero.

In this article, we will have a look at the UUID class in Java.

Further reading:

CharSequence vs. String in Java

Learn the differences between CharSequence and String.

Read more

Use char[ Array Over a String for Manipulating Passwords in Java?]

Explore several reasons why we shouldn’t use Strings for storing passwords and use char[] arrays instead.

Read more

Guide to Java String Pool

Learn how the JVM optimizes the amount of memory allocated to String storage in the Java String Pool.

Read more

2. Structure

Let’s take the example UUID:

123e4567-e89b-42d3-a456-556642440000
xxxxxxxx-xxxx-Bxxx-Axxx-xxxxxxxxxxxx

A represents the variant which determines the layout of the UUID. All other bits in the UUID depends on the setting of the bits in the variant field. The variant is determined by 3 most significant bit of A:

  MSB1    MSB2    MSB3
   0       X       X     reserved (0)
   1       0       X     current variant (2)
   1       1       0     reserved for Microsoft (6)
   1       1       1     reserved for future (7)

A‘s value in the mentioned UUID is ‘a’. The binary equivalent of ‘a’ (=10xx) shows variant as 2.
B represents the version. The version in the mentioned UUID (value of B) is 4.

Java provides methods for getting variant and version of UUID:__

UUID uuid = UUID.randomUUID();
int variant = uuid.variant();
int version = uuid.version();

These are 5 different versions for variant 2 UUIDs: Time Based (UUIDv1), DCE Security (UUIDv2), Name Based (UUIDv3 and UUIDv5), Random (UUIDv4).

Java provides an implementation for the v3 and v4, but also provides a constructor for generating any type of UUID:

UUID uuid = new UUID(long mostSigBits, long leastSigBits);

2.1. Version 3 & 5

The UUIDs are generated using the hash of namespace and name. The namespace identifiers are UUIDs like Domain Name System (DNS), Object Identifiers (OIDs), URLs etc.

UUID = hash(NAMESPACE_IDENTIFIER + NAME)

The only difference between UUIDv3 and UUIDv5 is the Hashing Algorithm – v3 uses MD5 (128 bits) while v5 uses SHA-1 (160 bits).

Simply put, we truncate the resulting hash to 128-bits and then replace 4 bit for the version and 2 bit for the variant.

Let’s generate type 3 UUID:

String source = namespace + name;
byte[] bytes = source.getBytes("UTF-8");
UUID uuid = UUID.nameUUIDFromBytes(bytes);

Java doesn’t provide the implementation for type 5. Check our source code repository for the UUIDv5.

2.2. Version 4

The UUID v4 implementation uses random numbers as the source. The Java implementation is SecureRandom – which uses an unpredictable value as the seed to generate random numbers to reduce the chance of collisions.

Let’s generate version 4 UUID:

UUID uuid = UUID.randomUUID();

Let’s generate a unique key using ‘SHA-256′ and a random UUID:

MessageDigest salt = MessageDigest.getInstance("SHA-256");
salt.update(UUID.randomUUID().toString().getBytes("UTF-8"));
String digest = bytesToHex(salt.digest());

3. Conclusion

Both UUIDv3 and UUIDv5 have the nice property that different systems can generate the same UUID using the same namespace and name. These are basically used for creating hierarchical UUIDs.

As both the hash functions MD5 and SHA1 have both been broken, using v5 is recommended. If you just need simple UUID generation, type 4 can be OK for the general use-case.

And, as always, the source code of implementation is available over on Github.

Leave a Reply

Your email address will not be published.