Collisioni UUID [chiuso]


33

Qualcuno ha fatto qualche vera ricerca sulla probabilità di collisioni UUID, in particolare con gli UUID versione 4 (casuali), dato che i generatori di numeri casuali che usiamo non sono veramente casuali e che potremmo avere dozzine o centinaia di macchine identiche che eseguono lo stesso codice generazione di UUID?

I miei colleghi ritengono che il test della collisione UUID sia una completa perdita di tempo, ma inserisco sempre il codice per rilevare un'eccezione chiave duplicata dal database e riprovare con un nuovo UUID. Ma questo non risolverà il problema se l'UUID proviene da un altro processo e fa riferimento a un oggetto reale.


4
Alla domanda era già stata data risposta su Stack Overflow: stackoverflow.com/questions/3038023/… , come mostra la ricerca di base di Google: google.com/search?q=uuid+collision
Arseni Mourzenko

3
Questa domanda riguarda gli algoritmi specifici utilizzati in SQL * Server, che NON è assolutamente una versione 4 (casuale). Sto chiedendo in particolare la versione 4.
Paul Tomblin,

Stai dicendo che l'implementazione della NEWID()funzione di SQL Server non è casuale? In tal caso, hai qualche fonte per eseguire il backup di tale richiesta? Il suo output sembra chiaramente UUID v4 per me. NEWSEQUENTIALID()è decisamente non del tutto casuale, ma questo è il suo scopo : generare UUID che funzionano bene (così come gli UUID possono, almeno) come chiavi di indice.
un CVn del

1
Sto andando dalla risposta alla domanda collegata, che afferma che NEWID () contiene alcuni bit dell'indirizzo mac, che lo rende un UUID V1 o V2, non un V4.
Paul Tomblin,

2
Questa domanda sembra fuori tema perché riguarda qualcosa già discusso ad-nausea su Internet, nei libri e soprattutto su StackOverflow

Risposte:


18

Wikipedia ha alcuni dettagli:

http://en.wikipedia.org/wiki/Universally_unique_identifier

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

Ma la probabilità vale solo se i bit sono perfettamente casuali. Tuttavia, la RFC http://tools.ietf.org/html/rfc4122#page-14 collegata nell'altra risposta definisce questo per la versione 4:

"4.4. [...] L'UUID versione 4 è pensato per generare UUID da numeri veramente casuali o pseudo-casuali. [...] Imposta tutti gli altri bit sui valori scelti casualmente (o pseudo-casualmente)."

Ciò consente praticamente di tutto, dal generatore casuale xkcd http://xkcd.com/221/ a un dispositivo hardware che utilizza il rumore quantico. Le considerazioni sulla sicurezza nella RFC:

"6. Le applicazioni distribuite che generano UUID su una varietà di host devono essere disposte a fare affidamento sull'origine dei numeri casuali su tutti gli host. Se ciò non è fattibile, è necessario utilizzare la variante dello spazio dei nomi."

Ho letto questo come: sei da solo. Sei responsabile del tuo generatore casuale all'interno della tua stessa applicazione, ma questo e tutto il resto si basa sulla fiducia. Se non ti fidi della tua capacità di comprendere e usare correttamente il generatore casuale di tua scelta, allora è davvero una buona idea controllare le collisioni. Se non ti fidi del programmatore degli altri processi, verifica la presenza di collisioni o utilizza una versione UUID diversa.


11

Dovresti certamente rilevare se si verifica una collisione e la tua applicazione dovrebbe generare un'eccezione se si verifica. Ad esempio, se l'UUID viene utilizzato come chiave primaria nel database, il database dovrebbe generare un errore durante l'inserimento di un ID in conflitto.

Tuttavia, ritengo che scrivere codice per generare un nuovo UUID in caso di collisione e provare di nuovo a perdere tempo. La possibilità che si verifichi una collisione è così piccola che lanciare un'eccezione sarebbe un modo perfettamente ragionevole di affrontarla.

Ricorda, non è solo una perdita del tuo tempo a scrivere il codice, ma rende anche il codice più complesso, rendendo più difficile la lettura per la persona successiva, per quasi nessun guadagno.


