libminuid design

libminuid generates non-standard UUIDs (GUIDs). This document explains why it goes for a non-standard model and explains some of the design decisions.

Prior art

Standard UUIDs are widespread. There are accessible implementations. However there are a few drawbacks of them:

Design decisions

Session prefix: random salt

By using a random salt as the first 14 bytes of the UUID, each UUID has 112 bits that should make it unique across different threads/processes. This is somewhat lower, but comparable to the standard UUID version 4's 122 bits.

Using random salt evades the main issues with standard UUIDs:

As a fallback mechanism, on systems not offering /dev/urandom or /dev/random, the host application may add to the salt by using whatever unique identifiers or random sources available.

Suffix: 32 bit unsigned counter

For the purpose of having unique identifiers, a long-enough, properly obtained random number should be enough. However generating such random number may be expensive and in some situations a lot of UUIDs need to be generated at once.

To solve this, libminuid's UUID consists of the long random number session prefix, generated only once per session and a plain integer counter suffix that is simply incremented on each new UUID generation. In the unlikely situation the 32 bit counter overflows, the random prefix should be altered or a new random prefix should be generated.

Typically one process would set up one session, generating one random number. If the application deals with multiple independent contexts, it's also reasonable to create one session per context.

Multi-threaded applications should either initialize one session per thread (that generate UUIDs) or should implement a thin wrapper around libminuid API with locking.

Privacy implications

Because of the session seed and counter, looking at UUIDs there are still three things that can be figured:

Application designers should keep these in mind and where relevant, evade these by using multiple sessions.

String format: base64

Standard UUID uses hexadecimal printout and is written in text form as 32 characters + 4 hyphens, which is total 36 characters (for 128 bits of binary UUID).

Libminuid uses base64 with no separators between prefix and suffix. It takes 24 characters in plain text to encode the 144 bits long binary UUID.

Thus libminuid produces more compact text output with two drawbacks:

Widely used file formats and protocols typically can transmit base64 encoded content or arbitrary text strings so the second drawback shouldn't cause problems in practice.