2011-08-23 5 views
11

This article wyjaśnia, w jaki sposób generowane są Guidy.Czy możemy zdekodować Guida, aby dowiedzieć się, gdzie i kiedy został wygenerowany?

Moje pytanie brzmi: czy jest jakiś sposób, aby dowiedzieć się, która maszyna w mojej farmie sieci generowała ten Guid i kiedy?

+0

Tak - wszystkie informacje, co musisz zrobić, to w tym artykule i połączonego projektu internetowego. Zakłada się, że identyfikator GUID został wygenerowany za pomocą tego algorytmu, jeśli został wygenerowany przy użyciu innego algorytmu, musisz znaleźć specyfikację/szczegóły tego algorytmu. Możesz użyć pola Wariant (opisanego w powiązanej notatce), aby określić, który wariant układu został użyty. – Justin

Odpowiedz

13

Neil Fenwick ma rację. Jednak możemy wykorzystać tę strukturę na naszą korzyść.

Wersja 4 (.Net)

Wersja 4 UUID używać schematu polegając tylko na liczb losowych. Algorytm ten ustawia numer wersji oraz dwa zarezerwowane bity. Wszystkie inne bity są ustawiane przy użyciu losowego lub pseudolosowego źródła danych. UUID w wersji 4 mają postać xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx gdzie x jest dowolną cyfrą szesnastkową, a y jest jedną z 8, 9, A lub B. f47ac10b-58cc-4372-a567-0e02b2c3d479.

użyć wersji Pole

Jesteśmy wolni, aby zmienić pierwszy półbajt bajtu 8; więc jeśli masz mniej niż 17 maszyn, możesz je zidentyfikować, zmieniając identyfikatory GUID utworzone na każdym z nich.

static Guid NewSystemGuid(int machine) 
{ 
    if (machine < 0 | machine > 0xF) 
     throw new ArgumentOutOfRangeException("machine"); 
    var g = Guid.NewGuid(); 
    var arr = g.ToByteArray(); 
    arr[7] = (byte)((machine << 4) | (arr[7] & 0xF)); 
    return new Guid(arr); 
} 

static int ExtractMachine(Guid guid) 
{ 
    var arr = guid.ToByteArray(); 
    return (arr[7] >> 4) & 0xF; 
} 

użyć wersji Field i „Y”

Nie jestem pewien, czy zmieniając Y zmienią unikalność identyfikatora GUID, więc może się wahać. Jeśli masz mniej niż 17 maszyn, pozostań przy pierwszym rozwiązaniu.

static Guid NewSystemGuid(int machine) 
{ 
    if (machine < 0 | machine > 0xFF) 
     throw new ArgumentOutOfRangeException("machine"); 

    var m1 = machine & 0xF; 
    var m2 = (machine >> 4) & 0xF; 

    var g = Guid.NewGuid(); 
    var arr = g.ToByteArray(); 
    arr[7] = (byte)((m1 << 4) | (arr[7] & 0xF)); 
    arr[8] = (byte)((m2 << 4) | (arr[8] & 0xF)); 
    return new Guid(arr); 
} 

static int ExtractMachine(Guid guid) 
{ 
    var arr = guid.ToByteArray(); 
    return 
     ((arr[7] >> 4) & 0xF) | 
     (((arr[8] >> 4) & 0xF) << 4); 
} 

pomocą wersji i „y” (Redux)

można nadal utrzymywać wartość „y”, ograniczając ilość urządzeń do 63 (przy użyciu 2 ostatnie bity do reprezentowania 4 możliwe wartości 'Y'):

static Guid NewSystemGuid(int machine) 
{ 
    if (machine < 0 | machine > 0x3F) 
     throw new ArgumentOutOfRangeException("machine"); 

    var m1 = machine & 0xF; 
    var m2 = (machine >> 4) & 0xF; 

    var g = Guid.NewGuid(); 
    var arr = g.ToByteArray(); 
    arr[7] = (byte)((m1 << 4) | (arr[7] & 0xF)); 

    var y = (arr[8] >> 4) & 0xF; 
    switch (y) 
    { 
     case 0x8: 
      arr[8] = (byte)((m2 << 4) | (arr[8] & 0xF)); 
      break; 
     case 0x9: 
      arr[8] = (byte)(((m2 | 0x8) << 4) | (arr[8] & 0xF)); 
      break; 
     case 0xA: 
      arr[8] = (byte)(((m2 | 0x4) << 4) | (arr[8] & 0xF)); 
      break; 
     case 0xB: 
      arr[8] = (byte)(((m2 | 0xC) << 4) | (arr[8] & 0xF)); 
      break; 
     default: 
      throw new Exception(); 
    } 
    return new Guid(arr); 
} 

static int ExtractMachine(Guid guid) 
{ 
    var arr = guid.ToByteArray(); 
    return 
     ((arr[7] >> 4) & 0xF) | 
     (((arr[8] >> 4) & 0x3) << 4); 
} 

użyć wersji 1 GUID

Mogłabyś al więc używać wersji 1 GUID, jak to jeszcze możliwe ich generowania:

class SequentialGuid 
{ 
    [DllImport("rpcrt4.dll", SetLastError = true)] 
    static extern int UuidCreateSequential(out Guid guid); 

    public static Guid NewGuid() 
    { 
     Guid guid; 
     UuidCreateSequential(out guid); 
     return guid; 
    } 

    public static byte[] ExtractMacAddress(Guid guid) 
    { 
     var arr = guid.ToByteArray(); 
     // Require version 1. 
     if (((arr[7] >> 4) & 0xF) != 1) 
      throw new ArgumentOutOfRangeException("guid", "GUID is required to be a sequential (version 1) GUID."); 

     var macLong = BitConverter.ToInt64(arr, arr.Length - 8); 
     macLong = IPAddress.NetworkToHostOrder(macLong); 
     arr = BitConverter.GetBytes(macLong); 
     Array.Resize(ref arr, 6); 

     return arr; 
    } 
} 
+0

to był świetny wysiłek :) – Faisal

+0

@Faisal jeśli komentarz rozwiązuje twój problem pamiętaj, aby go zaakceptować :). –

+0

Pamiętałem to; Czekałem tylko na inne odpowiedzi. Zaakceptowany :) – Faisal

Powiązane problemy