UUIDs tipo 3 e tipo 5 são apenas uma técnica de inserir um hash em um UUID.
- Tipo 1: armazena endereço MAC + data e hora em 128 bits
- Tipo 3 : armazena um hash MD5 em 128 bits
- Tipo 4: armazena dados aleatórios em 128 bits
- Tipo 5 : insere um hash SHA1 em 128 bits
- Tipo 6: ideia não oficial para UUIDs sequenciais
Um hash SHA1 gera 160 bits (20 bytes); o resultado do hash é convertido em um UUID.
Com o hash de 20 bytes de 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
(Observe que os primeiros dois bits de '9' já são 1 e 0, respectivamente, portanto, isso não tem efeito).
O que eu hash?
Você provavelmente está se perguntando o que é isso que devo fazer hash. Basicamente, você faz hash da concatenação de:
sha1([NamespaceUUID]+[AnyString]);
Você prefixa sua string com um denominado namespace para evitar conflitos de nome.
O UUID RFC pré-define quatro namespaces para você:
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}
Então, você pode misturar:
StackOverflowDnsUUID = sha1(Namespace_DNS + "stackoverflow.com");
StackOverflowUrlUUID = sha1(Namespace_URL + "stackoverflow.com");
A RFC então define como:
- pegue os 160 bits de SHA1
- e convertê-lo em 128 bits de um UUID
A essência básica é pegar apenas os primeiros 128 bits, inserir um 5
no registro de tipo e definir os dois primeiros bits da clock_seq_hi_and_reserved
seção como 1 e 0, respectivamente.
Mais exemplos
Agora que você tem uma função que gera um denominado Nome , pode ter a função (em pseudo-código):
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;
}
(Observe que o endian-ness do seu sistema pode afetar os índices dos bytes acima)
Você pode receber chamadas:
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');
Agora de volta à sua pergunta
Para UUIDs da versão 3 e 5, o namespace e o nome dos argumentos da linha de comando adicionais devem ser fornecidos. O namespace é um UUID em representação de string ou um identificador para UUIDs de namespace predefinidos internamente (atualmente conhecidos são "ns: DNS", "ns: URL", "ns: OID" e "ns: X500"). O nome é uma string de comprimento arbitrário.
O namespace é o UUID que você quiser. Pode ser um dos pré-definidos, ou você pode criar o seu próprio, por exemplo:
UUID Namespace_RectalForeignExtractedObject = '8e884ace-bee4-11e4-8dfc-aa07a5b093db'
O nome é uma string de comprimento arbitrário.
O nome é apenas o texto que você deseja anexar ao namespace, fazer o hash e colocá-lo em um 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');
Nota : Qualquer código lançado em domínio público. Nenhuma atribuição necessária.