2
il tuo UUID è buono solo come il tuo generatore casuale. Con una ( molto ) povera si verificheranno non solo collisioni, ma inevitabili. Detto questo, forse verificare la presenza di duplicati al momento della generazione sarebbe davvero eccessivo, ma aspettarsi che la situazione potesse verificarsi e, a mio avviso, non è molto da chiedere. In alcuni domini (ad esempio l'assistenza sanitaria) penso che sia necessario disporre di codice che rilevi tali situazioni (forse come rilevamento delle collisioni nel database). rimarrai sorpreso da quanto tempo ho trascorso situazioni di debug che non si verificano mai.
Newtopiano,

1
Penso di non essermi chiarito. Ho aggiornato la risposta per essere più esplicito.
Pete,

7

Questa è un'ottima domanda Non credo sia stato adeguatamente considerato nella fretta di utilizzare gli UUID ovunque. Non ho trovato nessuna ricerca solida.

Un suggerimento: cammina molto attentamente qui e conosci bene la tua crittografia. Se usi un UUID a 128 bit, l '"effetto compleanno" ci dice che è probabile una collisione dopo aver generato circa 2 ^ 64 chiavi, a condizione che tu abbia 128 bit di entropia in ciascuna chiave .

In realtà è piuttosto difficile garantire che sia così. La vera casualità può essere generata da (a) decadimento radioattivo (b) rumore di fondo casuale, spesso contaminato se non si è attenti (c) rumore elettronico opportunamente scelto, ad esempio prelevato da un diodo Zener polarizzato al contrario. (Ho giocato con l'ultimo, e funziona come un fascino, a proposito).

Non mi fiderei di pronunce come "Non l'ho visto in un anno di utilizzo", a meno che l'utente non abbia generato qualcosa che si avvicina a 2 ^ 64 (cioè circa 10 ^ 19) chiavi e le abbia confrontate tutte l'una contro l'altra, a esercizio non banale.

Il problema è questo Diciamo che hai solo 100 bit di entropia, quando si confrontano le tue chiavi con tutte le altre chiavi che tutti gli altri stanno generando in uno spazio chiave comune. Inizierai a vedere le collisioni tra circa 2 ^ 50 ie. circa 10 ^ 15 tasti. Le possibilità di vedere una collisione se hai popolato il tuo database con solo 1000 miliardi di chiavi sono ancora trascurabili. E se non controlli, in seguito otterrai errori imprevisti che si insinuano nel tuo database di dimensioni peta-row. Questo potrebbe mordere duro.

Il fatto stesso che ci siano più approcci per generare tali UUID dovrebbe causare un momentaneo spasmo di preoccupazione. Quando ti rendi conto che pochi generatori usano processi "veramente casuali" con entropia sufficiente per un UUID di tipo 4, dovresti essere eccessivamente preoccupato a meno che tu non abbia esaminato attentamente il contenuto di entropia del generatore. (La maggior parte delle persone non lo farà, o nemmeno saprà farlo; potresti iniziare con la suite DieHarder). NON confondere la generazione di numeri pseudocasuali con la generazione di numeri casuali reali.

È fondamentale rendersi conto che l'entropia che si inserisce è l'entropia che si possiede e semplicemente perturbare la chiave applicando una funzione crittografica non altera l'entropia. Potrebbe non essere intuitivamente ovvio che se il mio intero spazio comprende le cifre 0 e 1, il contenuto di entropia è lo stesso di quello delle seguenti due stringhe, a condizione che siano le uniche due opzioni: "Questa è una stringa davvero molto complessa 293290729382832 * ! @@ # & ^% $$) ,. m} "e" E ADESSO PER QUALCOSA DIVERSAMENTE COMPLETO ". Ci sono ancora solo due opzioni.

La casualità è difficile da ottenere, e semplicemente credere che "gli esperti l'hanno guardata, quindi è OK" potrebbe non essere sufficiente. I crittografi esperti (e ce ne sono alcuni che sono veramente competenti) sono i primi ad ammettere che spesso sbagliano. Ci siamo fidati di cuore, DigiNotar, ecc.

Penso che Paul Tomblin stia esercitando la dovuta cautela. Il mio 2c.


6

Il problema che hai è che se usi un "generatore di numeri casuali" e non sai quanto sia casuale quel generatore, allora la probabilità di collisione è in realtà sconosciuta. Se i generatori di numeri casuali sono correlati in qualche modo, la probabilità di collisione può aumentare notevolmente - probabilmente molti, molti ordini o entità.

Anche se hai una probabilità molto piccola di collisione, hai un problema fondamentale: la probabilità NON è 0. Ciò significa che alla fine si verificherà una collisione, che non si verificherà molto spesso.

Più frequentemente si generano e si utilizzano gli UUID, prima è probabile che si verifichi una collisione. (generare 1 all'anno significa un tempo di attesa più lungo rispetto alla generazione di un milione al secondo, a parità di altre condizioni).

Se tale probabilità è limitata, sconosciuta e si utilizzano molti UUID, è necessario considerare le conseguenze di una collisione. Se non è accettabile generare un'eccezione e chiudere un'applicazione aziendale, non farlo! (Esempi sulla parte superiore della mia testa: "Va bene chiudere il server web durante l'aggiornamento di un check-in della biblioteca ... non accadrà spesso" e "Va bene chiudere il sistema di gestione stipendi nel mezzo di facendo la corsa ai salari ". Queste decisioni possono essere mosse che limitano la carriera.)

Potresti avere un caso peggiore, sempre a seconda della tua applicazione. Se verifichi la presenza di un UUID (ad esempio, esegui una ricerca) e poi ne fai uno nuovo se uno non è già lì - che è un tipo abbastanza comune di cose da fare - allora potresti scoprire che stai collegando record o stringendo relazioni , quando in realtà si collegano 2 cose tramite un UUID che non deve essere collegato. Questo è qualcosa in cui lanciare un'eccezione non risolverà nulla e hai creato un pasticcio non rilevabile creato da qualche parte. Questo è il genere di cose che porta alla perdita di informazioni e può essere molto imbarazzante. (es: accedi alla tua banca e scopri che puoi vedere il saldo del conto di qualcun altro! Bad!)

Riepilogo: è necessario considerare il modo in cui vengono utilizzati gli UUID e le conseguenze di una collisione. Ciò determina se è necessario prestare attenzione per rilevare ed evitare le collisioni, intraprendere alcune semplici azioni in caso di collisione o fare nulla. Una soluzione semplice, unica e adatta a tutti è probabilmente inappropriata in alcune circostanze.


2
"La probabilità (di collisione) NON è 0" Qualsiasi sequenza a lunghezza finita ha questa proprietà. Anche con un UUID v4 perfettamente casuale, una volta che hai generato 2 ^ 122 UUID unici (128 bit meno 4 bit versione meno 2 bit riservati), il successivo che generi è garantito per essere una collisione. Molto probabilmente verrai colpito prima di una collisione. La domanda più grande è se una collisione dopo qualcosa come 5e36 ripetizioni è un problema e a cui non si può rispondere in generale (anche se è ovviamente possibile rispondere in ogni caso specifico), come dici nel riassunto.
un CVn

Ovviamente. Questa era una dichiarazione dell'ovvio (ma porta ancora a ripetere). Il problema è quanta correlazione hanno i generatori di numeri casuali. Ciò potrebbe aumentare in modo significativo la probabilità di collisione (2 ^ grande), ma quanto è qualcosa che non si saprà a meno che non si eseguano molti scavi, ricerche o calcoli. Supponendo che la probabilità di collisione sia significativamente peggiore di un valore migliore è probabilmente prudente. Dopodiché ... devi quindi considerare le conseguenze.
quick_now

0

Ci sono due problemi coinvolti:

  1. Qualità dei generatori di numeri casuali utilizzati.

  2. Quantità di UUID che possono essere generati.

Un UUID "casuale" ha 122 bit casuali. Supponendo una casualità perfetta, ci si può aspettare la prima collisione intorno a 2 ^ 61 UUID generati (che è la radice quadrata di 2 ^ 122). Se tutti su questa terra generassero un UUID al secondo, questo è 10.000.000.000 * 365 * 24 * 60 * 60 = 315360000000000000 UUID all'anno, che è abbastanza vicino a 2 ^ 58. Cioè, dopo alcuni anni si otterrebbero le prime collisioni. A meno che la tua applicazione non si avvicini a quei numeri, puoi essere abbastanza sicuro che non otterrai una collisione se il tuo generatore casuale è di qualità decente.

Parlando del generatore di numeri casuali: se usi i generatori di librerie C standard (direttamente, indirettamente o generatori simili), probabilmente seminandoli con il tempo, verrai spazzato via. Questi non possono attingere abbastanza entropia per evitare collisioni. Tuttavia, se sei su Linux, leggi solo 16 byte di dati da /dev/urandom: Questo si basa su un pool di entropia che è agitato dal kernel, che ha accesso ad alcuni eventi casuali reali. A meno che in genere non si generino UUID, molto presto nella sequenza di avvio, /dev/urandomdovrebbero comportarsi come una vera fonte casuale.


-1

L'ho provato una volta usando un programma abbastanza semplice (forza bruta) che ha generato 10 milioni di UUID e non ho avuto collisioni.

L' UUID RFC afferma che l'UUID non è solo un gruppo di numeri (pseudo) casuali.


1
La versione 4, che è quella di cui sto chiedendo, è praticamente un gruppo di numeri casuali, tranne i 6 bit che saranno esattamente gli stessi in tutti loro.
Paul Tomblin,

8
10 milioni non sono nemmeno una goccia nel secchio. C'è solo 1 possibilità su 3E30 di una collisione. Se ne avessi trovato uno, ti avrei consigliato di correre fuori e comprare un biglietto in ogni lotteria che puoi!
Ross Patterson,

@RossPatterson, quello che mi chiedevo in particolare è se hai diverse centinaia di computer che usano esattamente lo stesso algoritmo psue-random sullo stesso hardware aumentando notevolmente le probabilità di collisione. Sospetto che lo sarebbe.
Paul Tomblin,

1
@Paul - Avrei pensato solo se l'entropia nel processo iniziale di semina fosse insufficiente, ad esempio se il seme è generato solo dall'ora del giorno e tutte le macchine si sono avviate molto vicino allo stesso istante. Dubito fortemente che il seeding sia così debole - è anche possibile che vengano utilizzati numeri di serie hardware, che ovviamente sarebbero unici per ogni macchina.
Steve314,

1
Purtroppo, la semina può essere molto debole. I sistemi Linux adorano seminare il PRNG da fonti altamente casuali (attività del driver del dispositivo, ecc. ), Ma in altri ambienti, lo standard è utilizzare l'attuale timestamp, che con un numero sufficiente di macchine in stretta sincronizzazione temporale, potrebbe essere un problema.
Ross Patterson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.