2010-02-03 24 views
30

Estoy teniendo un problema que genera un GUID para una cadena - por ejemplo:¿Cómo puedo generar un GUID para una cadena?

Guid g = New Guid("Mehar"); 

¿Cómo puedo calcular un GUID para "Mehar"? Estoy recibiendo una excepción.

+0

¿Qué quiere decir con "generate GUID for strings"? –

+0

¿Qué estás tratando de hacer Mehar? 'Guid (cadena)' recibe una cadena con formato guid, como '{00000000-0000-0000-0000-000000000000}' –

+0

mi duda es que necesito generar una identificación única para una cadena general (Mehar) que es así "fc098275- 7af6-4780-9bee-624563ec5cb0 " – Mehar

Respuesta

-2

utiliza el método estático NewGuid() para crear GUID, es decir, Guid g = Guid.NewGuid(); o string s = Guid.NewGuid().ToString()'

+1

-1 No es lo que el OP ha aclarado fue la intención –

4

no puede utilizar GUID de esa manera. El constructor of Guid espera una representación de cadena válida de un Guid.

Lo que está buscando se llama función Hash. (por ejemplo: MD5)

3

Creo que tiene un malentendido sobre lo que realmente es un Guid. No hay representación Guid de una cadena como "Mehar".

La razón por la cual hay una sobrecarga de new Guid(String s) es para que pueda crear un guid a partir de una representación de cadena típica de uno, como "00000000-0000-0000-0000-000000000000".

Consulte el artículo de la wiki para obtener más información sobre qué es realmente Guid.

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

+0

Gracias entiendo ahora – Mehar

-1

GUID son al azar, no se asignan intrínsecamente a cualquier cadena u otro valor.

Si necesita tal enlace, almacene las guías en un diccionario y busque un guid existente primero antes de crear uno nuevo.

+3

Guid no son completamente al azar (o incluso mayormente al azar, IIRC). Siguen un formato estricto para que puedan, de hecho, pero globalmente únicos, no solo "probablemente" únicos :) –

+2

-1: Solo los GUID de la versión 4 son aleatorios. Los GUID de la versión 3 y los GUID de la versión 5 están, de hecho, intrínsecamente asignados a una cadena. –

+0

@DavidCary ¿Dónde se describen las versiones de GUID? ¿Estás seguro de que no estás pensando en UUID? – Taemyr

17

Estoy bastante seguro de que has confundido System.Guid con querer un hash (digamos, SHA-256) de una cadena determinada.

Tenga en cuenta que, al seleccionar un algoritmo hash criptográficamente seguro, MD5, SHA0 y SHA1 son todos generally considered dead. SHA2 y hasta todavía se pueden usar.

+0

¿Cómo se usa SHA2 y SHA1 no, si, de acuerdo con su enlace, SHA2 tiene el mismo estado "debilitado" que SHA1, solo desde una fecha posterior? – Ruslan

5

Lo que está buscando probablemente sea generar UUID versión 3 o versión 5, que son UUID basados ​​en nombre. (la versión 5 es la recomendada). No creo que el .NET Framework tenga soporte para eso. Ver http://en.wikipedia.org/wiki/Universally_Unique_Identifier

Hice algunas búsquedas en Google para ver si podía encontrar algo en la API de Win32, pero no apareció nada. Sin embargo, estoy seguro de que el .NET Framework tiene alguna implementación oculta en alguna parte, porque hasta donde yo sé, cuando se genera un objeto COM en .NET, y no se proporciona un GUID explícito, el framework .NET genera un nombre UUID basado en crear un ClassID e InterfaceID bien definidos, es decir, UUID que no cambian cada vez que recompila (como VB6). Pero esto probablemente esté oculto, así que supongo que debes implementar el algoritmo tú mismo. Afortunadamente, .NET proporciona un algoritmo MD5 y SHA1, por lo que no creo que la implementación de un UUID versión3 y versión5 sea demasiado difícil.

71

bastante viejo este hilo, pero así es como hemos resuelto este problema:

