Создание 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');
Примечание. Любой код, выпущенный в общественное достояние. Не требуется атрибуция.