UUID v2 Generator
Generate DCE Security UUID v2 with local domain and ID
What is UUID v2?
UUID v2 is the DCE Security UUID version, standardised as part of the Distributed Computing Environment (DCE) specification and referenced in RFC 4122. It extends UUID v1 by embedding a POSIX user or group identifier (UID/GID) into the timestamp field.
The structure is similar to UUID v1, but the 32-bit time_low field is replaced by a 32-bit local identifier (e.g. a POSIX UID) and a 1-byte local_domain field identifies what kind of local ID it is. The timestamp is truncated as a result, reducing its precision and uniqueness guarantees.
UUID v2 is extremely rare in modern software. Most developers will never need to generate one. This page documents the format for completeness and to aid in decoding UUID v2 values encountered in legacy systems.
UUID v2 Structure
A UUID v2 has the same 128-bit, hyphenated format as other UUID versions. The fields differ from UUID v1 as follows:
| Field | Bits | Purpose |
|---|---|---|
| local_id | 32 | <code>local_id</code> — 32-bit local domain identifier (e.g. POSIX UID from <code>/etc/passwd</code>), replaces the time_low field of UUID v1 |
| time_mid | 16 | <code>time_mid</code> — middle 16 bits of the truncated UUID v1 timestamp |
| time_hi+version | 16 | <code>time_hi_and_version</code> — top 12 timestamp bits with version nibble set to <code>2</code> |
| variant+clock_hi | 8 | <code>clock_seq_hi_and_reserved</code> — variant bits plus high portion of clock sequence |
| local_domain | 8 | <code>local_domain</code> — domain identifier: <code>0</code> = POSIX User (UID), <code>1</code> = POSIX Group (GID), <code>2</code> = Organization |
| node | 48 | <code>node</code> — 48-bit MAC address of the generating host |
Example: 000003e8-92e0-21ef-8000-325096b39f47 — local_id 0x000003e8 = UID 1000, local_domain 0x00 = POSIX User
Local Domain Values
The local_domain byte specifies the type of local identifier embedded in the UUID:
The domain values are defined by the DCE specification. Values 3–255 are reserved. In practice, only domain 0 (Person/UID) is commonly encountered in real-world UUID v2 values.
Why UUID v2 Is Rarely Used
Three characteristics make UUID v2 impractical for most modern applications:
Coarse Timestamp Resolution
The timestamp is truncated to 28 bits (approximately 7.2-minute granularity). Within that window, UUIDs generated with the same local_id and domain on the same host are not unique — the spec relies on the clock_seq field to differentiate them, limiting uniqueness to 64 values per 7-minute window.
No Standard Library Support
Unlike UUID v1 and v4, UUID v2 is not supported by most UUID libraries. The uuid npm package, Python's uuid module, and Java's java.util.UUID all omit v2. Custom implementation is required.
POSIX-specific Semantics
The local domain concept (UID/GID) is inherently POSIX-specific and does not translate meaningfully to Windows, embedded systems, or cloud environments where the concept of a POSIX user ID is absent.
Historical Context
UUID v2 was defined as part of the Open Software Foundation's Distributed Computing Environment (DCE/RPC) in the early 1990s. The goal was to create UUIDs that could carry authorization context — specifically, to let an RPC server identify the calling user without a separate authentication step.
The DCE security model assumed a homogeneous POSIX environment where every node participated in a shared UID/GID namespace. The embedded UID would let the server quickly check access control lists without a round-trip to a directory service.
- The internet moved away from homogeneous POSIX environments toward heterogeneous cloud architectures
- Modern authentication uses tokens (JWT, OAuth) rather than embedded UIDs in identifiers
- UUID v4 (fully random) and UUID v7 (time-ordered) cover the practical use cases for unique identifiers
- DCE/RPC itself fell out of widespread use
RFC 4122 (2005) included UUID v2 by reference to the DCE specification, but deliberately omitted the detailed generation algorithm — noting that it was defined by DCE rather than the IETF.
RFC 9562 (2024), which updated the UUID standard, retained UUID v2 for historical completeness but continued to note its POSIX-specific nature and the absence of a complete generation algorithm in the IETF standard.
UUID v2 vs UUID v1
UUID v2 is derived from UUID v1. Here is how they compare:
| Aspect | UUID v1 | UUID v2 |
|---|---|---|
| Timestamp bits | 60 bits (~100ns precision) | 28 bits (~7.2-minute precision) |
| Local identifier | None | 32-bit POSIX UID/GID |
| Local domain | Not present | 0=UID, 1=GID, 2=Org |
| Node field | MAC address | MAC address |
| Library support | Widely supported | Rarely supported |
| Standard | RFC 4122 / RFC 9562 | DCE spec (referenced by RFC 4122) |
| Practical use | Legacy timestamp-ordered IDs (Cassandra) | DCE Security contexts only |
UUID v2 offers nothing over UUID v1 for general-purpose use, and is strictly worse in most respects. There is no reason to choose UUID v2 for new development.
Code Examples
UUID v2 has no native support in standard libraries. The following examples show how to work with UUID v2 values:
Python — manual implementation
import uuid, struct, time
def uuid_v2(local_id: int, local_domain: int = 0) -> str:
"""
Generate a DCE Security UUID (v2).
local_domain: 0 = POSIX UID, 1 = POSIX GID, 2 = Org
local_id: 32-bit unsigned integer (e.g. os.getuid())
"""
# Get a v1 UUID for the time and node fields
v1 = uuid.uuid1()
fields = list(v1.fields) # [time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node]
# Replace time_low with local_id
fields[0] = local_id & 0xFFFFFFFF
# Replace version nibble: clear lower 12 bits of time_hi, set version 2
fields[2] = (fields[2] & 0x0FFF) | 0x2000
# Replace clock_seq_low with local_domain
fields[4] = local_domain & 0xFF
return str(uuid.UUID(fields=tuple(fields)))
import os
print(uuid_v2(os.getuid(), local_domain=0)) # POSIX UID
print(uuid_v2(os.getgid(), local_domain=1)) # POSIX GID
Go — note
// The standard "github.com/google/uuid" package does NOT support v2. // You would need to implement it manually, similar to the Python example above. // Most Go developers use v4 or v7 for new projects. import "github.com/google/uuid" v4 := uuid.New() // v4 — recommended for most use cases v7, _ := uuid.NewV7() // v7 — time-ordered, ideal for database primary keys
JavaScript — extract fields
To extract the local_id and domain from an existing UUID v2 string:
// Extracting fields from a UUID v2 string
const uuidStr = '000003e8-1234-2abc-8200-a1b2c3d4e5f6'
// ^^^^^^^^ ^^^^ ^ ^^
// local_id ver variant+clockSeqHi
// ^^ = local_domain (00 = POSIX UID)
const parts = uuidStr.split('-')
const localId = parseInt(parts[0], 16) // → 1000 (0x3e8)
const version = parseInt(parts[2][0], 16) // → 2
const localDomain = parseInt(parts[3].slice(2), 16) // low byte of octet pair
const DOMAIN_NAMES = ['POSIX UID', 'POSIX GID', 'Org']
console.log(`Local ID: ${localId}`) // Local ID: 1000
console.log(`Version: ${version}`) // Version: 2
console.log(`Domain: ${DOMAIN_NAMES[localDomain]}`) // Domain: POSIX UID
google/uuid Go package supports UUID v2 generation via uuid.NewDCEGroup() and uuid.NewDCEPerson() — one of the few mainstream libraries that does.