Colisiones de UUID [cerrado]

33

¿Alguien ha hecho alguna investigación real sobre la probabilidad de colisiones de UUID, especialmente con UUID de versión 4 (aleatorio), dado que los generadores de números aleatorios que utilizamos no son realmente aleatorios y que podríamos tener docenas o cientos de máquinas idénticas que ejecutan el mismo código generando UUID?

Mis compañeros de trabajo consideran que la prueba de colisión UUID es una pérdida de tiempo completa, pero siempre pongo el código para detectar una excepción de clave duplicada de la base de datos e intentar nuevamente con un nuevo UUID. Pero eso no va a resolver el problema si el UUID proviene de otro proceso y se refiere a un objeto real.

Paul Tomblin
fuente
44
La pregunta ya fue respondida en Stack Overflow: stackoverflow.com/questions/3038023/… , como muestra la búsqueda básica de Google: google.com/search?q=uuid+collision
Arseni Mourzenko
3
Esa pregunta es sobre los algoritmos específicos utilizados en SQL * Server, que definitivamente NO es una versión 4 (aleatoria). Estoy preguntando sobre la versión 4 específicamente.
Paul Tomblin
¿Estás diciendo que la implementación de SQL Server de la NEWID()función no es aleatoria? Si es así, ¿tiene alguna fuente para respaldar tal reclamo? Su salida se ve claramente como v4 UUID para mí. NEWSEQUENTIALID()decididamente no es completamente al azar, pero ese es su propósito : generar UUID que funcionen bien (al igual que los UUID pueden, al menos) como claves de índice.
un CVn
1
Voy por la respuesta a la pregunta vinculada, que establece que NEWID () contiene algunos bits de la dirección mac, lo que lo convierte en un UUID V1 o V2, no un V4.
Paul Tomblin el
2
Esta pregunta parece estar fuera de tema porque se trata de algo ya discutido ad-nauseum en Internet, en libros y especialmente en StackOverflow

Respuestas:

18

Wikipedia tiene algunos detalles:

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

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

Pero la probabilidad solo se mantiene si los bits son perfectamente aleatorios. Sin embargo, el RFC http://tools.ietf.org/html/rfc4122#page-14 vinculado en la otra respuesta define esto para la versión 4:

"4.4. [...] El UUID de la versión 4 está destinado a generar UUID a partir de números verdaderamente aleatorios o pseudoaleatorios. [...] Establezca todos los demás bits en valores elegidos al azar (o pseudoaleatoriamente)".

Esto permite prácticamente cualquier cosa, desde el generador aleatorio xkcd http://xkcd.com/221/ hasta un dispositivo de hardware que utiliza ruido cuántico. Las consideraciones de seguridad en el RFC:

"6. Las aplicaciones distribuidas que generan UUID en una variedad de hosts deben estar dispuestas a confiar en la fuente de números aleatorios en todos los hosts. Si esto no es factible, se debe usar la variante de espacio de nombres".

Leí esto como: Estás solo. Usted es responsable de su generador aleatorio dentro de su propia aplicación, pero esto y cualquier otra cosa se basa en la confianza. Si no confía en su propia capacidad para comprender y utilizar correctamente el generador aleatorio de su elección, entonces es una buena idea verificar las colisiones. Si no confía en el programador de los otros procesos, compruebe si hay colisiones o use una versión de UUID diferente.

Seguro
fuente
11

Sin duda, debe detectar si se produce una colisión, y su aplicación debería lanzar una excepción si sucede. Por ejemplo, si el UUID se usa como clave principal en la base de datos, la base de datos debería arrojar un error al insertar una identificación en colisión.

Sin embargo, creo que escribir código para generar un nuevo UUID en el caso de una colisión y volver a intentarlo es una pérdida de tiempo. La posibilidad de que ocurra una colisión es tan pequeña que lanzar una excepción sería una forma perfectamente razonable de tratarla.

Recuerde, no solo es una pérdida de tiempo escribir el código, sino que también lo hace más complejo, lo que dificulta la lectura de la siguiente persona, casi sin ganancia.

Pete
fuente
2
su UUID es tan bueno como su generador aleatorio. Con un muy ( muy ) pobre, las colisiones no solo ocurrirán, sino que son inevitables. Dicho esto, quizás buscar duplicados en el momento de la generación sería excesivo, pero esperar que la situación pueda ocurrir y, en mi opinión, no es mucho pedir. En algunos dominios (salud, por ejemplo), creo que es necesario tener un código que capte tales situaciones (tal vez como detección de colisión en la base de datos). Te sorprendería cuánto tiempo pasé depurando situaciones que nunca suceden.
Newtopian
1
Creo que no me dejé claro. He actualizado la respuesta para que sea más explícita.
Pete
7

Esta es una muy buena pregunta. No creo que se haya considerado adecuadamente en la prisa por usar UUID en todas partes. No he encontrado ninguna investigación sólida.

Una sugerencia: pise con mucho cuidado aquí y conozca bien su criptografía. Si usa un UUID de 128 bits, el 'efecto de cumpleaños' nos dice que es probable que se produzca una colisión después de haber generado aproximadamente 2 ^ 64 claves, siempre que tenga 128 bits de entropía en cada clave .

En realidad, es bastante difícil garantizar que este sea el caso. La verdadera aleatoriedad puede generarse a partir de (a) la desintegración radiactiva (b) el ruido de fondo aleatorio de la radio, a menudo contaminado a menos que tenga cuidado (c) ruido electrónico elegido adecuadamente, por ejemplo, tomado de un diodo Zener de polarización inversa. (He jugado con el último, y funciona de maravilla, por cierto).

No confiaría en pronunciamientos como "No he visto esto en un año de uso", a menos que el usuario haya generado algo que se acerque a las teclas 2 ^ 64 (es decir, aproximadamente 10 ^ 19), y las haya verificado entre sí, un ejercicio no trivial

El problema es este. Digamos que tiene solo 100 bits de entropía, cuando compara sus claves con todas las otras claves que todos los demás generan en un espacio de claves común. Comenzará a ver colisiones en aproximadamente 2 ^ 50 es decir. Cerca de 10 ^ 15 teclas. Sus posibilidades de ver una colisión si ha llenado su base de datos con solo 1000 mil millones de claves siguen siendo insignificantes. Y si no verifica, más tarde obtendrá errores inesperados que se arrastran en su base de datos del tamaño de una fila peta. Esto podría morder con fuerza.

El hecho mismo de que existen múltiples enfoques para generar tales UUID debería causar un espasmo momentáneo de preocupación. Cuando se da cuenta de que pocos generadores usan procesos 'verdaderamente aleatorios' con suficiente entropía para un UUID tipo 4, debe preocuparse en exceso a menos que haya examinado cuidadosamente el contenido de entropía del generador. (La mayoría de las personas no harán esto, ni siquiera sabrán cómo hacerlo; puede comenzar con la suite DieHarder). NO confunda la generación de números pseudoaleatorios con la verdadera generación de números aleatorios.

Es crítico que te des cuenta de que la entropía que ingresas es la entropía que tienes, y simplemente perturbar la clave aplicando una función criptográfica no altera la entropía. Puede no ser intuitivamente obvio que si todo mi espacio comprende los dígitos 0 y 1, el contenido de entropía es el mismo que el de las siguientes dos cadenas, siempre que sean las únicas dos opciones: "Esta es una cadena realmente muy compleja 293290729382832 * ! @@ # & ^% $$) ,. m} "y" Y AHORA POR ALGO COMPLETAMENTE DIFERENTE ". Todavía hay solo dos opciones.

La aleatoriedad es difícil de entender, y simplemente creer que "los expertos lo han mirado, por lo tanto está bien" puede no ser suficiente. Los criptógrafos expertos (y hay pocos de estos que son realmente competentes) son los primeros en admitir que a menudo se equivocan. Confiamos en heartbleed, DigiNotar, etc.

Creo que Paul Tomblin está ejerciendo la precaución adecuada. Mi 2c.

usuario199506
fuente
6

El problema que tiene es que si usa un "generador de números aleatorios" y no sabe cuán aleatorio es ese generador, entonces la probabilidad de colisión es realmente desconocida. Si los generadores de números aleatorios están correlacionados de alguna manera, la probabilidad de colisión puede aumentar dramáticamente, posiblemente muchos, muchos órdenes o magnitud.

Incluso si tiene una probabilidad muy pequeña de colisión, tiene un problema fundamental: la probabilidad NO es 0. Esto significa que eventualmente ocurrirá una colisión, simplemente no ocurrirá con mucha frecuencia.

Cuanto más frecuentemente genere y use los UUID, más pronto se verá esa colisión. (generar 1 por año significa un tiempo de espera más largo que generar un millón por segundo, todas las demás cosas son iguales).

Si esa probabilidad es finita, desconocida, y usa muchos UUID, entonces debe considerar las consecuencias de una colisión. Si no es aceptable lanzar una excepción y cerrar una aplicación comercial, ¡no lo haga! (Ejemplos en la parte superior de mi cabeza: "Está bien apagar el servidor web en medio de la actualización de un registro de la biblioteca ... no sucederá con frecuencia" y "Está bien cerrar el sistema de nómina en medio de haciendo la carrera de pago ". Estas decisiones pueden ser movimientos que limitan la carrera.)

Sin embargo, es posible que tenga un caso peor, de nuevo dependiendo de su aplicación. Si prueba la presencia de un UUID (es decir, realiza una búsqueda) y luego hace uno nuevo si todavía no está allí, lo cual es algo bastante común, entonces puede encontrar que está vinculando registros o estableciendo relaciones , cuando de hecho está conectando 2 cosas a través de un UUID que no debe conectarse. Esto es algo en lo que arrojar una excepción no resolverá nada y tendrás un desastre indetectable creado en alguna parte. Este es el tipo de cosa que conduce a la fuga de información y puede ser muy vergonzoso. (Ej: ¡Ingrese a su banco y descubra que puede ver el saldo de la cuenta de otra persona! ¡Malo!)

