Cómo Crear Determinista Guid

En nuestra aplicación que estamos creando archivos Xml con un atributo que tiene un valor Guid. Este valor debía ser coherente entre el archivo de actualizaciones. Así que, incluso si todo lo demás en el archivo de cambios, el guid de valor para el atributo debe seguir siendo el mismo.

Una solución obvia era crear una estática diccionario con el nombre y el Guid para ser utilizado por ellos. Entonces, cuando se genera el archivo, vamos a buscar palabras en el diccionario para el nombre de archivo y usar el guid correspondiente. Pero esto no es factible, debido a que podría escala a 100 de los archivos y no quieren mantener la gran lista de guid.

Otra posibilidad era hacer el Guid de la misma basada en la ruta de acceso del archivo. Desde nuestras rutas de los archivos y la estructura de directorio de aplicación son únicos, el Guid, debe ser única para que la ruta de acceso. Así que cada vez que se ejecute una actualización, el archivo tiene el mismo guid basado en su camino. He encontrado una buena forma de generar este tipo de ‘Determinista Guid‘ (Gracias Elton Stoneman). Básicamente hace eso:

private Guid GetDeterministicGuid(string input) 

{ 

//use MD5 hash to get a 16-byte hash of the string: 

MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider(); 

byte[] inputBytes = Encoding.Default.GetBytes(input); 

byte[] hashBytes = provider.ComputeHash(inputBytes); 

//generate a guid from the hash: 

Guid hashGuid = new Guid(hashBytes); 

return hashGuid; 

} 

Así que dada una cadena, el Guid siempre será el mismo.

Hay otros enfoques o métodos recomendados para hacer esto? ¿Cuáles son los pros o los contras de ese método?

OriginalEl autor Punit Vora | 2010-04-15

