V5 UUID oluşturuluyor. Ad ve ad alanı nedir?


125

manSayfayı okudum ama ne nameve ne işe yaradığını anlamıyorum namespace.

Sürüm 3 ve sürüm 5 UUID'leri için ek komut satırı argümanları ad alanı ve ad verilmelidir. Ad alanı, dize gösteriminde bir UUID veya dahili olarak önceden tanımlanmış ad alanı UUID'leri için bir tanımlayıcıdır (şu anda "ns: DNS", "ns: URL", "ns: OID" ve "ns: X500" bilinmektedir). Ad, keyfi uzunlukta bir dizedir.

Ad alanı:

Ad alanı, dize gösteriminde bir UUID veya bir

Oluşturulan UUID v5 ile ilişkili olarak onu (UUID v4) bir yerde saklamam gerektiği anlamına mı geliyor? Her iki durumda da, bu neden otomatik olarak yapılmıyor?

Ad, keyfi uzunlukta bir dizedir.

nametamamen rastgele bir dizge? Öyleyse bunun amacı nedir? UUID v5'ten kodu çözülebilir mi?

Yanıtlar:


106

Ad ve ad alanı, (büyük olasılıkla) benzersiz UUID'lerin bir hiyerarşisini oluşturmak için kullanılabilir.

Kabaca konuşursak, bir tip 3 veya tip 5 UUID, bir adla birlikte bir ad alanı tanımlayıcısını karma hale getirerek oluşturulur. Tip 3 UUID'ler MD5 kullanır ve tip 5 UUID'ler SHA1 kullanır. Türü belirtmek için yalnızca 128 bit kullanılabilir ve 5 bit kullanılır, bu nedenle tüm karma bitleri onu UUID'ye dönüştürmez. (Ayrıca MD5 kriptografik olarak bozuk kabul edilir ve SHA1 son aşamasındadır, bu nedenle "çok güvenli" olması gereken verileri doğrulamak için bunu kullanmayın). Bununla birlikte, potansiyel olarak hiyerarşik bir özet veya MAC gibi davranan, olasılıkla benzersiz 128 bitlik bir değerle olası hiyerarşik bir adı eşleyen tekrarlanabilir / doğrulanabilir bir "karma" işlevi oluşturmanın bir yolunu sunar.

Bir (anahtar, değer) deponuz olduğunu, ancak yalnızca bir ad alanını desteklediğini varsayalım. Tip 3 veya tip 5 UUID kullanarak çok sayıda farklı mantıksal ad alanı oluşturabilirsiniz. İlk olarak, her ad alanı için bir kök UUID oluşturun. Bu, bir yere sakladığınız sürece tip 1 (ana bilgisayar + zaman damgası) veya tip 4 (rastgele) UUID olabilir. Alternatif oluşturabilir biri sizin root için rasgele UUID (veya kullanmak nullUUID: 00000000-0000-0000-0000-000000000000root olarak) "kullanarak her ad alanı için bir tekrarlanabilir UUID oluşturmak ve daha sonra uuid -v5 $ROOTUUID $NAMESPACENAME". Artık bir ad alanındaki anahtarlar için benzersiz UUID'ler oluşturabilirsiniz "uuid -v5 $NAMESPACEUUID $KEY". Bu UUID'ler, çarpışmayı önleme olasılığı yüksek olan tek bir anahtar-değer deposuna atılabilir. Bu işlem, örneğin bir UUID anahtarıyla ilişkili" değer ", sırayla bir tür mantıksal" ad alanını temsil ediyorsa, yinelemeli olarak tekrarlanabilir. "bir paket, kapsayıcı veya dizin gibi, ardından UUID'si daha hiyerarşik UUID'ler oluşturmak için kullanılabilir.

