我读过的man
页面,但我不已了解了name
和namespace
是。
对于第3版和第5点的UUID的附加命令行参数名称空间和名称必须得到。 名称空间是在任一字符串表示一个UUID或用于在内部预先定义的命名空间的UUID的标识符(目前已知的是“NS:DNS”,“NS:URL”,“NS:OID”,和“NS:X500”)。 这个名字是任意长度的字符串。
命名空间:
名称空间是无论是在字符串表示或一个UUID
这是否意味着我需要将它存储(UUID V4)与生成的UUID V5关系的地方? 在这两种情况下,这是为什么不自动完成?
这个名字是任意长度的字符串。
name
一个完全随机的字符串? 什么是它那么目的是什么? 是否可以从UUID V5解码?
名称和命名空间可以被用来创造的(很有可能)独特的UUID的层次结构。
粗略地讲,是通过散列连同名称的命名空间标识符产生的类型3或5型UUID。 类型3的UUID使用MD5和5型的UUID使用SHA1。 只有128位可和5位被用于指定的类型,所以所有的散列位的不让它进入UUID。 (也MD5被认为是打破加密和SHA1是其最后的腿,所以不要用它来验证需要“非常安全”数据)。 这就是说,它可以让你创建一个可重复的/可核实“散列”函数映射可能分层名称到一个概率唯一的128位值,可能表现得像一个层次散列或MAC的方式。
假设你有一个(键,值)商店,但它仅支持一个命名空间。 可以生成使用类型3或5型的UUID大量不同的逻辑名称空间。 首先,为每个命名空间的根UUID。 这可能是1型(主机+时间戳)或4型(随机)UUID只要你藏在某个地方。 另外,您可以为您的根一个随机UUID(或使用null
UUID: 00000000-0000-0000-0000-000000000000
根),然后创建一个使用“每个命名空间可重复的UUID uuid -v5 $ROOTUUID $NAMESPACENAME
”。 现在,您可以创建使用“命名空间中的按键独特的UUID uuid -v5 $NAMESPACEUUID $KEY
”。 这些UUID可扔进以避免碰撞的概率高的单键值存储。 这个过程可以递归地重复,使得如果例如“值”与依次一个UUID键相关联表示某种逻辑“命名空间”象桶,容器或目录的,那么它的UUID可以反过来用于产生多个分层的UUID。
所生成的类型3或5型UUID保持命名空间ID和名称中的命名空间(键)的(部分)的散列。 它没有更多保持命名空间UUID比确实消息MAC保持它从编码的消息的内容。 名称是“任意”(八位位组)从UUID算法的透视字符串。 但是它的意义取决于应用程序。 这可能是一个对象存储中的逻辑目录,对象ID内的文件名,等等。
虽然这非常适用于中等一大批命名空间和密钥,它最终耗尽蒸汽的,如果你的目标是一个非常大的数字,是具有非常高的概率独特的密钥。 为生日问题(又名生日悖论)的Wikipedia条目包括的表中给出了至少一个碰撞为键和表大小的各种数目的概率。 为128位,散列26个十亿键这样具有碰撞的概率p=10^-18
(忽略不计),但260000亿键,增加至少一个碰撞的概率p=10^-12
(一个在一万亿美元),和散列26*10^15
键,增加至少一个碰撞的概率p=10^-6
在一百万(之一)。 在调整了5个比特编码的UUID类型,它会稍快用完了,所以一万亿键具有大致1英寸-A-兆具有单个碰撞的机会。
见http://en.wikipedia.org/wiki/Birthday_problem#Probability_table的概率表。
见http://www.ietf.org/rfc/rfc4122.txt关于UUID编码的更多细节。
类型3和类型5的UUID只是馅散列成UUID的技术。
- 类型1:充塞MAC地址,日期时间为128位
- 类型3:充塞MD5哈希到128位
- 类型4:充塞随机数据转换成128个比特
- 5型 :充塞的SHA1哈希到128位
一个SHA1哈希输出160位(20个字节)。 哈希的结果被转换为一个UUID。 从SHA1 20字节:
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然后定义如何:
- 采取从SHA1的160位
- 并将其转换成一个UUID的128位
的基本要点是,只取第一个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/questions/5515880/test-vectors-for-uuid-version-5-converting-hash-into-guid-algorithm');
现在回到你的问题
对于第3版和第5点的UUID的附加命令行参数名称空间和名称必须得到。 名称空间是在任一字符串表示一个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');
注 :释放到公共领域的任何代码。 无需归属。
一个名字只不过是一个标识符,一些命名空间中唯一更多。 问题是,命名空间通常相当小,一个名字常与别人的名字冲突。 例如,我的车的车牌号码(名称)是我州机动车管理局的命名空间中是唯一的,但它可能不会在世界上独一无二的; 其他国家的DMV可能已经在自己的命名空间中使用相同的名称。 哎呀,其他人可能有一个电话号码(名称)也匹配,因为这是又一个命名空间,等等。
的UUID可以被看作是居住在一个单一命名空间如此巨大,它可以为一切提供一个唯一的名称; 这就是“万能”的意思。 但你如何在其他命名现有名称的UUID地图?
一个显而易见的解决方案是生成的每个项目在他们的不相交的命名空间,以取代旧名称的UUID(V1或V4)。 缺点是,他们是大了很多,你要传达的所有新的名字给大家谁拥有你的数据集的副本,更新所有的API等的赔率被你不能真正完全删除旧名称的无论如何,这意味着现在每个项目有两个名字,让你做的事是好还是坏?
这是V3 / V5进来的UUID 看起来就像V4随机但实际上却是确定的。 那么任何人谁有权UUID的命名空间可以独立生成该命名空间中的任何给定名称相同的UUID。 你不需要把它们发布在所有甚至没有预先生成它们,因为任何人都可以根据需要动态地创建他们!
DNS名称和URL是很常用的命名空间,所以标准的UUID公布那些; ASN.1的OID和X.500的名字并不常见,但标准机构爱他们,所以他们公布的标准命名空间的UUID对他们来说太。
对于所有其他名称空间,必须要产生自己的命名空间UUID(V1或V4),并将其传达给任何人谁需要它。 如果你有多个命名空间,其发布的UUID为每一个显然是不理想的。
这就是层次进来:您创建一个“基地” UUID(无论何种类型),然后使用它作为命名的其他命名空间命名空间! 这样,您只需要发布基本UUID(或使用明显的一个),每个人都可以计算出的其余部分。
例如,让我们留下来,我们想创造一些StackOverflow的UUID的; 具有DNS命名空间中一个明显的名字,所以基本是显而易见的:
uuid ns_dns = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
uuid ns_base = uuidv5(ns_dns, 'stackoverflow.com');
StackOverflow的本身对于用户来说,问题,答案,评论等不同的命名空间,但这些都是相当明显,以及:
uuid ns_user = uuidv5(ns_base, 'user');
uuid ns_question = uuidv5(ns_base, 'question');
uuid ns_answer = uuidv5(ns_base, 'answer');
uuid ns_comment = uuidv5(ns_base, 'comment');
这种特殊的问题是#10867405,因此它的UUID是:
uuid here = uuidv5(ns_question, '10867405');
请注意,没有什么随机在这个过程中,所以任何人谁遵循同样的逻辑将得到相同的答案,然而UUID命名空间是如此巨大,它(实际上,给定一个122位的加密哈希的安全性)永远不会有冲突UUID从任何其他名称空间/名称对生成的。
文章来源: Generating v5 UUID. What is name and namespace?