5 Kommentare

  1. 133

    Como lo menciona @bacar, RFC 4122 §4.3) define una manera de crear un nombre basado en el UUID. La ventaja de hacer esto (en tan solo utilizando un hash MD5) es que estos son la garantía de que no colisionan con los sin nombre basado en los Uuid, y tiene una muy (muy) pequeña posibilidad de colisión con otro nombre basado en los Uuid.

    No hay soporte nativo en el .NET Framework para la creación de estos, pero he publicado el código en GitHub que implementa el algoritmo. Puede ser utilizado de la siguiente manera:

    Guid guid = GuidUtility.Create(GuidUtility.UrlNamespace, filePath);

    Para reducir el riesgo de colisiones con otros Guid aún más, se podría crear un privado GUID utilizar como ID de espacio de nombres (en lugar de utilizar el espacio de nombres de URL ID definido en el RFC).

    Estoy muy feliz de haber encontrado este, gracias por publicarlo.
    RFC4122 es incorrecta y tiene la fe de erratas que corrige el código C (rfc-editor.org/errata_search.php?rfc=4122& ‘ id=1352). Si esta aplicación no es totalmente compatible con RFC4122 y su fe de erratas, por favor proporcione más detalles; me gustaría hacer es seguir el estándar.
    Yo no me di cuenta de que, gracias/lo siento! Yo siempre debe recordar para comprobar la fe de erratas cuando la lectura de un RFC… 🙂
    Eres bienvenido/no hay problema. Se perturba la mente que no actualizar el RFC en el lugar con las correcciones de las erratas. Incluso un enlace al final del documento sería mucho más útil que confiar en los que el lector recuerde de la búsqueda por fe de erratas (esperemos que antes escribir una implementación basada en el RFC…).
    Usted debería considerar la posibilidad de contribuir a este .NET .NET repo está aquí:github.com/dotnet/coreclr/tree/master/src/mscorlib/src/System

    OriginalEl autor Bradley Grainger

  2. 25

    Este va a convertir cualquier cadena en un Guid sin tener que importar un fuera de la asamblea.

    public static Guid ToGuid(string src)
    {
        byte[] stringbytes = Encoding.UTF8.GetBytes(src);
        byte[] hashedBytes = new System.Security.Cryptography
            .SHA1CryptoServiceProvider()
            .ComputeHash(stringbytes);
        Array.Resize(ref hashedBytes, 16);
        return new Guid(hashedBytes);
    }

    Hay mucho mejores formas para generar un Guid único, pero esta es una manera de reforzar continuamente una cadena de datos clave para un Guid de datos clave.

    Encontré este fragmento de código para ser útil cuando se utiliza identificador único en una base de datos federados de distribución.
    Advertencia! Este código no genera válido Guid / Uuid (como bacar también se menciona a continuación). Ni la versión ni el tipo de campo se han establecido correctamente.
    ¿No sería igual de efectivo para el uso de la MD5CryptoServiceProvider en lugar de la SHA1, desde MD5 es ya el 16 bytes de longitud?

    OriginalEl autor Ben Gripka

  3. 18

    Como Rob menciona, su método no genera un UUID, se genera un hash que se parece a un UUID.

    La RFC 4122 en Uuid permite específicamente determinista (nombre) con el Uuid – Versiones de 3 y 5 utilizar md5 y SHA1(respectivamente). La mayoría de la gente probablemente está familiarizado con la versión 4, que es al azar. Wikipedia da una buena visión general de las versiones. (Tenga en cuenta que el uso de la palabra «versión» aquí parece describir un ‘tipo’ de UUID de la versión 5 no reemplazar a la versión 4).

    Parece ser que hay un par de librerías que hay para la generación de la versión 3/5 Uuid, incluyendo la python uuid módulo, boost.uuid (C++) y OSSP UUID. (Yo no he visto por ninguna .net)

    Esto es exactamente lo que el cartel original es después. UUID ya tiene un algoritmo para empezar con una cadena y convertirlo en un GUID. UUID de la versión 3 de hash de la cadena con MD5, mientras que la versión 5 de hashes con SHA1. El punto importante en la creación de un «guid» se hace «único» contra otros Guid. El algoritmo define dos bits que se deben establecer, así como de un nibble se establece en 3 o 5, dependiendo de si es la versión 3 o 5.
    Con respecto al uso de la palabra «versión», RFC 4122 §4.1.3 los estados: «La versión es más exactamente un sub-tipo; de nuevo, nos reservamos el plazo para la compatibilidad.»
    He publicado algunos de código de C# para crear v3 y v5 Guid en GitHub: github.com/LogosBible/Logos.Utility/blob/master/src/…
    Yo Aviso or bit a Bit de operador utilizado en un signo extendido operando; considerar la posibilidad de la conversión a un menor sin signo tipo de
    Esto se está poniendo fuera de tema! Sugieren mover individuales lib informes de errores a GitHub.

    OriginalEl autor bacar

  4. 5

    MD5 es débil, yo creo que se puede hacer lo mismo con SHA-1 y obtener mejores resultados.

    Por CIERTO, sólo una opinión personal, vestirse un hash md5 como un GUID no hacen un buen GUID. Guid, por su propia naturaleza no Determinista. esto se siente como una trampa. ¿Por qué no llamar al pan, pan y solo decir que es una cadena prestados hash de la entrada. puede hacerlo mediante el uso de esta línea, en lugar de la nueva guid línea:

    string stringHash = BitConverter.ToString(hashBytes)
    Gracias por tu aporte, pero esto me da una cadena, y estoy buscando un GUID…
    Ok, llame a su hash de una «GUID», problema resuelto. O es el verdadero problema que una Guid objeto?
    ojalá fuera así de simple.. 🙂 pero sí, necesito un ‘GUID’ objeto
    «Guid, por su propia naturaleza no Determinista» – esto es cierto sólo de ciertos tipos (‘versiones’) de Guid. Sin embargo estoy de acuerdo en que «vestir un hash md5 como un GUID no hacer una buena GUID», por otras razones, como las descritas por @Bradley Grainger y @Rob Fonseca-Ensor, y mi respuesta a esta pregunta.

    OriginalEl autor ryber

  5. 3

    Que usted necesita para hacer una distinción entre las instancias de la clase Guid, y los identificadores globalmente únicos. Un «determinista guid» es en realidad un hash (como se evidencia por su llamada a provider.ComputeHash). Hash tiene una probabilidad mucho mayor de colisiones (dos cadenas diferentes sucediendo para producir el mismo hash) de Guid creado a través de Guid.NewGuid.

    Por lo que el problema con su enfoque es que usted tendrá que estar bien con la posibilidad de que dos caminos diferentes, se producirá el mismo GUID. Si usted necesita un identificador que es único para cualquier cadena de ruta de acceso, entonces la cosa más fácil de hacer es sólo uso de la cadena. Si usted necesita la cadena ser apartadas de sus usuarios, cifrar – usted puede utilizar ROT13 o algo más potente…

    Intentar calzador algo que no es un puro GUID en el GUID tipo de datos podría llevar a problemas de mantenimiento en el futuro…

    Usted reclama «Hash tiene una probabilidad mucho mayor de colisiones … que Guid creado a través de Guid.NewGuid.». ¿Puede explicar eso? Desde un punto de Vista matemático, el número de bits que se puede establecer es el mismo, y ambos MD5 y SHA1 son los hash criptográfica, específicamente diseñado para reducir la probabilidad de (accidental o intencional) colisiones de hash.

    OriginalEl autor Rob Fonseca-Ensor

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea