Generatore UUID v1

Genera UUID v1 basati sul tempo con timestamp integrato

Formatta

Quantità:
Note:UUID v1 incorpora l'indirizzo MAC dell'host e il timestamp di generazione, il che solleva problemi di privacy per la maggior parte delle applicazioni moderne. Per i nuovi progetti, UUID v4 è raccomandato a meno che non si abbia specificamente bisogno di identificatori decodificabili ordinati nel tempo.

Cos'è UUID v1?

UUID v1 è la versione UUID originale, standardizzata in RFC 4122 (2005). Genera identificatori univoci combinando un timestamp ad alta precisione con l'indirizzo MAC dell'host generatore, più una breve sequenza di clock per gestire la risoluzione sub-timestamp.

Poiché il timestamp è incorporato, i valori UUID v1 dallo stesso host sono monotonicamente crescenti nel tempo — rendendoli naturalmente ordinati. Questo era progettato per sistemi distribuiti dove ogni nodo poteva generare UUID indipendentemente senza coordinazione.

Oggi UUID v1 è ampiamente superato da UUID v7 (ordinabile, nessuna divulgazione MAC) e UUID v4 (completamente casuale, privato). Rimane in uso in sistemi come Apache Cassandra e database distribuiti legacy.

Anatomia di un UUID v1

Una stringa UUID v1 come 550e8400-e29b-11d4-a716-446655440000 codifica sei campi distinti:

CampoDimensioneDescrizione
time_low32 bitsCampo basso a 32 bit del timestamp gregoriano a 60 bit (intervalli di 100 nanosecondi dal 15 ott. 1582)
time_mid16 bitsCampo medio a 16 bit del timestamp a 60 bit
time_hi_and_version16 bitsI 12 bit superiori del timestamp a 60 bit più il numero di versione a 4 bit (sempre <code>1</code>)
clock_seq_hi_res8 bitsCampo alto della sequenza di clock a 6 bit combinato con il marcatore di variante RFC 4122 a 2 bit
clock_seq_low8 bits8 bit inferiori della sequenza di clock
node48 bitsIdentificatore di nodo a 48 bit — tipicamente l'indirizzo MAC dell'interfaccia di rete generatrice, o un valore casuale a 48 bit se nessun MAC è disponibile

Il campo della sequenza di clock (clock_seq_hi_res + clock_seq_low) è un contatore a 14 bit. Viene incrementato ogni volta che il clock di sistema va indietro (es. regolazione NTP) o quando il sistema si riavvia senza persistere l'ultimo timestamp noto. Questo impedisce la generazione di UUID duplicati se il clock non avanza monotonicamente.

Decodifica del timestamp UUID v1

