Kolizje podczas generowania uuid w JavaScript

Dotyczy to tego pytania . Używam poniższego kodu z this answer do generowania UUID w 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);
});

To rozwiązanie wydaje się działać dobrze, ale dostaję kolizji. Oto co mam:

  • Aplikacja internetowa działająca w Google Chrome.
  • 16 użytkowników.
  • około 4000 uuid zostało wygenerowanych przez tych użytkowników w ciągu ostatnich dwóch miesięcy.
  • mam około 20 kolizji - np. wygenerowano nowy UUID dzisiaj było tak samo jak jakieś dwa miesiące temu(inny użytkownik).

Co powoduje ten problem i jak mogę go uniknąć?

Author: Peter Mortensen, 2011-08-02

6 answers

Moje najlepsze przypuszczenie jest to, że Math.random() jest uszkodzony w systemie z jakiegoś powodu(dziwnie to brzmi). To pierwszy raport, jaki widziałem, kiedy ktoś miał kolizje.

node-uuid posiada uprząż testową , której można użyć do sprawdzenia rozkładu cyfr szesnastkowych w tym kodzie. Jeśli to wygląda dobrze, to nie jest Math.random(), więc spróbuj zastąpić implementację UUID, której używasz w metodzie uuid() i sprawdź, czy nadal masz dobre wyniki.

[Update: Just saw Veselin ' s raport {[10] } o błędzie z Math.random() przy starcie. Ponieważ problem występuje tylko przy starcie, test node-uuid raczej nie będzie przydatny. Skomentuję bardziej szczegółowo devoluk.com link.]

 36
Author: broofa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-23 22:33:47

Rzeczywiście są kolizje, ale tylko pod Google Chrome. Sprawdź moje doświadczenia na ten temat w Problem z generatorem liczb losowych Google Chrome

Wygląda na to, że kolizje zdarzają się tylko przy pierwszych kilku rozmowach z matematyką.przypadkowe. Bo jeśli po prostu uruchomić metodę createGUID / testGUIDs powyżej (co oczywiście było pierwszą rzeczą, którą próbowałem), to po prostu działa bez żadnych kolizji.

Więc aby wykonać pełny test trzeba zrestartować Google Chrome, wygenerować 32 bajt, restart Chrome, generate, restart, generate, itp.

 36
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/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-30 03:25:43

Żeby inni ludzie byli tego świadomi-natknąłem się na zaskakująco dużą liczbę pozornych kolizji przy użyciu wspomnianej tutaj techniki generowania UUID. Te kolizje trwały nawet po tym, jak przełączyłem się na seedrandom {[2] } dla mojego generatora liczb losowych. To sprawiło, że wyrywałam sobie włosy, jak możesz sobie wyobrazić.

W końcu zorientowałem się, że problemem jest (prawie?) związany wyłącznie z botami Google Web crawler. Jak tylko zacząłem ignorować prośby z "googlebot" w polu user-agent kolizje zniknęły. Domyślam się, że muszą buforować wyniki skryptów JS w jakiś półinteligentny sposób, z efektem końcowym, że ich spidering browser nie może być liczony, aby zachowywać się tak, jak normalne przeglądarki zrobić.

Tak dla twojej wiadomości.

 21
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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 18:21:58

Właśnie przeprowadziłem podstawowy test 100,000 iteracji w Chrome przy użyciu algorytmu uuid, który napisałeś, i nie dostałem żadnych kolizji. Oto fragment kodu:

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);
 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/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-30 03:23:05

Odpowiedź , która pierwotnie zamieszczała To rozwiązanie UUID, została zaktualizowana 2017-06-28:

Adobry artykuł od twórców Chrome omawiający Stan matematyki.losowa jakość PRNG w Chrome, Firefox i Safari. tl; dr - na koniec-2015 jest "całkiem dobry", ale nie Jakość kryptograficzna. Aby rozwiązać ten problem, Oto zaktualizowana wersja powyższego rozwiązania, które wykorzystuje ES6, crypto API i trochę JS wizardy nie mogę wziąć kredyt dla :

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());
 3
Author: Luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-03 18:40:11

Odpowiedzi tutaj dotyczą "co jest przyczyną problemu?"(Chrome Math.random seed issue), ale nie "jak mogę tego uniknąć?".

Jeśli nadal szukasz, jak uniknąć tego problemu, napisałem ta odpowiedź jakiś czas temu jako zmodyfikowane spojrzenie na funkcję Broofa, aby obejść ten dokładny problem. Działa on poprzez przesunięcie pierwszych 13 liczb hex o część szesnastkową znacznika czasu, co oznacza, że nawet jeśli matematyka.losowy znajduje się na tym samym nasionie i nadal będzie generował inny UUID, chyba że generowane z dokładnością do milisekundy.

 0
Author: Briguy37,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-26 19:40:54