Создание UUID V5. Что такое имя и пространство имен?

Я прочитал страницу man, но я не понимаю, для чего предназначены name и namespace.

Для UUID версии 3 и версии 5 дополнительная командная строка необходимо указать пространство имен и имя аргументов. Пространство имен UUID в строчном представлении или           идентификатор для внутренних предопределенных UUID пространства имен (в настоящее время известны "ns: DNS", "ns: URL", "ns: OID" и "ns: X500" ). name - строка произвольной длины.

Пространство имен:

Пространство имен является либо UUID в строчном представлении, либо

Означает ли это, что мне нужно его хранить (UUID v4) где-то по отношению к сгенерированному UUID v5? В любом случае, почему это не делается автоматически?

Имя представляет собой строку произвольной длины.

name вполне случайная строка? Тогда в чем его цель? Может ли он быть декодирован из UUID v5?

Ответ 1

Имя и пространство имен могут использоваться для создания иерархии (очень вероятно) уникальных UUID.

Грубо говоря, UUID типа 3 или типа 5 генерируется путем объединения идентификатора пространства имен с именем. UUID типа 3 используют MD5, а UUID типа 5 используют SHA1. Доступны только 128 бит и 5 бит используются для указания типа, поэтому все хэш-биты не попадают в UUID. (Также MD5 считается криптографически сломанным, а SHA1 находится на последних ногах, поэтому не используйте это для проверки данных, которые должны быть "очень безопасными" ). Тем не менее, это дает вам способ создания повторяемой/проверяемой функции "хэш", отображающей возможное иерархическое имя на вероятностно уникальное 128-битное значение, потенциально действующее как иерархический хеш или MAC.

Предположим, что у вас есть хранилище (ключ, значение), но оно поддерживает только одно пространство имен. Вы можете сгенерировать большое количество различных логических пространств имен с использованием UUID типа 3 или 5. Сначала создайте корневой UUID для каждого пространства имен. Это может быть тип 1 (host + timestamp) или тип 4 (случайный) UUID, если вы его где-то запечатываете. В качестве альтернативы вы можете создать один случайный UUID для своего корня (или использовать нулевой UUID: 00000000-0000-0000-0000-000000000000 как root), а затем создать воспроизводимый UUID для каждого пространства имен, используя "uuid -v5 $ROOTUUID $NAMESPACENAME". Теперь вы можете создавать уникальные UUID для ключей в пространстве имен, используя "uuid -v5 $NAMESPACEUUID $KEY". Эти UUID могут быть выброшены в одно хранилище ключей с высокой вероятностью избежать столкновения. Этот процесс можно повторить рекурсивно, так что если, например, "значение", связанное с ключом UUID, представляет собой своего рода логическое "пространство имен", такое как ведро, контейнер или каталог, тогда его UUID может использоваться, в свою очередь, для создания более иерархических UUID,.

Сгенерированный тип UUID типа 3 или типа 5 содержит (частичный) хэш идентификатора пространства имен и пространства имен в пространстве имен (ключ). Он больше не содержит UUID пространства имен, чем сообщение MAC удерживает содержимое сообщения, из которого оно закодировано. Имя является "произвольной" (октетной) строкой с точки зрения алгоритма uuid. Его значение, однако, зависит от вашего приложения. Это может быть имя файла в логическом каталоге, идентификатор объекта в хранилище объектов и т.д.

В то время как это хорошо работает для умеренно большого количества пространств имен и ключей, в конечном итоге он исчерпывается, если вы нацелены на очень большое количество ключей, которые уникальны с очень высокой вероятностью. В записи Википедии для проблемы дня рождения (aka Birthday Paradox) есть таблица, которая дает вероятности хотя бы одного столкновения для различного количества ключей и размеров таблиц. Для 128 бит, хеширование из 26 миллиардов ключей таким образом имеет вероятность столкновения p = 10 ^ -18 (пренебрежимо мало), но 26 триллионов ключей, увеличивает вероятность хотя бы одного столкновения с p = 10 ^ -12 (один в триллион) и хеширование 26 * 10 ^ 15 ключей, увеличивает вероятность по крайней мере одного столкновения до p = 10 ^ -6 (один миллион). При настройке на 5 бит, которые кодируют UUID-тип, он будет работать несколько быстрее, поэтому триллион ключей имеют примерно 1-в-триллион вероятность иметь одно столкновение.

См. http://en.wikipedia.org/wiki/Birthday_problem#Probability_table для таблицы вероятностей.

Подробнее о кодировании UUID см. http://www.ietf.org/rfc/rfc4122.txt.

Ответ 2

UUID типа 3 и тип 5 - это всего лишь метод наложения хэша в UUID.

  • Тип 1: переназначает MAC-адрес, дата и время в 128 бит.
  • Тип 3: заполняет хэш MD5 на 128 бит
  • Тип 4: заполняет случайные данные на 128 бит
  • Тип 5: содержит хэш SHA1 в 128 бит

Хэш SHA1 выводит 160 бит (20 байтов). Результат хеша преобразуется в UUID. Из 20-байтов из SHA1:

SHA1 Digest:   74738ff5 5367 e958 9aee 98fffdcd1876 94028007
UUID (v5):     74738ff5-5367-5958-9aee-98fffdcd1876
                             ^_low nibble is set to 5 to indicate type 5
                                  ^_first two bits set to 1 and 0, respectively

(Обратите внимание, что первые два бита '9' уже равны 1 и 0 соответственно, поэтому это не влияет).

Что мне делать?

Вам, наверное, интересно, что это такое, что я должен хэш. В основном вы хешируете конкатенацию:

sha1([NamespaceUUID]+[AnyString]);

Вы префикс своей строки с так называемым пространством имен, чтобы предотвратить конфликты имен.

UUID RFC предопределяет для вас четыре пространства имен:

  • NameSpace_DNS: {6ba7b810-9dad-11d1-80b4-00c04fd430c8}
  • NameSpace_URL: {6ba7b811-9dad-11d1-80b4-00c04fd430c8}
  • NameSpace_OID: {6ba7b812-9dad-11d1-80b4-00c04fd430c8}
  • NameSpace_X500: {6ba7b814-9dad-11d1-80b4-00c04fd430c8}

Итак, вы можете использовать хэш вместе:

StackOverflowDnsUUID = sha1(Namespace_DNS + "stackoverflow.com");
StackOverflowUrlUUID = sha1(Namespace_URL + "stackoverflow.com");

Затем RFC определяет, как:

  • взять 160 бит из SHA1
  • и преобразовать его в 128 бит UUID

Основной смысл состоит в том, чтобы взять только первые 128 бит, записать 5 в записи типа, а затем установить первые два бита clock_seq_hi_and_reserved до 1 и 0 соответственно.

Дополнительные примеры

Теперь, когда у вас есть функция, которая генерирует так называемое Имя, вы можете иметь функцию (в псевдокоде):

UUID NameToUUID(UUID NamespaceUUID, String Name)
{
    byte[] hash = sha1(NamespaceUUID.ToBytes() + Name.ToBytes());
    UUID result;
    Copy(hash, result, 16);
    result[6] &= 0x0F; 
    result[6] |= 0x50;
    result[8] &= 0x3F; 
    result[8] |= 0x80;
    return result;
}

(Обратите внимание, что конечная система вашей системы может влиять на индексы указанных выше байтов)

Вы можете звонить:

uuid = NameToUUID(Namespace_DNS, 'www.stackoverflow.com');
uuid = NameToUUID(Namespace_DNS, 'www.google.com');
uuid = NameToUUID(Namespace_URL, 'http://www.stackoverflow.com');
uuid = NameToUUID(Namespace_URL, 'http://www.google.com/search&q=rfc+4112');
uuid = NameToUUID(Namespace_URL, 'http://stackoverflow.com/info/5515880/test-vectors-for-uuid-version-5-converting-hash-into-guid-algorithm');

Теперь вернемся к вашему вопросу

Для UUID версии 3 и версии 5 необходимо указать дополнительное пространство и имя аргумента командной строки. Пространство имен является либо UUID в строчном представлении, либо идентификатором для внутренних предварительно определенных UUID пространства имен (в настоящее время известны "ns: DNS", "ns: URL", "ns: OID" и "ns: X500" ). Имя представляет собой строку произвольной длины.

пространство имен - это любой UUID, который вам нравится. Это может быть один из предопределенных, или вы можете сделать свой собственный, например:

UUID Namespace_RectalForeignExtractedObject = '4d79546f-6e67-7565-496e-486572417373'

Имя представляет собой строку произвольной длины.

Имя - это только текст, который вы хотите добавить в пространство имен, затем хешировать и вставлять в UUID:

uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'screwdriver');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'toothbrush');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'broomstick');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'orange');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'axe handle');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'impulse body spray');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'iPod Touch');

Примечание. Любой код, выпущенный в общественное достояние. Не требуется атрибуция.