Generowanie UUID v5. Co to jest nazwa i przestrzeń nazw?

Przeczytałem stronę man, ale nie wiem Do czego służą name i namespace.

Dla wersji 3 i wersji 5 uuid dodatkowego wiersza poleceń argumenty przestrzeń nazw i nazwa muszą być podane. Przestrzeń nazw jest albo UUID w reprezentacji łańcuchów lub identyfikator wewnętrznie predefiniowanych identyfikatorów uuid przestrzeni nazw (obecnie znane są "ns:DNS", "NS:URL", "NS:OID" i "ns:X500"). Na nazwa jest ciągiem o dowolnej długości.

The przestrzeń nazw:

Przestrzeń nazw jest albo UUID w reprezentacji łańcuchowej, albo

Czy to znaczy, że muszę go przechowywać (UUID v4) gdzieś w związku z wygenerowanym UUID v5? W obu przypadkach, dlaczego nie odbywa się to automatycznie?

Nazwa jest ciągiem o dowolnej długości.

name zupełnie przypadkowy ciąg? W takim razie jaki jest jego cel? Czy można go dekodować z UUID v5?

 142
Author: Gajus, 2012-06-03

3 answers

Nazwa i przestrzeń nazw mogą być używane do tworzenia hierarchii (bardzo prawdopodobnie) unikalnych uuid.

Z grubsza rzecz biorąc, identyfikator uuid typu 3 lub 5 jest generowany przez połączenie identyfikatora przestrzeni nazw z nazwą. Uuid typu 3 używa MD5, a uuid typu 5-SHA1. Tylko 128-bitowe są dostępne i 5-bitowe są używane do określenia typu, więc wszystkie bity skrótu nie trafiają do UUID. (Również MD5 jest uważany za złamany kryptograficznie, a SHA1 jest na ostatnich nogach, więc nie używaj tego do weryfikacji danych to musi być "bardzo bezpieczne"). To powiedziawszy, daje sposób na stworzenie powtarzalnej / weryfikowalnej funkcji "hash" mapującej prawdopodobnie hierarchiczną nazwę na probabilistycznie unikalną 128-bitową wartość, potencjalnie działającą jak hierarchiczny hash lub MAC.

Załóżmy, że masz magazyn (klucz, wartość), ale obsługuje on tylko jedną przestrzeń nazw. Możesz wygenerować dużą liczbę różnych logicznych przestrzeni nazw za pomocą identyfikatorów uuid typu 3 lub 5. Najpierw Utwórz root UUID dla każdej przestrzeni nazw. To może być Typ 1 (host+timestamp) lub wpisz 4 (losowy) UUID, o ile gdzieś go schowasz. Alternatywnie możesz utworzyć jeden losowy UUID dla roota (lub użyć null UUID: 00000000-0000-0000-0000-000000000000 jako root), a następnie utworzyć powtarzalny UUID dla każdej przestrzeni nazw za pomocą "uuid -v5 $ROOTUUID $NAMESPACENAME". Teraz możesz tworzyć unikalne uuid dla kluczy w przestrzeni nazw za pomocą "uuid -v5 $NAMESPACEUUID $KEY". Te uuid można wrzucić do jednego magazynu wartości klucza z dużym prawdopodobieństwem uniknięcia kolizji. Proces ten można powtarzać rekurencyjnie tak, że jeśli dla przykład "wartość" powiązana z kluczem UUID z kolei reprezentuje jakiś rodzaj logicznej "przestrzeni nazw", takiej jak wiadro, kontener lub katalog, a następnie jego UUID może być użyty z kolei do generowania bardziej hierarchicznych uuid.

Wygenerowany UUID typu 3 lub typu 5 zawiera (częściowy) hash przestrzeni nazw id i name-within-namespace (klucz). Nie posiada on więcej przestrzeni nazw UUID niż wiadomość MAC przechowująca zawartość wiadomości, z której jest zakodowana. Nazwa jest ciągiem "arbitralnym" (oktetem) z perspektywa algorytmu uuid. Jego znaczenie zależy jednak od twojej aplikacji. Może to być nazwa pliku w katalogu logicznym, object-id w obiekcie-store, itd.

