¿Qué tan único es UUID?

¿Qué tan seguro es usar UUID para identificar de manera única algo (lo estoy usando para archivos cargados en el servidor)? Según lo entiendo, se basa en números aleatorios. Sin embargo, me parece que dado el tiempo suficiente, eventualmente se lo repetiría solo, por pura casualidad. ¿Hay un mejor sistema o patrón de algún tipo para aliviar este problema?

    Muy seguro:

    Se estima que el riesgo anual de que una persona sea golpeada por un meteor es una posibilidad en 17 mil millones, lo que significa que la probabilidad es de aproximadamente 0.00000000006 (6 × 10 -11 ), lo que equivale a la creación de algunas decenas de trillones de UUID. en un año y tener un duplicado. En otras palabras, solo después de generar mil millones de UUID por segundo durante los próximos 100 años, la probabilidad de crear solo un duplicado sería aproximadamente del 50%.

    Advertencia:

    Sin embargo, estas probabilidades solo se mantienen cuando los UUID se generan utilizando suficiente entropía. De lo contrario, la probabilidad de duplicados podría ser significativamente mayor, ya que la dispersión estadística podría ser menor. Cuando se requieren identificadores únicos para aplicaciones distribuidas, de modo que los UUID no entren en conflicto incluso cuando se combinan datos de muchos dispositivos, la aleatoriedad de las semillas y los generadores utilizados en cada dispositivo debe ser confiable durante la vida de la aplicación. Donde esto no es factible, RFC4122 recomienda usar una variante de espacio de nombres en su lugar.

    Fuente: http://en.wikipedia.org/wiki/UUID#Random_UUID_probability_of_duplicates

    El artículo de Wikepedia tiene esta sección eliminada, pero tienen una referencia útil Enlace externo a ella en otro lugar: http://www.h2database.com/html/advanced.html#uuid

    Si por “dado suficiente tiempo” te refieres a 100 años y los estás creando a un ritmo de mil millones por segundo, entonces sí, tienes un 50% de posibilidades de tener una colisión después de 100 años.

    Hay más de un tipo de UUID, por lo tanto, “qué tan seguro” depende del tipo (que las especificaciones del UUID llaman “versión”) que está utilizando.

    • La versión 1 es el UUID de la dirección MAC más el tiempo. Los 128 bits contienen 48 bits para la dirección MAC de la tarjeta de red (que el fabricante asigna de forma exclusiva) y un reloj de 60 bits con una resolución de 100 nanosegundos. Ese reloj se ajusta en 3603 AD para que estos UUID sean seguros al menos hasta entonces (a menos que necesite más de 10 millones de nuevos UUID por segundo o alguien clone su tarjeta de red). Digo “al menos” porque el reloj comienza el 15 de octubre de 1582, por lo que tiene alrededor de 400 años después de que el reloj se cierra antes de que haya siquiera una pequeña posibilidad de duplicaciones.

    • La versión 4 es el número aleatorio UUID. Hay seis bits fijos y el rest del UUID es de 122 bits de aleatoriedad. Vea Wikipedia u otro análisis que describa cuán poco probable es un duplicado.

    • La versión 3 usa MD5 y la versión 5 usa SHA-1 para crear esos 122 bits, en lugar de un generador de números aleatorio o pseudoaleatorio. Entonces, en términos de seguridad, es como si la Versión 4 fuera un problema estadístico (siempre y cuando se asegure de que lo que procesa el algoritmo de resumen sea siempre único).

    • La versión 2 es similar a la versión 1, pero con un reloj más pequeño, por lo que se ajustará mucho antes. Pero dado que los UUID de la Versión 2 son para DCE, no debería usarlos.

    Entonces, para todos los problemas prácticos, están a salvo. Si no te sientes cómodo con las probabilidades (p. Ej., Eres el tipo de persona preocupada porque la tierra sea destruida por un gran asteroide durante tu vida), solo asegúrate de utilizar un UUID de la Versión 1 y se garantiza que es único ( en su vida, a menos que planee vivir más allá de 3603 AD).

    Entonces, ¿por qué no todos simplemente usan los UUID de la Versión 1? Esto se debe a que los UUID de la Versión 1 revelan la dirección MAC de la máquina en la que se generó y pueden ser predecibles, dos cosas que pueden tener implicaciones de seguridad para la aplicación que usa esos UUID.

    La respuesta a esto puede depender en gran medida de la versión de UUID.

    Muchos generadores UUID usan un número aleatorio de la versión 4. Sin embargo, muchos de ellos usan Pseudo un generador de números aleatorios para generarlos.

    Si se usa un PRNG pobremente sembrado con un período pequeño para generar el UUID, diría que no es muy seguro en absoluto.

    Por lo tanto, solo es tan seguro como los algoritmos utilizados para generarlo.

    Por otro lado, si conoce la respuesta a estas preguntas, entonces creo que una versión 4 uuid debería ser muy segura de usar. De hecho, lo estoy usando para identificar bloques en un sistema de archivos de bloque de red y hasta ahora no he tenido un choque.

    En mi caso, el PRNG que estoy usando es un twister de mersenne y estoy siendo cuidadoso con la forma en que está sembrado, que proviene de múltiples fonts, incluyendo / dev / urandom. El torbellino de Mersenne tiene un período de 2 ^ 19937 – 1. Pasará mucho tiempo antes de que vea una repetición de uuid.

    Citando de Wikipedia :

    Por lo tanto, cualquiera puede crear un UUID y usarlo para identificar algo con la confianza razonable de que el identificador nunca será usado involuntariamente por nadie para nada más

    Continúa explicando con bastante detalle qué tan segura es en realidad. Entonces para responder a su pregunta: Sí, es lo suficientemente seguro.

    Los esquemas de UUID generalmente usan no solo un elemento pseudoaleatorio, sino también la hora actual del sistema, y ​​algún tipo de identificación de hardware a menudo única, si está disponible, como una dirección MAC de red.

    El objective de usar UUID es que confíe en que hará un mejor trabajo al proporcionar una ID única que la que usted mismo podría hacer. Este es el mismo razonamiento detrás del uso de una biblioteca de criptografía de terceros en lugar de desplegar la suya propia. Hacerlo usted mismo puede ser más divertido, pero por lo general es menos responsable hacerlo.

    Estado haciéndolo por años. Nunca se encuentre con un problema

    Normalmente configuro mis bases de datos para tener una tabla que contiene todas las claves, las fechas modificadas y demás. No se ha encontrado con un problema de llaves duplicadas.

    El único inconveniente que tiene es que cuando se escriben algunas consultas para encontrar información rápidamente, se está haciendo una gran cantidad de copias y pegadas de las teclas. Ya no tienes los ID cortos fáciles de recordar.

    Aquí hay un fragmento de prueba para que pruebes que es único. inspirado en el comentario de @ scalabl3

    Lo curioso es que podrías generar 2 seguidas que fueran idénticas, por supuesto en niveles alucinantes de coincidencia, suerte e intervención divina, pero a pesar de las insondables probabilidades, ¡todavía es posible! : D Sí, no sucederá. ¡Solo digo por la diversión de pensar en ese momento en el que creaste un duplicado! ¡Video de captura de pantalla! – scalabl3 20 de octubre de 15 a las 19:11

    Si tiene suerte, marque la checkbox, solo verifica los ID generados actualmente. Si desea una verificación de historial, déjelo sin marcar. Tenga en cuenta que es posible que se quede sin ram en algún momento si lo deja sin marcar. Traté de hacerlo compatible con la CPU para que pueda cancelar rápidamente cuando sea necesario, simplemente pulse el botón de fragmento de ejecución nuevamente o salga de la página.

    Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); } Math.trueRandom = (function() { var crypt = window.crypto || window.msCrypto; if (crypt && crypt.getRandomValues) { // if we have a crypto library, use it var random = function(min, max) { var rval = 0; var range = max - min; if (range < 2) { return min; } var bits_needed = Math.ceil(Math.log2(range)); if (bits_needed > 53) { throw new Exception("We cannot generate numbers larger than 53 bits."); } var bytes_needed = Math.ceil(bits_needed / 8); var mask = Math.pow(2, bits_needed) - 1; // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 // Create byte array and fill with N random numbers var byteArray = new Uint8Array(bytes_needed); crypt.getRandomValues(byteArray); var p = (bytes_needed - 1) * 8; for(var i = 0; i < bytes_needed; i++ ) { rval += byteArray[i] * Math.pow(2, p); p -= 8; } // Use & to apply the mask and reduce the number of recursive lookups rval = rval & mask; if (rval >= range) { // Integer out of acceptable range return random(min, max); } // Return an integer that falls within the range return min + rval; } return function() { var r = random(0, 1000000000) / 1000000000; return r; }; } else { // From http://baagoe.com/en/RandomMusings/javascript/ // Johannes Baagøe , 2010 function Mash() { var n = 0xefc8249d; var mash = function(data) { data = data.toString(); for (var i = 0; i < data.length; i++) { n += data.charCodeAt(i); var h = 0.02519603282416938 * n; n = h >>> 0; h -= n; h *= n; n = h >>> 0; h -= n; n += h * 0x100000000; // 2^32 } return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 }; mash.version = 'Mash 0.9'; return mash; } // From http://baagoe.com/en/RandomMusings/javascript/ function Alea() { return (function(args) { // Johannes Baagøe , 2010 var s0 = 0; var s1 = 0; var s2 = 0; var c = 1; if (args.length == 0) { args = [+new Date()]; } var mash = Mash(); s0 = mash(' '); s1 = mash(' '); s2 = mash(' '); for (var i = 0; i < args.length; i++) { s0 -= mash(args[i]); if (s0 < 0) { s0 += 1; } s1 -= mash(args[i]); if (s1 < 0) { s1 += 1; } s2 -= mash(args[i]); if (s2 < 0) { s2 += 1; } } mash = null; var random = function() { var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 s0 = s1; s1 = s2; return s2 = t - (c = t | 0); }; random.uint32 = function() { return random() * 0x100000000; // 2^32 }; random.fract53 = function() { return random() + (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 }; random.version = 'Alea 0.9'; random.args = args; return random; }(Array.prototype.slice.call(arguments))); }; return Alea(); } }()); Math.guid = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.trueRandom() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); }; function logit(item1, item2) { console.log("Do "+item1+" and "+item2+" equal? "+(item1 == item2 ? "OMG! take a screenshot and you'll be epic on the world of cryptography, buy a lottery ticket now!":"No they do not. shame. no fame")+ ", runs: "+window.numberofRuns); } numberofRuns = 0; function test() { window.numberofRuns++; var x = Math.guid(); var y = Math.guid(); var test = x == y || historyTest(x,y); logit(x,y); return test; } historyArr = []; historyCount = 0; function historyTest(item1, item2) { if(window.luckyDog) { return false; } for(var i = historyCount; i > -1; i--) { logit(item1,window.historyArr[i]); if(item1 == history[i]) { return true; } logit(item2,window.historyArr[i]); if(item2 == history[i]) { return true; } } window.historyArr.push(item1); window.historyArr.push(item2); window.historyCount+=2; return false; } luckyDog = false; document.body.onload = function() { document.getElementById('runit').onclick = function() { window.luckyDog = document.getElementById('lucky').checked; var val = document.getElementById('input').value if(val.trim() == '0') { var intervaltimer = window.setInterval(function() { var test = window.test(); if(test) { window.clearInterval(intervaltimer); } },0); } else { var num = parseInt(val); if(num > 0) { var intervaltimer = window.setInterval(function() { var test = window.test(); num--; if(num < 0 || test) { window.clearInterval(intervaltimer); } },0); } } }; }; 
     Please input how often the calulation should run. set to 0 for forever. Check the checkbox if you feel lucky.

    No sé si esto es importante para usted, pero tenga en cuenta que los GUID son globalmente únicos, pero las subcadenas de GUID no lo son .