Oluşturulan tip 3 veya tip 5 UUID, ad alanı kimliği ve ad içinde ad (anahtar) için (kısmi) bir karma tutar. Bir MAC mesajının kodlandığı mesajın içeriğini tuttuğundan daha fazla UUID ad alanını tutmamaktadır. İsim, uuid algoritmasının perspektifinden "keyfi" (sekizli) bir dizedir. Ancak anlamı, uygulamanıza bağlıdır. Mantıksal bir dizin içindeki bir dosya adı, bir nesne deposu içindeki nesne kimliği, vb. Olabilir.

Bu, orta derecede çok sayıda ad alanı ve anahtar için iyi çalışsa da, çok yüksek olasılıkla benzersiz çok sayıda anahtarı hedefliyorsanız, sonunda buhar biter. Doğum Günü Problemi için Wikipedia girişi (diğer adıyla Doğum Günü Paradoksu), çeşitli sayıdaki anahtarlar ve tablo boyutları için en az bir çarpışma olasılığını veren bir tablo içerir. 128-bit için, 26 milyar anahtara bu şekilde hashing uygulamak p=10^-18(ihmal edilebilir) çarpışma olasılığına sahiptir , ancak 26 trilyon anahtar, en az bir çarpışma olasılığını p=10^-12(trilyonda bir) 26*10^15artırır ve anahtarları hashing , olasılığını artırır. en az bir çarpışmap=10^-6(milyonda bir). UUID tipini kodlayan 5 bit için ayarlandığında, biraz daha hızlı tükenecektir, bu nedenle bir trilyon anahtarın kabaca trilyonda 1 tek bir çarpışmaya sahip olma şansı vardır.

Olasılık tablosu için http://en.wikipedia.org/wiki/Birthday_problem#Probability_table adresine bakın .

UUID kodlamaları hakkında daha fazla ayrıntı için http://www.ietf.org/rfc/rfc4122.txt adresine bakın .


2
Hiyerarşinin belirli bir düzeyinde, verilerin kendisindeki (bu GUID tarafından tanımlanan) çakışmaların UUID'lerle çarpışma olasılığını artırmamasını sağlamak için ad alanı olarak bir UUIDv5 ve rastgele anahtar olarak UUIDv4 kullanabilir miyim? Bilmem gereken herhangi bir performans sorunu var mı?
ermik

Konseptte yeniyim ve bahsettiğiniz hiyerarşinin ne olduğu konusunda kafam karıştı . Nerede görebilirim vs ... Açıklamaya takıldıktan sonra biraz netlik geldi, bu ad alanı için yeniden üretilebilir bir UUID oluşturmak için kullanılabilir . Merak ediyorum, belirli bir UUID'nin (3 veya 5 türünde) belirli bir ad alanı (UUID'si) kullanılarak üretildiğini doğrulamanın bir yolu var mı?
msciwoj

213

Type 3 ve Type 5 UUID'ler yalnızca bir hash'i bir UUID'ye doldurma tekniğidir .

  • Tip 1: MAC adresini + tarih saatini 128 bit olarak doldurur
  • Tip 3 : bir MD5 karmasını 128 bite doldurur
  • Tip 4: rastgele verileri 128 bit olarak doldurur
  • Tip 5 : SHA1 karmasını 128 bite doldurur
  • Tip 6: sıralı UUID'ler için resmi olmayan fikir

Bir SHA1 hash değeri 160 bit (20 bayt) çıkarır; karmanın sonucu bir UUID'ye dönüştürülür.

SHA1'deki 20 baytlık hash ile:

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'un ilk iki bitinin sırasıyla 1 ve 0 olduğuna dikkat edin, bu yüzden bunun bir etkisi yoktur).

Ne yapıyorum?

Muhtemelen hash etmem gereken şeyin ne olduğunu merak ediyorsunuz. Temel olarak şunların birleşimini hash edersiniz:

sha1([NamespaceUUID]+[AnyString]);

Ad çakışmalarını önlemek için dizenizin önüne sözde bir ad alanı eklersiniz.

UUID RFC sizin için dört ad alanlarını-tanımlar önceden:

  • 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}

Böylece birlikte hash yapabilirsiniz:

