生成v5 UUID。 什么是名称和命名空间?

我已阅读man页,但我不清楚namenamespace的用途。

对于版本3和版本5的UUID,必须给出额外的命令行参数命名空间和名称。 命名空间是字符串表示中的UUID或内部预定义名称空间UUID(当前已知为“ns:DNS”,“ns:URL”,“ns:OID”和“ns:X500”)的标识符。 该名称是一个任意长度的字符串。

命名空间:

命名空间可以是字符串表示中的UUID,也可以是

这是否意味着我需要在与生成的UUID v5相关的某处存储它(UUID v4)? 无论哪种情况,为什么这不会自动完成?

该名称是一个任意长度的字符串。

name完全随机的字符串? 那么它的目的是什么? 它可以从UUID v5解码吗?


名称和名称空间可用于创建(非常可能)唯一UUID的层次结构。

粗略地说,类型3或类型5的UUID是通过将名称空间标识符与名称散列在一起而生成的。 类型3的UUID使用MD5,类型5的UUID使用SHA1。 只有128位是可用的,5位用于指定类型,所以所有的散列位都不会写入UUID。 (MD5也被认为是密码破坏的,而SHA1是最后一段,所以不要用它来验证需要“非常安全”的数据)。 也就是说,它为您提供了创建可重复/可验证的“散列”函数的方法,该函数将可能的分层名称映射到概率唯一的128位值上,可能像分层散列或MAC一样起作用。

假设你有一个(key,value)存储,但它只支持一个名字空间。 您可以使用类型3或类型5的UUID生成大量不同的逻辑名称空间。 首先,为每个名称空间创建一个根UUID。 这可以是类型1(主机+时间戳)或类型4(随机)UUID,只要您将其存储在某个地方。 或者,您可以为您的根创建一个随机UUID(或使用null UUID: 00000000-0000-0000-0000-000000000000作为根),然后使用“ uuid -v5 $ROOTUUID $NAMESPACENAME ”为每个名称空间创建可重现的UUID。 现在,您可以使用“ uuid -v5 $NAMESPACEUUID $KEY ”为名称空间内的键创建唯一的UUID。 这些UUID可以抛入一个单一的键值存储中,避免碰撞的概率很高。 这个过程可以递归地重复,以便例如,如果与UUID键相关联的“值”反过来代表像某个桶,容器或目录那样的某种类型的逻辑“名字空间”,则其UUID可以反过来被用来生成更多等级的UUID。

生成的类型3或类型5的UUID包含名称空间ID和名称空间内的名称空间(键)的(部分)散列。 它不再保存名称空间UUID,而是消息MAC保存它所编码的消息的内容。 从uuid算法的角度来看,该名称是一个“任意”(八位字节)字符串。 它的含义取决于你的应用。 它可能是逻辑目录中的文件名,对象存储中的对象ID等等。

虽然这适用于大量的命名空间和密钥,但如果您正在寻找非常多的密钥,而且这些密钥的概率很高,那么它最终会失去动力。 生日问题(又名生日悖论)的维基百科条目包括一个表,其中给出了各种键和表大小的至少一次碰撞的概率。 对于128位,通过这种方式散列260亿个密钥具有p=10^-18 (可忽略)的碰撞概率,但是26万亿个密钥将至少一个碰撞的概率提高到p=10^-12一万亿),并且散列26*10^15键,将至少一次碰撞的概率提高到p=10^-6 (百万分之一)。 对编码UUID类型的5位进行调整后,其运行速度会更快一些,所以万亿个按键的单次碰撞概率大约为1万亿。

有关概率表,请参阅http://en.wikipedia.org/wiki/Birthday_problem#Probability_table。

有关UUID编码的更多详细信息,请参见http://www.ietf.org/rfc/rfc4122.txt。


类型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位,在类型记录中clock_seq_hi_and_reserved 5 ,然后分别将clock_seq_hi_and_reserved部分的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');
    

    注意 :任何代码发布到公共领域。 无需归属。

    链接地址: http://www.djcxy.com/p/70111.html

    上一篇: Generating v5 UUID. What is name and namespace?

    下一篇: How can a URI contain a URN as well as a URL?