Chociaż działa to dobrze dla umiarkowanie dużej liczby przestrzeni nazw i kluczy, ostatecznie kończy się, jeśli dążysz do bardzo dużej liczby kluczy, które są unikalne z bardzo dużym prawdopodobieństwem. Wpis na Wikipedii dotyczący problemu urodzinowego (aka paradoks urodzinowy) zawiera tabelę, która daje prawdopodobieństwo co najmniej jednej kolizji dla różnych liczb kluczy i rozmiarów tabel. Dla 128-bitów, hashowanie 26 miliardów kluczy w ten sposób ma prawdopodobieństwo kolizji p=10^-18 (nieistotne), ale 26 bilionów kluczy zwiększa prawdopodobieństwo co najmniej jednej kolizji do p=10^-12 (jeden na trylion), a hashowanie 26*10^15 kluczy zwiększa prawdopodobieństwo co najmniej jednej kolizji do p=10^-6 (jeden na milion). Dostosowanie do 5 bitów kodujących Typ UUID, skończy się nieco szybciej, więc bilion kluczy mają mniej więcej 1 w bilionie szans na jedną kolizję.

Zobacz http://en.wikipedia.org/wiki/Birthday_problem#Probability_table dla tabeli prawdopodobieństwa.

Zobacz http://www.ietf.org/rfc/rfc4122.txt aby uzyskać więcej szczegółów na temat kodowania UUID.

 117
Author: Jeff Anderson-Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 06:46:50

Uuid typu 3 i 5 to tylko technika wpychania hash do UUID:

  • Type 1 : stuffs MAC address+datetime na 128 bitów
  • Type 3 : stuffs an MD5 hash na 128 bitów
  • Type 4 : stuffs losowe DANE na 128 bitów
  • Type 5 : stuffs an SHA1 hash na 128 bitów
  • Typ 6: nieoficjalny pomysł dla sekwencyjnych uuid

Skrót SHA1 wyświetla 160 bitów (20 bajtów); wynik tego skrótu jest zamieniany na UUID.

Z 20-bajtowym digestem z 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

(zauważ, że pierwsze dwa bity '9' to odpowiednio 1 i 0, więc nie ma to żadnego wpływu).

Co mam hashować?

Pewnie zastanawiasz się, co to jest, że mam haszysz. W zasadzie masz konkatenację of:

Sha1 ( Namespaceuid+AnyString);

Przedrostek łańcucha tworzy się w przestrzeni nazw , aby zapobiec konfliktom nazw.

Uuid RFC wstępnie definiuje cztery przestrzenie nazw dla ciebie:

  • NameSpace_DNS: {6ba7b810-9-11d1-80b4-00c04fd430c8}
  • NameSpace_URL: {6ba7b811-9-11d1-80b4-00c04fd430c8}
  • NameSpace_OID: {6ba7b812-9-11d1-80b4-00c04fd430c8}
  • NameSpace_X500: {6ba7b814-9-11d1-80b4-00c04fd430c8}

Więc moglibyście razem hashować:

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

Następnie RFC definiuje jak:

  • weź 160 bitów z SHA1
  • i przekształcić go w 128 bitów UUID

Podstawowy gist polega na pobieraniu tylko pierwszych 128 bitów, stuff a 5 w rekordzie typu, a następnie Ustaw dwa pierwsze bity sekcji clock_seq_hi_and_reserved na 1 i 0, odpowiednio.

Więcej przykładów

Teraz , gdy masz funkcję, która generuje tak zwaną nazwę , możesz mieć funkcję (w pseudo-kodzie):

UUID NameToUUID(UUID NamespaceUUID, String Name)
{
    //Note: All code on stackoverflow is public domain - no attribution required.

    Byte[] hash = sha1(NamespaceUUID.ToBytes() + Name.ToBytes());
    Uuid result;

    //Copy first 16-bytes of the hash into our Uuid result
    Copy(hash, result, 16);

    //set high-nibble to 5 to indicate type 5
    result[6] &= 0x0F; 
    result[6] |= 0x50; 

    //set upper two bits to "10"
    result[8] &= 0x3F; 
    result[8] |= 0x80; 

    return result;
}

(Uwaga: endian-ness Twojego systemu może wpływać na indeksy powyższych bajtów)

Teraz możesz mieć połączenia:

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

A teraz wróć do pytania

Dla identyfikatorów uuid wersji 3 i 5 Należy podać dodatkową przestrzeń nazw i nazwę argumentów wiersza poleceń. Przestrzeń nazw jest albo uuid w reprezentacji łańcuchowej lub identyfikator wewnętrznie predefiniowanej przestrzeni nazw uuid (obecnie znane są "NS:DNS", "NS:URL", "NS:OID" i "ns:X500"). Nazwa jest ciągiem o dowolnej długości.

