2011-08-23 10 views
11

This article spiega come vengono generati i Guids.Possiamo decodificare un Guid per scoprire dove e quando è stato generato?

La mia domanda è che c'è un modo per scoprire quale macchina nella mia web farm ha generato questo Guid e quando?

+0

Sì, tutte le informazioni necessarie per eseguire questa operazione si trovano in questo articolo e nella bozza Internet collegata. Ciò presuppone che il GUID sia stato generato con tale algoritmo, se è stato generato con un algoritmo diverso è necessario trovare la specifica/i dettagli di tale algoritmo. È possibile utilizzare il campo Variant (descritto nel memo collegato) per determinare quale variante di layout è stata utilizzata. – Justin

risposta

13

Neil Fenwick è corretto. Tuttavia possiamo usare la struttura a nostro vantaggio.

versione 4 (Net)

Versione 4 UUID utilizzare uno schema contando solo su numeri casuali. Questo algoritmo imposta il numero di versione e due bit riservati. Tutti gli altri bit vengono impostati utilizzando un'origine dati casuale o pseudocasuale. Gli UUID versione 4 hanno il formato xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx dove x è qualsiasi cifra esadecimale e y è uno tra 8, 9, A o B. ad es. f47ac10b-58CC-4372-a567-0e02b2c3d479.

utilizzare il campo Versione

Siamo liberi di cambiare il primo nibble del byte di 8; quindi se hai meno di 17 macchine puoi identificarle modificando i GUID creati su ognuno di essi.

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

utilizzare il campo Versione e 'y'

Io non sono sicuro se la modifica Y altererà l'unicità del GUID, così il vostro chilometraggio può variare. Se hai meno di 17 macchine, rimani con la prima soluzione.

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

usare la versione e 'y' (Redux)

È ancora possibile mantenere il valore 'y' limitando la quantità di macchine a 63 (utilizzando gli ultimi 2 bit per rappresentare la 4 possibili valori di '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); 
} 

utilizzare la versione 1 GUID

Si potrebbe al quindi utilizza GUID versione 1, poiché è ancora possibile generarli:

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

questo è stato un grande sforzo :) – Faisal

+0

@Faisal se il commento risolve il tuo problema ricordati di accettarlo :). –

+0

L'ho ricordato; Stavo solo aspettando altre risposte. Accettato :) – Faisal

Problemi correlati