Il timestamp a 60 bit è distribuito su tre campi nell'UUID. Per ricostruire il tempo di generazione:

  1. Estrarre time_low (byte 0-3), time_mid (byte 4-5) e time_hi (byte 6-7, meno il nibble di versione)
  2. Riassemblare: (time_hi &lt;&lt; 48) | (time_mid &lt;&lt; 32) | time_low
  3. Il risultato è un conteggio a 60 bit di intervalli di 100 nanosecondi dal 15 ottobre 1582 (l'epoch del calendario gregoriano)
  4. Sottrarre l'offset gregoriano-verso-Unix: 122.192.928.000.000.000 (intervalli di 100 ns tra il 15 ott. 1582 e il 1 gen. 1970)
  5. Dividere per 10.000 per convertire gli intervalli di 100 nanosecondi in millisecondi
  6. Usare il risultato come timestamp Unix in millisecondi per costruire un oggetto Date
  7. Formattare in ISO 8601 per output leggibile dall'uomo

La precisione del timestamp è 100 nanosecondi — molto più fine della precisione in millisecondi di UUID v7. Tuttavia, in pratica la maggior parte dei sistemi operativi non espone una risoluzione dell'orologio sub-millisecondo, quindi i bit inferiori sono spesso a zero o sintetizzati.

Problemi di privacy

Lo svantaggio più significativo di UUID v1 è che incorpora l'indirizzo MAC dell'host generatore nel campo node. Ciò significa che ogni UUID v1 porta un'impronta permanente e globalmente univoca della macchina che lo ha generato.

Un avversario che ottiene un UUID v1 può determinare: (1) il tempo approssimativo in cui l'ID è stato generato, (2) l'indirizzo MAC dell'host generatore, e (3) analizzando più UUID, il tasso al quale gli ID vengono generati.

Per questa ragione, UUID v1 non dovrebbe mai essere usato come identificatore pubblico (es. in URL o risposte API) a meno che non si sia a proprio agio nel divulgare queste informazioni. RFC 4122 stesso nota che un sistema può usare un valore casuale a 48 bit invece dell'indirizzo MAC, ma molte implementazioni non lo fanno.

Quando UUID v1 è ancora appropriato

Chiavi primarie Apache Cassandra
Cassandra usa UUID v1 (tramite il tipo TimeUUID) come pattern di design fondamentale. L'ordinamento per timestamp si mappa naturalmente al modello di archiviazione di Cassandra, consentendo query efficienti su intervalli di tempo.
Sistemi distribuiti legacy
Sistemi costruiti prima dell'esistenza di UUID v7 (pre-2024) che si basano su UUID ordinati per timestamp e non possono facilmente migrare a un nuovo formato.
Log di audit ed eventi
Quando l'identità dell'host generatore è nota e fidata, incorporare l'indirizzo MAC può fornire tracciabilità aggiuntiva per gli eventi di audit.
Identificatori interni
ID che non vengono mai esposti al di fuori di un sistema interno controllato, dove la divulgazione dell'indirizzo MAC non è una preoccupazione.
Query su intervalli di tempo senza una colonna timestamp separata
Il timestamp incorporato può essere decodificato per filtrare le righe per tempo di generazione, fungendo da ID e timestamp combinati.
Interoperabilità con vecchi generatori UUID v1
Quando si ricevono o elaborano valori UUID v1 da sistemi esterni che li producono, decodificando il timestamp incorporato per la visualizzazione o l'analisi.

UUID v1 vs UUID v7

UUID v7 è il successore moderno di UUID v1 per gli identificatori ordinati nel tempo. Ecco un confronto diretto:

AspettoUUID v1UUID v7
Epoch / Base temporaleEpoch gregoriano (15 ott. 1582)Epoch Unix (1 gen. 1970)
Precisione100 nanosecondi1 millisecondo
Identificatore nodoIndirizzo MAC (divulga l'identità dell'host)Casuale (privato)
PrivacyDivulga indirizzo MAC e timestamp di generazioneNessuna informazione sull'host incorporata
Prestazioni indice DBBuone — sequenziale per hostEccellenti — k-sortable su tutti i generatori
StandardRFC 4122 (2005)RFC 9562 (2024)

Per i nuovi progetti, UUID v7 è il sostituto raccomandato per UUID v1. Fornisce garanzie simili di ordinamento temporale senza le implicazioni sulla privacy legate all'incorporare l'indirizzo MAC dell'host.

Esempi di codice

La generazione UUID v1 non è disponibile nativamente nei browser o Node.js. Usare il pacchetto npm 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))
}

Domande Frequenti

Posso decodificare il timestamp da un UUID v1?
Sì. Il timestamp di generazione è completamente recuperabile da una stringa UUID v1. Questo strumento fa esattamente questo — incollare qualsiasi UUID v1 e visualizzerà il timestamp UTC decodificato. Vedere i passaggi di decodifica sopra per l'algoritmo.
L'indirizzo MAC è sempre presente in UUID v1?
Non necessariamente. RFC 4122 permette alle implementazioni di sostituire un valore casuale a 48 bit all'indirizzo MAC quando nessuna interfaccia di rete è disponibile o quando si desidera privacy. In pratica, molte implementazioni lato server incorporano il vero indirizzo MAC. I valori UUID v1 generati nel browser usano sempre un valore node casuale poiché i browser non espongono gli indirizzi MAC.
Perché il timestamp UUID v1 usa il 1582 come epoch?
La riforma del calendario gregoriano è entrata in vigore il 15 ottobre 1582. Il timestamp UUID v1 è stato definito rispetto a questa data per fornire un punto di riferimento stabile e universale precedente all'epoch Unix (1970). Questo dà al campo timestamp a 60 bit un range sufficiente per rimanere univoco fino a circa l'anno 3400.
UUID v1 vs UUID v7 — quando usare ancora v1?
Il motivo principale per usare UUID v1 oggi è la compatibilità con sistemi esistenti — in particolare Apache Cassandra, che usa v1 come tipo TimeUUID. Per tutti i nuovi sistemi, UUID v7 è strettamente migliore: usa l'epoch Unix più familiare, non ha divulgazione di indirizzo MAC e offre migliori prestazioni degli indici B-tree.
I valori UUID v1 possono collidere?
In teoria, due valori UUID v1 possono collidere se lo stesso indirizzo MAC genera due UUID all'interno dello stesso intervallo di 100 nanosecondi e la sequenza di clock è identica. La sequenza di clock esiste precisamente per prevenire questo — viene incrementata nelle chiamate successive rapide. In pratica, le collisioni UUID v1 sono estremamente rare nei sistemi correttamente implementati.