2010-02-03 18 views
30

Mam problem generując GUID na sznurku - na przykład:Jak wygenerować identyfikator GUID dla ciągu?

Guid g = New Guid("Mehar"); 

Jak mogę obliczyć GUID dla "Mehar"? Dostaję wyjątek.

+0

Co masz na myśli przez "generowanie identyfikatora GUID dla ciągów"? –

+0

Co próbujesz zrobić Mehar? 'Guid (ciąg)' otrzymuje ciąg sformatowany z guidem, np. '{00000000-0000-0000-0000-000000000000}' –

+0

moja wątpliwość jest potrzebna do wygenerowania unikalnego identyfikatora dla ogólnego ciągu znaków (Mehar), który jest podobny do tego "fc098275- 7af6-4780-9bee-624563ec5cb0 " – Mehar

Odpowiedz

-2

użyć metody statycznej NewGuid(), aby utworzyć GUID, to znaczy Guid g = Guid.NewGuid(); lub string s = Guid.NewGuid().ToString()'

+1

-1 To, co OP wyjaśnił, nie było zamierzone. –

4

Nie można używać GUID tamtędy. constructor of Guid oczekuje prawidłowej, ciągłej reprezentacji Guid.

To, czego szukasz, to funkcja skrótu. (na przykład: MD5)

3

Myślę, że masz nieporozumienie co do tego, czym jest Guid. Nie ma reprezentacji Guida ciągu, takiego jak "Mehar".

Powodem jest przeciążenie new Guid(String s), dzięki czemu można utworzyć przewodnik z typowej reprezentacji ciągów, np. "00000000-0000-0000-0000-000000000000".

Zobacz artykuł wiki, aby uzyskać więcej informacji na temat tego, czym jest Guid.

http://en.wikipedia.org/wiki/Globally_Unique_Identifier

+0

Dziękuję, rozumiem, teraz – Mehar

-1

GUID są losowe, nie są one nierozerwalnie przypisane do dowolnego napisu lub innej wartości.

Jeśli potrzebujesz takiego łączenia, zapisz je w słowniku i sprawdź istniejący kod przed utworzeniem nowego.

+3

Guid nie są całkowicie przypadkowe (lub nawet w większości przypadkowe, IIRC). Kierują się surowym formatem, dzięki czemu mogą rzeczywiście, ale globalnie wyjątkowe, a nie tylko "prawdopodobnie" wyjątkowe :) –

+2

-1: Tylko GUIDy w wersji 4 są losowe. Identyfikatory GUID w wersji 3 i GUID w wersji 5 są w istocie przypisane do ciągu znaków. –

+0

@DavidCary Gdzie są opisane wersje GUID? Czy na pewno nie myślisz o UUID? – Taemyr

17

Jestem całkiem pewien, że mylić z System.Guid chcąc hash (powiedzmy, SHA-256) danego łańcucha.

Należy pamiętać, że przy wyborze algorytmu zabezpieczającego kryptograficznie MD5, SHA0 i SHA1 są wszystkie generally considered dead. SHA2 i nowsze są nadal przydatne.

+0

W jaki sposób SHA2 jest użyteczny, a SHA1 nie, jeśli zgodnie ze swoim linkiem SHA2 ma taki sam status "osłabiony" jak SHA1, tylko od późniejszego terminu? – Ruslan

5

To, czego szukasz, to prawdopodobnie generowanie identyfikatorów UUID w wersji 3 lub 5, które są opartymi na nazwach identyfikatorami UUID. (zalecana jest wersja 5). Nie sądzę, że framework .NET ma wbudowaną obsługę. Zobacz http://en.wikipedia.org/wiki/Universally_Unique_Identifier

Zrobiłem kilka wyszukiwania google, aby zobaczyć, czy mogę znaleźć coś w Win32 API, ale nic nie wymyślił. Jednak jestem pewien, że .NET Framework ma pewne implementacji ukryte gdzieś, ponieważ o ile wiem, podczas generowania obiektu COM w .NET i nie dostarczasz jawnego GUID, to struktura .NET generuje nazwę oparty na UUID, aby utworzyć dobrze zdefiniowany identyfikator ClassID i InterfaceID, tj. identyfikatory UUID, które nie zmieniają się przy każdej rekompilacji (np. VB6). Ale prawdopodobnie jest to ukryte, więc domyślam się, że musisz sam zaimplementować algorytm. Na szczęście .NET zapewnia algorytm MD5 i SHA1, więc nie sądzę, aby wdrożenie UUID w wersji 3 i wersji 5 było zbyt trudne.

71

dość stary wątek, ale jest to w jaki sposób rozwiązać ten problem:

Od Guid użytkownika z .NET Framework są arbitralne 16bytes lub odpowiednio 128bitowe, można obliczyć Guid z dowolnych ciągów stosowanie wszelkich funkcji skrótu do ciąg znaków, który generuje 16-bajtowy skrót i następnie przekazuje wynik do konstruktora Guid.

Zdecydowaliśmy się skorzystać z funkcji skrótu MD5 i przykładowy kod mógłby wyglądać następująco:

 string input = "asdfasdf"; 
     using (MD5 md5 = MD5.Create()) 
     { 
      byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(input)); 
      Guid result = new Guid(hash); 
     } 

Należy pamiętać, że to pokolenie Guid ma kilka wad przez samą jak to zależy od jakości mieszania funkcjonować! Jeśli funkcja mieszająca generuje równe skróty dla wielu ciągów, których używasz, wpłynie to na zachowanie twojego oprogramowania.

Oto lista najpopularniejszych funkcji mieszających, które produkują skrót z 128bit:

  • RIPEMD (prawdopodobieństwo kolizji: 2^18)
  • MD4 (prawdopodobieństwo kolizji: na pewno)
  • MD5 (prawdopodobieństwo kolizji: 2^20,96)

Należy pamiętać, że można użyć także innych funkcji skrótu, które produkują większe digest i po prostu obciąć ci. Dlatego może być sprytniej używać nowszej funkcji skrótu. Aby wymienić niektóre:

  • SHA1
  • SHA-2
  • SHA-3

Dzisiaj (sie 2013) SHA1 hash 160bit można uznać za bycie dobrym wyborem.

+14

Jeśli chcesz utworzyć identyfikator GUID z danych mieszania MD5, powinieneś postępować zgodnie ze standardem i * wskaż *, że jest to [** typ 3 ** guid] (http://en.wikipedia.org /wiki/Universally_unique_identifier#Version_3_.28MD5_hash.29) - co oznacza, że ​​dane pochodzą z skrótu MD5. Identyfikatory GUID typu 3 mają postać "xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx", gdzie ** "3" ** oznacza "typ 3", a symbol y jest zamaskowany na "10xx".Możesz także użyć skrótu SHA1 (Typ 5), gdzie zmienisz 3 na 5. –

+1

Dodałbym komentarz Iana do odpowiedzi, aby wyjaśnić, że nie możesz po prostu przetłumaczyć hasza na GUID: pewne bity w GUID potrzebujesz specjalnych wartości. –

+1

Mówimy tu o GUID, a nie o UUID. Zwróć uwagę na różnicę. –

3

Ogólnie istnieje kilka sposobów na utworzenie uniwersalnego unikalnego identyfikatora (UUID RFC 4122, a.k.a. GUID). Możemy pożyczyć te cztery z Python i zrobić w C# czegoś zarówno:

uuid.uuid1([node[, clock_seq]])

Generowanie UUID z identyfikatora hosta, numeru sekwencji i bieżącej chwili. Jeśli węzeł nie jest podany, funkcja getnode() jest używana do uzyskania adresu sprzętowego . Jeśli podano clock_seq, jest on używany jako numer kolejny; w przeciwnym razie wybierany jest losowy 14-bitowy numer sekwencji.

uuid.uuid3(namespace, name)

Generowanie UUID w oparciu o hash MD5 identyfikator przestrzeni nazw (co jest UUID) i nazwę (która jest ciągiem znaków).

uuid.uuid4()

wygenerować losowy UUID.

uuid.uuid5(namespace, name)

Generowanie UUID opartego na SHA-1 hash identyfikator przestrzeni nazw (co jest UUID) i nazwę (która jest ciągiem znaków).

Więc jeśli potrzebujesz ID ciąg jako przedmiot, a nie identyfikator wartości, należy magiel prywatnych UUID z danego ciągu, Twój prywatny UUID generować raz używając uuid1, a następnie użyć go jako nazw dla uuid3 lub uuid5.

te warianty i wersje opisane na Wikipedii Universally_unique_identifier#Variants_and_versions

2

Jeśli intencją OP jest stworzenie UUID (GUID) z hash ciąg jakiegoś (MD5, SHA-1, et.c.), znalazłem to bardzo podobne pytanie z tym wielkim odpowiedź:

https://stackoverflow.com/a/5657517/430885

ma link do github-urywek oparciu o RFC 4122 §4.3, który stworzy Guid z ciągiem i nazw (które można wybrać dla siebie, aby zapewnić ochronę przed kolizjami ze środowiska zewnętrznego).

Bezpośredni link do fragmentu: https://github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs

0

Tu jest moje własne podejście, ja celowo używając String hex zrzucić jeśli to możliwe - wizualnie widać, przynajmniej jak duży ciąg jest, a jeśli trzeba - dekodowane za pomocą konwertera hexa online. Ale jeśli łańcuch jest zbyt długi (więcej niż 16 bajtów) - wtedy użyjemy sha-1 do obliczenia skrótu i ​​wygenerowania z niego polecenia.

/// <summary> 
/// Generates Guid based on String. Key assumption for this algorithm is that name is unique (across where it it's being used) 
/// and if name byte length is less than 16 - it will be fetched directly into guid, if over 16 bytes - then we compute sha-1 
/// hash from string and then pass it to guid. 
/// </summary> 
/// <param name="name">Unique name which is unique across where this guid will be used.</param> 
/// <returns>For example "{706C7567-696E-7300-0000-000000000000}" for "plugins"</returns> 
static public String GenerateGuid(String name) 
{ 
    byte[] buf = Encoding.UTF8.GetBytes(name); 
    byte[] guid = new byte[16]; 
    if (buf.Length < 16) 
    { 
     Array.Copy(buf, guid, buf.Length); 
    } 
    else 
    { 
     using (SHA1 sha1 = SHA1.Create()) 
     { 
      byte[] hash = sha1.ComputeHash(buf); 
      // Hash is 20 bytes, but we need 16. We loose some of "uniqueness", but I doubt it will be fatal 
      Array.Copy(hash, guid, 16); 
     } 
    } 

    // Don't use Guid constructor, it tends to swap bytes. We want to preserve original string as hex dump. 
    String guidS = "{" + String.Format("{0:X2}{1:X2}{2:X2}{3:X2}-{4:X2}{5:X2}-{6:X2}{7:X2}-{8:X2}{9:X2}-{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}", 
     guid[0], guid[1], guid[2], guid[3], guid[4], guid[5], guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]) + "}"; 

    return guidS; 
} 
Powiązane problemy