StackOverflowDnsUUID = sha1(Namespace_DNS + "stackoverflow.com");
StackOverflowUrlUUID = sha1(Namespace_URL + "stackoverflow.com");

RFC daha sonra nasıl yapılacağını tanımlar:

  • 160 biti SHA1'den alın
  • ve bunu 128 bit UUID'ye dönüştürün

Temel özü sadece ilk 128 bit, malzeme a almaktır 5olarak tipi kayıt ve ardından ilk iki bitlerini clock_seq_hi_and_reservedsırasıyla 1 ve 0 için bölümü.

Daha fazla örnek

Artık sözde bir Ad üreten bir işleve sahip olduğunuza göre, işleve sahip olabilirsiniz (sözde kodda):

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;
}

(Sisteminizin sonluluğunun yukarıdaki baytların endekslerini etkileyebileceğini unutmayın)

Çağrı alabilirsin:

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');

Şimdi sorunuza geri dönün

Sürüm 3 ve sürüm 5 UUID'leri için ek komut satırı argümanları ad alanı ve ad verilmelidir. Ad alanı, dize gösteriminde bir UUID veya dahili olarak önceden tanımlanmış ad alanı UUID'leri için bir tanımlayıcıdır (şu anda "ns: DNS", "ns: URL", "ns: OID" ve "ns: X500" bilinmektedir). Ad, keyfi uzunlukta bir dizedir.

Ad sever UUID odur. Önceden tanımlanmış olanlardan biri olabilir veya kendinizinkini oluşturabilirsiniz, örneğin:

UUID Namespace_RectalForeignExtractedObject = '8e884ace-bee4-11e4-8dfc-aa07a5b093db'

Ad, keyfi uzunlukta bir dizedir.

Ad, yalnızca ad alanına eklemek, ardından hashing uygulamak ve bir UUID'ye doldurmak istediğiniz metindir:

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');

Not : Kamu malı olarak yayınlanan herhangi bir kod. Herhangi bir atıf gerekmez.


45
Ayrıntılı açıklama için teşekkürler. Bonus puan verebilseydim Namespace_RectalForeignExtractedObjectyapardım.
boodle

UUID'den kodu çözülen ad veya ad alanının kodunu çözmek mümkün müdür?
Sathesh

4
@Sathesh Hayır, bir hash kodunu çözmek mümkün değildir; karmalar tek yönlü işlevlerdir. Örneğin, Star Trek TNG Blu-Ray koleksiyonunun tamamı 81 GB'dir ve C5740BBBF2429115276D4AB60A020ED3ADE01192 karma değerine sahiptir . Bu 20 baytlık karmanın kodunu 81 GB'ye geri çözmenin bir yolu yoktur. Gerçekten ihtiyacınız varsa, aynı sonucu veren kombinasyonu bulana kadar tüm olası GUID'leri ve olası dizeleri hashlemeyi deneyebilirsiniz. Herhangi bir luch ile onu sonsuza kadar sonsuzluk arasında bir yerde bulacaksınız.
Ian Boyd

22

Ad, bazı ad alanlarında benzersiz olan bir tanımlayıcıdan başka bir şey değildir. Sorun, ad alanlarının genellikle oldukça küçük olması ve birindeki adların genellikle diğerlerindeki adlarla çakışmasıdır. Örneğin, arabamın plaka numarası (adı) eyalet DMV ad alanında benzersizdir, ancak muhtemelen dünyada benzersiz değildir; diğer durum DMV'leri kendi ad alanlarında aynı adı kullanmış olabilir. Heck, başka birinin de eşleşen bir telefon numarası (adı) olabilir, çünkü bu başka bir ad alanı vb.

UUID'ler, her şey için benzersiz bir ad sağlayabilecek kadar geniş tek bir ad alanında yer alıyor olarak görülebilir ; bu "evrensel" demek. Ancak diğer ad alanlarındaki mevcut adları bir UUID ile nasıl eşlersiniz?

