UUID v1 Generator

Generate time-based UUID v1 with embedded timestamp

Formatera

Antal:
Note:UUID v1 bäddar in värdens MAC-adress och genereringstidsstämpel, vilket väcker integritetsproblem för de flesta moderna applikationer. För nya projekt rekommenderas UUID v4 om du inte specifikt behöver tidsordnade, avkodningsbara identifierare.

Vad är UUID v1?

UUID v1 är den ursprungliga UUID-versionen, standardiserad i RFC 4122 (2005). Den genererar unika identifierare genom att kombinera en högprecisionstidsstämpel med MAC-adressen för den genererande värden, plus en kort klocksekvens för att hantera sub-tidsstämpelupplösning.

Eftersom tidsstämpeln är inbäddad ökar UUID v1-värden från samma värd monotont med tiden — vilket gör dem naturligt ordnade. Detta var utformat för distribuerade system där varje nod kunde generera UUID:n oberoende utan koordination.

Idag är UUID v1 till stor del ersatt av UUID v7 (sorterbar, ingen MAC-läcka) och UUID v4 (helt slumpmässigt, privat). Det används fortfarande i system som Apache Cassandra och äldre distribuerade databaser.

Anatomy of a UUID v1

En UUID v1-sträng som 550e8400-e29b-11d4-a716-446655440000 kodar sex distinkta fält:

FältStorlekBeskrivning
time_low32 bits32-bitars lågt fält av den 60-bitars gregorianska tidsstämpeln (100-nanosekundintervall sedan 15 okt 1582)
time_mid16 bitsMellersta 16-bitars fält av den 60-bitars tidsstämpeln
time_hi_and_version16 bitsTopp 12 bitar av den 60-bitars tidsstämpeln plus det 4-bitars versionsnumret (alltid <code>1</code>)
clock_seq_hi_res8 bits6-bitars klocksekvensfält kombinerat med den 2-bitars RFC 4122-variantmarkören
clock_seq_low8 bitsLägre 8 bitar av klocksekvensen
node48 bits48-bitars nodidentifierare — vanligtvis MAC-adressen för det genererande nätverksgränssnittet, eller ett slumpmässigt 48-bitarsvärde om ingen MAC är tillgänglig

Klocksekvens-fältet (clock_seq_hi_res + clock_seq_low) är en 14-bitars räknare. Den ökas när systemklockan går bakåt (t.ex. NTP-justering) eller när systemet startar om utan att bevara den senast kända tidsstämpeln. Det förhindrar att duplicerade UUID:n genereras om klockan inte är monotont stigande.

Avkoda UUID v1-tidsstämpeln

Den 60-bitars tidsstämpeln är spridd över tre fält i UUID. För att rekonstruera genereringstiden:

  1. Extrahera time_low (byte 0–3), time_mid (byte 4–5) och time_hi (byte 6–7, minus versionsnibble)
  2. Sätt ihop: (time_hi &lt;&lt; 48) | (time_mid &lt;&lt; 32) | time_low
  3. Resultatet är ett 60-bitars antal 100-nanosekundintervall sedan den 15 oktober 1582 (den gregorianska kalenderepoken)
  4. Subtrahera Gregoriansk-till-Unix-offset: 122 192 928 000 000 000 (100-ns intervall mellan 15 okt 1582 och 1 jan 1970)
  5. Dividera med 10 000 för att konvertera 100-nanosekundintervall till millisekunder
  6. Använd resultatet som en Unix-millisekund-tidsstämpel för att skapa ett Date-objekt
  7. Formatera som ISO 8601 för mänskligt läsbar utdata

Tidsstämpelprecisionen är 100 nanosekunder — mycket finare än UUID v7:s millisekundprecision. Men i praktiken exponerar de flesta operativsystem inte sub-millisekund klockupplösning, så de lägre bitarna är ofta noll eller syntetiserade.

Integritetsproblem

Den mest betydande nackdelen med UUID v1 är att det bäddar in MAC-adressen för den genererande värden i nodfältet. Det innebär att varje UUID v1 bär ett permanent, globalt unikt fingeravtryck av maskinen som genererade det.

