Столкновения при генерации UUID-ы на JavaScript?



Это относится к этот вопрос. Я использую ответ для создания UUID в 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);
});


Это решение, казалось, работает нормально, однако я получаю столкновения. Вот что у меня есть:




  • веб-приложение, работающее в Google Chrome.

  • 16 пользователей.

  • около 4000 UUIDs были созданы за последние 2 месяца этими пользователями.

  • я получил около 20 столкновений - например, новый UUID genereated сегодня был таким же, как и около 2 месяцев назад (другой пользователь).


Так вопросы являются:




  1. что вызывает проблему?

  2. как я могу избежать этого?

543   5  

5 ответов:

Я думаю, что это Math.random() сломленн на вашей системе по какой-то причине (странно как то звучит). Это первый отчет, который я видел о том, что кто-то получает столкновения.

node-uuid есть тестирование что вы можете использовать для проверки распределения шестнадцатеричных цифр в этом коде. Если это выглядит нормально, то это не Math.random(), поэтому попробуйте заменить реализацию UUID, которую вы используете в uuid() метод там и посмотреть, если вы все еще получаете хорошо результаты.

[обновление: только что видел отчет Веселина об ошибке с Math.random() при запуске. Так как проблема только при запуске, то node-uuid тест вряд ли будет полезен. Я прокомментирую более подробно на тему devoluk.com линк.]

действительно есть коллизии, но только под Google Chrome. Проверьте мой опыт по этой теме здесь

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

кажется, что столкновения происходят только на первых нескольких вызовах математики.случайность. Потому что если вы просто запустите метод createGUID / testGUIDs выше (что, очевидно, было первым, что я попробовал), он просто работает без каких-либо коллизий.

так, чтобы сделать полный тест нужно перезапустите Гугл Хром, генерируют 32 байта, перезагрузите хром, создать, перезагрузить, создать...

просто чтобы другие люди могли знать об этом - я столкнулся с удивительно большим количеством очевидных столкновений, используя технику генерации UUID, упомянутую здесь. Эти столкновения продолжались даже после того, как я переключился на seedrandom для моего генератора случайных чисел. Меня рвет на себе волосы, как вы можете себе представить.

Я в конце концов понял, что проблема была (почти?) исключительно связанные с веб-гусеничных ботов Google. Как только я начал игнорируя запросы с "googlebot" в поле user-agent, коллизии исчезли. Я предполагаю, что они должны кэшировать результаты сценариев JS каким-то полуинтеллектуальным способом, с конечным результатом, что их браузер-паук не может рассчитывать на то, чтобы вести себя так, как это делают обычные браузеры.

просто FYI.

Я хотел опубликовать это как комментарий к вашему вопросу, но, видимо, StackOverflow не позволит мне.

Я только что провел рудиментарный тест из 100 000 итераций в Chrome, используя алгоритм UUID, который вы опубликовали, и не получил никаких столкновений. Вот фрагмент кода:

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);

ответ это первоначально опубликованное решение UUID было обновлено на 2017-06-28:

A хорошая статья от разработчиков Chrome обсуждение состояния математики.случайное качество PRNG в Chrome, Firefox и Safari. tl;dr-по состоянию на конец 2015 года это "довольно хорошее", но не криптографическое качество. Чтобы решить эту проблему, вот обновленная версия вышеуказанного решения, которое использует ES6,crypto API, и немного JS wizardy я не могу взять кредит для:

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());

Comments

    Ничего не найдено.