Colisiones al generar UUID en JavaScript?


Esto se relaciona con esta pregunta. Estoy usando esta respuesta para generar UUID en JavaScript:

'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
    return v.toString(16);
});

Esta solución parecía estar funcionando bien, sin embargo, estoy recibiendo colisiones. Esto es lo que tengo:

  • Una aplicación web que se ejecuta en Google Chrome.
  • 16 usuarios.
  • estos usuarios han generado alrededor de 4000 UUID en los últimos 2 meses.
  • tengo alrededor de 20 colisiones-por ejemplo, el nuevo UUID generado hoy fue el mismo que hace aproximadamente 2 meses (usuario diferente).

Así que las preguntas son:

  1. ¿Qué está causando el problema?
  2. ¿Cómo puedo evitarlo?
Author: Community, 2011-08-02

5 answers

Mi mejor conjetura es que Math.random() está roto en su sistema por alguna razón (extraño como suena). Este es el primer informe que he visto de alguien teniendo colisiones.

node-uuid tiene un arnés de prueba que puede usar para probar la distribución de dígitos hexadecimales en ese código. Si eso se ve bien, entonces no es Math.random(), así que intente sustituir la implementación de UUID que está utilizando en el método uuid() allí y vea si todavía obtiene buenos resultados.

[Actualización: Acabo de ver a Veselin informe sobre el error con Math.random() al inicio. Dado que el problema es solo al inicio, es poco probable que la prueba node-uuid sea útil. Voy a comentar con más detalle sobre el devoluk.com link.]

 32
Author: broofa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-20 13:21:26

De hecho hay colisiones, pero solo bajo Google Chrome. Echa un vistazo a mi experiencia sobre el tema aquí

Http://devoluk.com/google-chrome-math-random-issue.html

Parece que las colisiones solo ocurren en las primeras llamadas de Matemáticas.aleatorio. Porque si solo ejecuta el método createGUID / testGUIDs anterior (que obviamente fue lo primero que probé) simplemente funciona sin colisiones en absoluto.

Así que para hacer una prueba completa es necesario reiniciar Google Chrome, generar 32 bytes, reiniciar Chrome, generar, reiniciar, generar...

 35
Author: Veselin Kulov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-24 13:43:01

Solo para que otras personas puedan ser conscientes de esto, me estaba topando con un número sorprendentemente grande de colisiones aparentes utilizando la técnica de generación de UUID mencionada aquí. Estas colisiones continuaron incluso después de cambiar a seetrandom para mi generador de números aleatorios. Eso me hizo arrancarme el pelo, como puedes imaginar.

Finalmente me di cuenta de que el problema era (casi?) asociados exclusivamente con los bots de rastreo web de Google. Tan pronto como empecé a ignorar las solicitudes con "googlebot" en el campo user-agent, las colisiones desaparecieron. Supongo que deben almacenar en caché los resultados de los scripts JS de alguna manera semiinteligente, con el resultado final de que su navegador spidering no se puede contar con que se comporte de la manera en que lo hacen los navegadores normales.

Sólo para tu INFORMACIÓN.

 15
Author: Ken Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-05 18:21:58

Quería publicar esto como un comentario a su pregunta, pero al parecer StackOverflow no me deja.

Acabo de ejecutar una prueba rudimentaria de 100,000 iteraciones en Chrome utilizando el algoritmo UUID que publicó y no tiene colisiones. Aquí hay un fragmento de código:

var createGUID = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
}

var testGUIDs = function(upperlimit) {
    alert('Doing collision test on ' + upperlimit + ' GUID creations.');
    var i=0, guids=[];
    while (i++<upperlimit) {
        var guid=createGUID();
        if (guids.indexOf(guid)!=-1) {
            alert('Collision with ' + guid + ' after ' + i + ' iterations');
        }
        guids.push(guid);
    }
    alert(guids.length + ' iterations completed.');
}

testGUIDs(100000);

¿Estás seguro de que no está pasando algo más aquí?

 4
Author: user533676,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-02 12:20:58

La respuesta que originalmente publicó esta solución UUID se actualizó el 2017-06-28:

Un buen artículo de los desarrolladores de Chrome discutir el estado de las matemáticas.calidad PRNG aleatoria en Chrome, Firefox y Safari. tl; dr-A finales de 2015 es "bastante bueno", pero no de calidad criptográfica. Para resolver ese problema, aquí hay una versión actualizada de la solución anterior que usa ES6, la API crypto y un poco de JS wizardy. para:

function uuidv4() {
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  )
}

console.log(uuidv4());
 1
Author: Luke M Willis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-03 18:40:11