En angripare som erhåller ett UUID v1 kan bestämma: (1) den ungefärliga tid som ID:t genererades, (2) MAC-adressen för den genererande värden, och (3) genom att analysera flera UUID:n, hastigheten med vilken ID:n genereras.

Av denna anledning bör UUID v1 aldrig användas som en publikt exponerad identifierare (t.ex. i URL:er eller API-svar) om du inte är bekväm med att avslöja denna information. RFC 4122 noterar själv att ett system kan använda ett slumpmässigt 48-bitarsvärde istället för MAC-adressen, men många implementationer gör det inte.

När UUID v1 fortfarande är lämpligt

Apache Cassandra primärnycklar
Cassandra använder UUID v1 (via TimeUUID-typen) som ett kärndesignmönster. Tidsstämpelordningen kartlägger naturligt till Cassandras lagringsmodell, vilket möjliggör effektiva tidsintervallsfrågor.
Äldre distribuerade system
System byggda före UUID v7 existerade (pre-2024) som förlitar sig på tidsstämpelordnade UUID:n och inte enkelt kan migrera till ett nytt format.
Revision och händelseloggar
När den genererande värdens identitet är känd och betrodd kan inbäddning av MAC-adressen ge ytterligare spårbarhet för revisionshändelser.
Interna identifierare
ID:n som aldrig exponeras utanför ett kontrollerat internt system, där MAC-adressavslöjande inte är ett problem.
Tidsintervallsfrågor utan en separat tidsstämpelkolumn
Den inbäddade tidsstämpeln kan avkodas för att filtrera rader efter genereringstid, vilket fungerar som ett kombinerat ID och tidsstämpel.
Interoperabilitet med äldre UUID v1-generatorer
När du tar emot eller bearbetar UUID v1-värden från externa system som producerar dem, avkoda den inbäddade tidsstämpeln för visning eller analys.

UUID v1 vs UUID v7

UUID v7 är den moderna efterträdaren till UUID v1 för tidsordnade identifierare. Här är en direkt jämförelse:

AspektUUID v1UUID v7
Epok / TidsbasGregoriansk epok (15 okt 1582)Unix-epok (1 jan 1970)
Precision100 nanosekunder1 millisekund
NodidentifierareMAC-adress (läcker värdidentitet)Slumpmässig (privat)
IntegritetLäcker MAC-adress och genereringstidsstämpelIngen värdinformation inbäddad
DB-indexprestandaBra — sekventiellt per värdUtmärkt — k-sorterbar över alla generatorer
StandardRFC 4122 (2005)RFC 9562 (2024)

För nya projekt är UUID v7 den rekommenderade ersättningen för UUID v1. Det ger liknande tidsordningsgarantier utan integritetsimplikationerna av att bädda in värdens MAC-adress.

Kodexempel

UUID v1-generering är inte tillgänglig inbyggt i webbläsare eller Node.js. Använd npm-paketet uuid:

JavaScript (browser)
// Generate a UUID v1 using the Web Crypto API
function generateUuidV1() {
  const buf = new Uint8Array(16)
  crypto.getRandomValues(buf)

  const ms = BigInt(Date.now())
  const gregorianOffset = 122192928000000000n
  const t = ms * 10000n + gregorianOffset

  const tLow   = Number(t & 0xFFFFFFFFn)
  const tMid   = Number((t >> 32n) & 0xFFFFn)
  const tHiVer = Number((t >> 48n) & 0x0FFFn) | 0x1000  // version 1

  const clockSeq    = (buf[8] & 0x3F) | 0x80  // variant 10xxxxxx
  const clockSeqLow = buf[9]

  const hex  = (n, pad) => n.toString(16).padStart(pad, '0')
  const node = [...buf.slice(10)].map(b => b.toString(16).padStart(2, '0')).join('')

  return `${hex(tLow,8)}-${hex(tMid,4)}-${hex(tHiVer,4)}-${hex(clockSeq,2)}${hex(clockSeqLow,2)}-${node}`
}