Desde Guid de del marco .NET son 16 bytes arbitrarias, o respectivamente de 128 bits, se puede calcular un GUID de cadenas arbitrarias mediante la aplicación de una función hash para la cadena que genera un hash de 16 bytes y luego pasa el resultado al constructor Guid.

se decidió utilizar la función hash MD5 y un código de ejemplo podría tener este aspecto:

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

Tenga en cuenta que esta generación Guid tiene algunos defectos por sí misma como que depende de la calidad del hash ¡función! Si su función hash genera hashes iguales para una gran cantidad de cadenas que utiliza, va a afectar el comportamiento de su software.

Aquí es una lista de las funciones hash más populares que producen un compendio de 128 bits:

  • RIPEMD (probabilidad de colisión: 2^18)
  • MD4 (probabilidad de colisión: seguro)
  • MD5 (probabilidad de colisión: 2^20,96)

Tenga en cuenta que también se pueden utilizar otras funciones de hash que producen digiere más grandes y simplemente truncan los. Por lo tanto, puede ser inteligente usar una nueva función hash. Para enumerar algunas:

  • SHA1
  • SHA-2
  • SHA-3

Hoy (agosto de 2013) el hash SHA1 160bit puede ser considerado ser una buena opción.

+14

Si va a crear un GUID a partir de datos hash MD5, realmente debe seguir el estándar, y * indicar * que este es un [** Tipo 3 ** guid] (http://en.wikipedia.org /wiki/Universally_unique_identifier#Version_3_.28MD5_hash.29) - lo que significa que los datos provienen de un hash MD5. Los GUID de tipo 3 tienen la forma 'xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx', donde ** ** 3' indica 'Tipo 3' e y está enmascarado en' 10xx'.También puede usar el hashing SHA1 (Tipo 5), donde cambia el 3 a 5. –

+1

Agregaría el comentario de Ian a la respuesta para ayudar a aclarar que no se puede simplemente transponer el hash en un GUID: ciertos bits en el GUID necesita valores especiales. –

+1

Estamos hablando de un GUID y no de un UUID. Toma nota de la diferencia. –

3

En general, hay pocas formas de crear una ID universal única (UUID RFC 4122, a.k.a GUID). Nos prestaron estos cuatro desde Python, y hacer algo en C# por igual:

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

generar un UUID de un ID de host, número de secuencia, y la hora actual. Si no se proporciona nodo, getnode() se utiliza para obtener la dirección de hardware . Si se da clock_seq, se usa como el número de secuencia; ; de lo contrario, se elige un número de secuencia aleatorio de 14 bits.

uuid.uuid3(namespace, name)

generar un UUID basado en el hash MD5 de un identificador de nombre (que es un UUID) y un nombre (que es una cadena).

uuid.uuid4()

generar un UUID al azar.

uuid.uuid5(namespace, name)

generar un UUID basado en el hash SHA-1 de un identificador de nombre (que es un UUID) y un nombre (que es una cadena).

Así que si necesitas Identificación de una cadena como un objeto, no Identificación de un valor, debe destrozar su UUID privado con cadena dada, Su UUID privada genere una vez usando uuid1, y luego usarlo como espacio de nombres para uuid3 o uuid5.

Estas variantes y versiones descritas en la Wikipedia Universally_unique_identifier#Variants_and_versions

2

Si la intención del op es crear un UUID (GUID) de un hash de la cadena de algún tipo (MD5, SHA-1, et.c.), he encontrado este pregunta muy similar con este gran respuesta:

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

Tiene un enlace a un fragmento de github-basado en el RFC 4122 § 4.3, que va a crear un GUID de una cadena y un espacio de nombres (que se puede elegir para usted mismo para garantizar contra las colisiones de ambientes externos).

Enlace directo al fragmento: https://github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs

0

Aquí está mi propio enfoque, estoy intencionalmente la cadena de volcado hexadecimal si es posible - visualmente se puede ver, al menos, tan grande cadena es, y si es necesario - decodificados usando algún convertidor hexadecimal en línea. Pero si la cadena es demasiado larga (más de 16 bytes), entonces use sha-1 para calcular el hash y generar el guid a partir de él.

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