Przestrzeń nazw jest tym, co lubisz. Może to być jeden z predefiniowanych, lub można tworzyć własne, np.:

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

Nazwa jest ciągiem o dowolnej długości.

Nazwa to tylko tekst, który chcesz dołączyć do w tym celu należy wykonać następujące czynności:]}

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');
 232
Author: Ian Boyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-08 20:23:13

Nazwa jest niczym innym jak identyfikatorem, który jest unikalny w jakiejś przestrzeni nazw. Problem polega na tym, że przestrzenie nazw są często dość małe, a nazwy w jednym często zderzają się z nazwami w innych. Na przykład numer rejestracyjny (nazwa) mojego samochodu jest unikalny w przestrzeni nazw mojego stanu DMV, ale prawdopodobnie nie jest unikalny na świecie; Inne stanowe DMV mogły używać tej samej nazwy w swoich własnych przestrzeniach nazw. Heck, ktoś inny może mieć numer telefonu (imię), który również pasuje, bo to jeszcze Inna Przestrzeń nazw itp.

Uuidy mogą być postrzegane jako zamieszkujące pojedynczą przestrzeń nazw tak rozległą, że może zapewnić unikalną nazwę dla wszystkiego ; to właśnie oznacza "uniwersalne". Ale jak mapować istniejące nazwy w innych przestrzeniach nazw na UUID?

Oczywistym rozwiązaniem jest wygenerowanie UUID (V1 lub V4) dla każdego elementu, który zastąpi stare nazwy w ich rozdzielonych przestrzeniach nazw. Minusem jest to, że są dużo większe, trzeba komunikować wszystkie nowe nazwy każdemu, kto ma Kopia zestawu danych, Aktualizacja wszystkich interfejsów API itp. Szanse są takie, że nie możesz całkowicie pozbyć się starych nazw, co oznacza, że teraz każdy przedmiot ma dwie nazwy, więc zrobiłeś wszystko lepiej czy gorzej?

Tutaj wkraczają V3/V5. Uuid wygląda tak samo losowo jak V4, ale jest deterministyczny; każdy, kto ma prawo UUID dla przestrzeni nazw, może wtedyniezależnie wygenerować ten sam UUID dla dowolnej nazwy w tej przestrzeni nazw. Nie musisz publikuj je w ogóle, ani nawet wstępnie Generuj, ponieważ każdy może je tworzyć w locie w razie potrzeby!

Nazwy DNS i adresy URL są bardzo często używanymi przestrzeniami nazw, więc dla nich zostały opublikowane standardowe uuid; ASN.1 nazwy OIDs i X. 500 nie są tak powszechne, ale organy standardów je uwielbiają, więc opublikowały dla nich również standardowe nazwy UUIDs.

Dla wszystkich innych przestrzeni nazw, musisz wygenerować własną przestrzeń nazw UUID (V1 lub V4) i przekazać ją każdemu, kto jej potrzebuje. Jeśli masz kilka przestrzenie nazw, konieczność publikowania UUID dla każdej z nich nie jest idealna.

Tutaj pojawia się hierarchia: tworzysz jeden "bazowy" UUID (dowolnego typu), a następnie używasz go jako przestrzeni nazw do nazywania innych przestrzeni nazw! W ten sposób wystarczy opublikować podstawowy UUID (lub użyć oczywistego), a każdy może obliczyć resztę.

Na przykład, pozostańmy, chcieliśmy utworzyć kilka uuid dla StackOverflow; który ma oczywistą nazwę w przestrzeni nazw DNS, więc baza jest oczywiste:

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

Sam StackOverflow ma osobne przestrzenie nazw dla użytkowników, pytań, odpowiedzi, komentarzy itp., ale te też są dość oczywiste:

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

To pytanie to #10867405, więc jego UUID będzie:

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

Zauważ, że nie ma nic przypadkowego w tym procesie, więc każdy, kto podąża za tą samą logiką, otrzyma tę samą odpowiedź, jednak Przestrzeń nazw UUID jest tak rozległa, że (w praktyce, biorąc pod uwagę bezpieczeństwo 122-bitowego hasha kryptograficznego) nigdy koliduje z UUID wygenerowanym z innej przestrzeni nazw / pary nazw.

 28
Author: StephenS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-11 12:45:07