// Extract the embedded timestamp from a UUID v1
function extractTimestamp(uuid) {
  const parts = uuid.split('-')
  const tHex = parts[2].slice(1) + parts[1] + parts[0]
  const t = BigInt('0x' + tHex)
  const ms = (t - 122192928000000000n) / 10000n
  return new Date(Number(ms))
}

const id = generateUuidV1()
console.log(id)                      // e.g. "1eb5e8b0-6b4d-11ee-9c45-a1f2b3c4d5e6"
console.log(extractTimestamp(id))    // e.g. 2023-10-15T12:34:56.789Z
Python
import uuid
from datetime import datetime, timezone

# Generate UUID v1 (uses MAC address by default)
uid = uuid.uuid1()
print(uid)

# Extract embedded timestamp
# uuid.time is 100-ns intervals since Oct 15, 1582
GREGORIAN_OFFSET = 122192928000000000  # 100-ns intervals
ts_100ns = uid.time
ts_ms = (ts_100ns - GREGORIAN_OFFSET) // 10000
dt = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc)
print(dt.isoformat())   # e.g. "2023-10-15T12:34:56.789000+00:00"
Go
package main

import (
    "fmt"
    "time"

    "github.com/google/uuid"  // go get github.com/google/uuid
)

func main() {
    id, _ := uuid.NewUUID()  // UUID v1
    fmt.Println(id)

    // Extract timestamp from UUID v1
    // uuid.Time is 100-ns ticks since Oct 15, 1582
    t := id.Time()
    sec  := int64(t)/1e7 - 12219292800  // convert to Unix seconds
    nsec := (int64(t) % 1e7) * 100
    ts   := time.Unix(sec, nsec).UTC()
    fmt.Println(ts.Format(time.RFC3339Nano))
}

Vanliga frågor

Kan jag avkoda tidsstämpeln från ett UUID v1?
Ja. Genereringstidsstämpeln är helt återhämtningsbar från en UUID v1-sträng. Det här verktyget gör exakt det — klistra in valfritt UUID v1 och det visar den avkodade UTC-tidsstämpeln. Se avkodningsstegen ovan för algoritmen.
Är MAC-adressen alltid närvarande i UUID v1?
Inte nödvändigtvis. RFC 4122 tillåter implementationer att ersätta ett slumpmässigt genererat 48-bitarsvärde för MAC-adressen när inget nätverksgränssnitt är tillgängligt eller när integritet önskas. I praktiken bäddar många serverimplementationer in den riktiga MAC-adressen. Webbläsargenererade UUID v1-värden använder alltid ett slumpmässigt nodvärde eftersom webbläsare inte exponerar MAC-adresser.
Varför använder UUID v1-tidsstämpeln 1582 som epok?
Den gregorianska kalenderreformen trädde i kraft den 15 oktober 1582. UUID v1-tidsstämpeln definierades relativt detta datum för att ge en stabil, universell referenspunkt som föregick Unix-epoken (1970). Det ger det 60-bitars tidsstämpelfältet tillräcklig räckvidd för att förbli unikt till ungefär år 3400 e.Kr.
UUID v1 vs UUID v7 — när ska jag fortfarande använda v1?
Den primära anledningen att använda UUID v1 idag är kompatibilitet med befintliga system — särskilt Apache Cassandra, som använder v1 som sin TimeUUID-typ. För alla nya system är UUID v7 strikt bättre: det använder den mer bekanta Unix-epoken, har ingen MAC-adressläcka och ger bättre B-tree-indexprestanda.
Kan UUID v1-värden kollidera?
I teorin kan två UUID v1-värden kollidera om samma MAC-adress genererar två UUID:n inom samma 100-nanosekundintervall och klocksekvensen är identisk. Klocksekvensen finns just för att förhindra detta — den ökas vid snabba successiva anrop. I praktiken är UUID v1-kollisioner extremt sällsynta i korrekt implementerade system.