Resumen: debe considerar la forma en que se usan sus UUID y las consecuencias de una colisión. Esto determina si debe tener cuidado para detectar y evitar colisiones, realizar alguna acción simple en caso de colisión o no hacer nada. Es probable que una solución simple, única y adecuada para todos sea inapropiada en algunas circunstancias.

rápidamente_ahora
fuente
2
"La probabilidad (de colisión) NO es 0" Cualquier secuencia de longitud finita tiene esta propiedad. Incluso con un UUID v4 perfectamente aleatorio, una vez que haya generado 2 ^ 122 UUID únicos (128 bits menos la versión de 4 bits menos 2 bits reservados), se garantiza que el próximo que genere será una colisión. Lo más probable es que golpee una colisión antes de eso. La pregunta más importante es si una colisión después de algo así como 5e36 repeticiones es un problema, y ​​eso no se puede responder en general (aunque obviamente es posible responder en cada caso específico), como usted dice en el resumen.
un CVn
Por supuesto. Esta fue una declaración de lo obvio (pero aún vale la pena repetir). El problema es cuánta correlación tienen los generadores de números aleatorios. Esto podría aumentar significativamente la probabilidad de colisión (2 ^ grande), pero cuánto es algo que no sabrá a menos que haga mucha excavación, investigación o cálculo. Asumir que la probabilidad de colisión es significativamente peor que un valor óptimo es probablemente prudente. Después de eso ... entonces debes considerar las consecuencias.
rápidamente_ahora
0

Hay dos problemas involucrados:

  1. Calidad de los generadores de números aleatorios que se utilizan.

  2. Cantidad de UUID que se pueden generar.

Un UUID "aleatorio" tiene 122 bits aleatorios. Suponiendo una aleatoriedad perfecta, puede esperar la primera colisión en alrededor de 2 ^ 61 UUID generados (esa es la raíz cuadrada de 2 ^ 122). Si todos en este mundo generaran un UUID por segundo, eso es 10,000,000,000 * 365 * 24 * 60 * 60 = 315360000000000000 UUID por año, que es bastante cercano a 2 ^ 58. Es decir, después de unos años obtendrías las primeras colisiones. A menos que su aplicación se acerque a esos números, puede estar bastante seguro de que no tendrá una colisión si su generador aleatorio es de buena calidad.

Hablando sobre el generador de números aleatorios: si usa los generadores de bibliotecas C estándar (directa, indirectamente o generadores similares), probablemente los siembra con el tiempo, usted es astuto. Estos no pueden aprovechar suficiente entropía para evitar colisiones. Sin embargo, si está en Linux, solo lea 16 bytes de datos de /dev/urandom: Esto se basa en un grupo de entropía que es agitado por el núcleo, que tiene acceso a algunos eventos aleatorios reales. A menos que normalmente genere UUID realmente, muy temprano en la secuencia de arranque, /dev/urandomdebería comportarse como una verdadera fuente aleatoria.

cmaster
fuente
-1

Lo probé una vez usando un programa bastante simple (fuerza bruta) que generó 10 millones de UUID-s y no he experimentado una colisión.

El UUID RFC dice que el UUID no es solo un grupo de números (pseudo) aleatorios.

xea
fuente
1
La versión 4, que es la que estoy preguntando, es un montón de números aleatorios, excepto los 6 bits que serán exactamente iguales en todos ellos.
Paul Tomblin
8
10 millones ni siquiera son una gota en el cubo. Solo hay una probabilidad de 1 en 3E30 de colisión. ¡Si encontraste uno, te habría aconsejado que salgas corriendo y compres un boleto en cada lotería que puedas!
Ross Patterson el
@RossPatterson, de lo que me preguntaba específicamente es si tienes varios cientos de computadoras que usan exactamente el mismo algoritmo psuedo-random en el mismo hardware, aumenta dramáticamente las probabilidades de colisión. Sospecho que lo haría.
Paul Tomblin
1
@Paul: habría pensado solo si no hay suficiente entropía en el proceso de siembra inicial, por ejemplo, si la semilla solo se genera a partir de la hora del día, y todas sus máquinas se iniciaron muy cerca del mismo instante. Dudo mucho que la distribución sea tan débil, incluso es posible que se utilicen números de serie de hardware, que por supuesto serían únicos para cada máquina.
Steve314
1
Por desgracia, la siembra puede ser muy débil. A los sistemas Linux les gusta sembrar el PRNG de fuentes altamente aleatorias (actividad del controlador del dispositivo, etc. ), pero en otros entornos, el estándar es usar la marca de tiempo actual, que con suficientes máquinas en sincronización de tiempo cercana, podría ser un problema.
Ross Patterson