Açık bir çözüm, ayrık ad alanlarındaki eski adları değiştirmek için her öğe için bir UUID (V1 veya V4) oluşturmaktır. Olumsuz yanı, çok daha büyük olmaları, tüm yeni isimleri veri kümenizin bir kopyasına sahip olan herkese iletmeniz, tüm API'lerinizi güncellemeniz vb. Muhtemelen eski isimlerden tamamen kurtulamamanızdır. her neyse, bu artık her öğenin iki adı olduğu anlamına geliyor , yani işleri daha iyi mi yoksa daha kötü mü yaptınız?

Bu, V3 / V5'in devreye girdiği yerdir. UUID'ler , V4 kadar rastgele görünür , ancak gerçekte deterministiktir; Bir ad alanı için doğru UUID'ye sahip olan herhangi biri, o ad alanı içindeki herhangi bir ad için aynı UUID'yi bağımsız olarak oluşturabilir. Bunları hiç yayınlamanıza veya önceden oluşturmanıza bile gerek yok, çünkü ihtiyaç duyulduğunda herkes anında oluşturabilir!

DNS adları ve URL'ler çok yaygın olarak kullanılan ad alanlarıdır, bu nedenle bunlar için standart UUID'ler yayınlanmıştır; ASN.1 OID'ler ve X.500 adları o kadar yaygın değildir, ancak standart kurumları onları sever, bu nedenle onlar için de standart ad alanı UUID'leri yayınladılar.

Diğer tüm ad alanları için, kendi ad alanı UUID'nizi (V1 veya V4) oluşturmanız ve ihtiyacı olan herkese iletmeniz gerekir. Birkaç ad alanınız varsa, her biri için UUID'yi yayınlamak zorunda olmak kesinlikle ideal değildir.

İşte hiyerarşinin devreye girdiği yer burasıdır: Bir "temel" UUID (her türden) yaratırsınız ve sonra bunu diğer ad alanlarınızı adlandırmak için bir ad alanı olarak kullanırsınız! Bu şekilde, yalnızca temel UUID'yi yayınlamanız gerekir (veya açık olanı kullanmanız gerekir) ve herkes geri kalanını hesaplayabilir.

Örneğin, StackOverflow için bazı UUID'ler oluşturmak istediğimizde kalalım; DNS ad alanında açık bir adı vardır, bu nedenle temel açıktır:

uuid ns_dns = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
uuid ns_base = uuidv5(ns_dns, 'stackoverflow.com');

StackOverflow'un kendisi, kullanıcılar, sorular, cevaplar, yorumlar vb. İçin ayrı ad alanlarına sahiptir, ancak bunlar da oldukça açıktır:

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');

Bu özel soru # 10867405, dolayısıyla UUID'si şöyle olacaktır:

uuid here = uuidv5(ns_question, '10867405');

Bu süreçte rastgele bir şey olmadığına dikkat edin , bu nedenle aynı mantığı izleyen herkes aynı cevabı alacaktır, ancak UUID ad alanı o kadar geniştir ki (122 bitlik şifreleme karmasının güvenliği göz önüne alındığında etkili bir şekilde) asla bir Diğer herhangi bir ad alanı / ad çiftinden üretilen UUID.


API'lerinin bir dize olarak yalnızca büyük tamsayıyı döndürdüğü göz önüne alındığında, stackoverflow'un neden benzersiz bir şekilde oluşturulmuş büyük bir tamsayıyı bir UUID'ye eşlemesi gerektiğini merak ediyorum. API'de değilse UUID nerede kullanılır. Görünüşe göre ya bir UUID ya da BIGINT seçmeliyiz? Neden bu karma strateji yapıyorsunuz? Cevabınızdaki net açıklama için henüz +1.
nishant

4
UUID V3 / V5, mevcut (ve muhtemelen çarpışan) ad alanlarını belirleyici olarak tek bir UUID ad alanına dönüştürmeniz gerektiğinde kullanılmak üzere tasarlanmıştır; bu, genellikle veri kümelerini birleştirirken yararlıdır. Bu yaptığınız şey için geçerli değilse, o zaman V1 / V4 ile gidin.
StephenS
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.