生成v5 UUID。 什么是名字和名字空间?
我已经阅读了man
页,但我不知道name
和namespace
是什么。
对于版本3和版本5 UUID,必须给出额外的命令行参数命名空间和名称。 命名空间可以是string表示forms的UUID,也可以是内部预先定义的命名空间UUID(当前已知为“ns:DNS”,“ns:URL”,“ns:OID”和“ns:X500”)的标识符。 该名称是一个任意长度的string。
命名空间:
命名空间可以是string表示中的UUID,也可以是
这是否意味着我需要将其存储在与生成的UUID v5相关的某个地方(UUID v4)? 无论哪种情况,为什么这不是自动完成的?
该名称是一个任意长度的string。
name
完全随机的string? 那么它的目的是什么呢? 它可以从UUID v5解码吗?
名称和名称空间可以用来创build(非常可能)唯一UUID的层次结构。
粗略地说,types3或types5的UUID是通过将名称空间标识符与名称进行散列来生成的。 types3的UUID使用MD5,types5的UUID使用SHA1。 只有128位可用,5位用于指定types,所以所有的散列位都不会写入UUID。 (另外MD5被认为是密码破译的,而SHA1是最后一段,所以不要用它来validation需要“非常安全”的数据)。 也就是说,它为您提供了创build可重复/可validation的“哈希”函数的方法,将可能的分层名称映射到概率唯一的128位值上,可能像分层哈希或MAC一样工作。
假设你有一个(键,值)存储,但它只支持一个名字空间。 您可以使用types3或types5的UUID生成大量不同的逻辑名称空间。 首先,为每个名称空间创build一个根UUID。 这可能是一个types1(主机+时间戳)或types4(随机)的UUID,只要你把它藏在某个地方。 或者,您可以为您的根目录创build一个随机UUID(或者使用空UUID:00000000-0000-0000-0000-000000000000作为根目录),然后使用“uuid -v5 $ ROOTUUID $ NAMESPACENAME”为每个名称空间创build可重现的UUID。 现在,您可以使用“uuid -v5 $ NAMESPACEUUID $ KEY”为名称空间内的键创build唯一的UUID。 这些UUID可以被抛入一个单一的键值存储,避免碰撞的概率很高。 这个过程可以recursion地重复,这样如果例如与UUID键相关联的“值”又代表像桶,容器或者目录那样的某种逻辑“名字空间”,那么它的UUID可以依次被用来产生更多的等级的UUID。
生成的types3或types5 UUID包含名称空间标识和名称空间内的名称空间(键)的(部分)散列。 它不再保存名称空间UUID,而是消息MAC保存从其编码的消息的内容。 该名称是从uuidalgorithm的angular度来看的“任意”(八位字节)string。 它的含义取决于你的应用程序。 它可以是逻辑目录中的文件名,对象存储中的对象ID等等。
虽然这适用于大量的命名空间和密钥,但是如果您正在寻找非常多的可能性很高的密钥,它最终会失去动力。 生日问题(又名生日悖论)的维基百科条目包括一个表,给出了各种键和表大小的至less一次碰撞的概率。 对于128位,通过这种方式对260亿个密钥进行散列有一个碰撞概率p = 10 ^ -18(可忽略),但是26万亿个密钥将至less一次碰撞的概率提高到p = 10 ^ -12一万亿),并且散列26 * 10 ^ 15个键,将至less一次碰撞的概率提高到p = 10 ^ -6(百万分之一)。 调整5位编码的UUIDtypes,它会跑得更快一些,所以万亿键大概有一个1万亿的机会有一个单一的冲突。
概率表见http://en.wikipedia.org/wiki/Birthday_problem#Probability_table 。
有关UUID编码的更多详细信息,请参见http://www.ietf.org/rfc/rfc4122.txt 。
types3和types5 UUID只是一种将散列填充到UUID的技术。
- types1:将MAC地址,date时间填入128位
- types3 :将MD5哈希填充到128位
- types4:填充随机数据到128位
- types5 :将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]);
你用一个所谓的名字空间来加你的string以防止名字冲突。
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位,在typeslogging中clock_seq_hi_and_reserved
5
,然后分别将clock_seq_hi_and_reserved
部分的clock_seq_hi_and_reserved
为1和0。
更多的例子
现在你已经有了一个可以生成所谓Name的函数,你可以使用这个函数(伪代码):
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,必须给出额外的命令行参数命名空间和名称。 命名空间可以是string表示forms的UUID,也可以是内部预先定义的命名空间UUID(当前已知为“ns:DNS”,“ns:URL”,“ns:OID”和“ns:X500”)的标识符。 该名称是一个任意长度的string。
命名空间是你喜欢的任何UUID。 它可以是预先定义的之一,或者你可以自己组装,例如:
UUID Namespace_RectalForeignExtractedObject = '4d79546f-6e67-7565-496e-486572417373'
该名称是一个任意长度的string。
这个名字就是你想要附加到命名空间的文本,然后散列,并填充到一个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');
注意 :任何代码发布到公共领域。 不需要归属