Versiones de UUID y cuándo usar cada una
(ntietz.com)- Los UUID tienen 8 versiones, de la v1 a la v8, y que el número sea más alto no significa que sea más nuevo o mejor, sino que RFC 9562 define distintos métodos de generación
- En la práctica, las opciones habituales se reducen a v4 y v7: v4 es la opción predeterminada para IDs aleatorios y v7 es adecuada cuando se necesita ordenar por momento de creación
- v1 y v6 usan los mismos componentes, pero v6 reorganiza los campos para que, al ordenarlos, queden en orden cronológico de creación
- v3 y v5 crean UUID a partir de un hash de los datos de entrada: v3 usa MD5 y v5 usa SHA-1; entre los posibles valores de entrada están DNS y URL
- En la práctica, conviene usar v7 en lugar de v1·v6 cuando sea posible; si necesitas un UUID basado en datos de entrada, considera v5; y si necesitas un UUID completamente personalizado, revisa v8
Métodos de generación por versión de UUID
- Las versiones de UUID van de la v1 a la v8 y todas están definidas en RFC 9562
-
UUID basados en tiempo
- UUID Version 1 se genera con timestamp, un contador monótono y una dirección MAC
- UUID Version 6 usa los mismos datos que v1, pero cambia el orden para que al ordenar queden por tiempo de creación
- UUID Version 7 se genera con timestamp y datos aleatorios
-
UUID aleatorios y definidos por el usuario
- UUID Version 4 se genera completamente con datos aleatorios y es la forma más cercana a lo que mucha gente imagina cuando piensa en un UUID
- UUID Version 8 es completamente definido por el usuario, salvo los campos version/variant requeridos en todas las versiones
-
UUID basados en hash de datos de entrada
- UUID Version 3 se genera con el hash MD5 de los datos proporcionados por el usuario
- Entre los posibles valores de entrada del RFC están DNS y URL
- UUID Version 5 se genera con el hash SHA-1 de los datos proporcionados por el usuario
- Igual que en v3, DNS y URL pueden usarse como entradas candidatas
- UUID Version 3 se genera con el hash MD5 de los datos proporcionados por el usuario
-
UUID reservados
- UUID Version 2 está reservada para IDs de seguridad y no se conocen detalles públicos
Criterios de elección en la práctica
- En la mayoría de los casos, la elección real es entre v4 o v7
- Si solo necesitas un ID aleatorio, v4 es la opción predeterminada adecuada
- Si el ID debe poder ordenarse, puedes considerar v7
- Por ejemplo, si usas un UUID como clave de base de datos, v7 puede ser una buena candidata
- v5 o v8 se acercan más a casos donde quieres incluir tus propios datos dentro del UUID
- En este tipo de casos, muchas veces el usuario ya sabe de antemano que lo necesita
- Según el RFC, v7 mejora v1 y v6, así que cuando sea posible conviene usar v7 en lugar de v1·v6
- Si realmente necesitas v1 o v6, puedes usar v6
- v2 está reservada para un uso de seguridad no especificado
- v3 fue reemplazada por v5, que usa un hash más fuerte, y si alguien necesita v3 probablemente ya lo sabe
1 comentarios
Opiniones en Hacker News
Decir que no hay detalles sobre UUID v2 solo aplica si leíste únicamente el RFC, famoso por ser poco claro: https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#t...
Casi nunca te lo vas a topar, pero también existe un UUID version 0. Vale la pena mencionarlo porque es el origen de los bits reservados que luego permitieron definir otras “versiones” de manera compatible. Dejé recopilada la investigación relacionada en mi biblioteca de UUID: https://github.com/okeeblow/DistorteD/blob/NEW%E2%80%85SENSA...
Decidí darle soporte porque está genial, pero todavía tengo que decidir cómo manejar el rollover de fechas y los UID Apollo más antiguos
Estoy empezando a trabajar en un RFC informativo sobre los tipos históricos de UUID definidos en el espacio Variant 0-7, que ayude a la gente a entenderlos. Si quieres participar en la discusión o revisar la redacción, puedes ver https://github.com/yocto/draft-yocto-uuid
Pude encontrar los detalles en 2 minutos. Haces clic en el enlace del artículo para ir a la sección de definición de DCE en el RFC 9562, entras a la especificación desde el primer enlace de ese párrafo y luego buscas “UUID” para llegar al Apéndice A, donde está todo
El nombre, de forma confusa, es “Universal Unique Identifier”, pero contiene todo lo necesario. Estaría bien que al menos hiciera clic en los enlaces que puso en su propio artículo
Por el contexto, como se explica que otras versiones se generan a partir de ciertos elementos, esa oración claramente se refiere a lo segundo. La frase es algo ambigua, pero no diría que induce al error
Aun así, el apéndice fue entretenido de leer, como una instantánea de la época
Estaría bueno que existiera un estándar de UUID corto como
73WakrfVbNJBaAmhQtEeDvobK7nP9xMEn sentido estricto no sería un UUID, porque podría duplicarse en algún lugar, pero quiero una combinación estándar de ID aleatorios que sean lo bastante cortos como para memorizarlos
Creo que no hay un estándar más popular porque hay que sacrificar algo. 128 bits tiene bajo riesgo de colisión para casi todos los usos, pero mientras más pequeño se vuelve, más hay que evaluar el contexto concreto y el impacto de una colisión, lo que dificulta estandarizarlo. Si usas otras codificaciones como base64 o base85 queda más corto, pero sacrificas cosas como distinción entre mayúsculas y minúsculas y seguridad en URLs: https://github.com/ulid/spec
Es solo otra representación del mismo UUID y se puede revertir. Al final, un UUID es un valor de 128 bits, así que no es tanto una conversión real sino una notación alternativa
Pierdes la ventaja de ordenamiento monótono que tienen algunas versiones de UUID, pero base58 es segura para URLs y no contiene caracteres especiales. El valor todavía se puede almacenar como binario. Por ejemplo, en Postgres puedes usar
byteaen lugar de una columna de textoLa discusión se puede ver aquí: https://github.com/uuid6/new-uuid-encoding-techniques-ietf-d...
El timestamp de UUID v7 fue un gran cambio para Databend. Lo usamos para encontrar rápidamente archivos de metadatos por timestamp en AWS S3, así que operaciones como vacuum se volvieron mucho más rápidas
PR: https://github.com/datafuselabs/databend/pull/16049
La gran ventaja de los UUID ordenados por tiempo es que mejoran la localidad. Al insertar nuevos elementos en un índice, por lo general terminas anexándolos al final, lo que puede ser más barato que inserciones aleatorias. Aunque también puede aumentar la contención, así que vale la pena considerar un híbrido que ponga algunos bits aleatorios antes del timestamp para crear “shards” ordenados. Además, las lecturas suelen concentrarse en los datos más recientes, así que es útil que esos datos estén juntos y se carguen bien en caché
Es difícil entender el propósito de uuid2. Ni siquiera sabía que existían más tipos como estos, y vi uuid2 por primera vez cuando le pedí a Xandr que borrara mi información personal: https://news.ycombinator.com/item?id=40913915
Incluso leyendo Wikipedia, no me queda claro por qué crear algo llamado “identificador único universal” y aun así tener varios tipos, y por qué algunos de ellos originalmente permitían rastrear hasta la PC. Me pregunto si mezclar parte del código MAC hace que uuid2 sea más cercano a lo aleatorio, o si hay otra razón. Desde el punto de vista de la privacidad, también me pregunto si no bastaría con usar identificadores largos con muchísimos caracteres posibles para que la probabilidad de colisión sea prácticamente nula.
Cualesquiera dos máquinas podían generar el mismo UID/UUID para las mismas dos entradas, y quien recibía el mensaje identificado podía revertir el identificador a sus componentes originales. Como se diseñó como etiqueta para mensajes transitorios, las dos dimensiones eran el tiempo y el ID de hardware; al principio se usaban números de serie de Apollo, y más tarde direcciones de hardware Ethernet, entre otras cosas.
Creo que gran parte de la confusión viene de que, en la implementación inicial de AEGIS, los ingenieros de Apollo empezaron a usar UID “canned”, es decir, estáticos y bien conocidos, para identificar elementos del sistema de archivos. Con el tiempo, el uso común de los UUID se desplazó por completo: de identificadores transitorios donde las colisiones estaban previstas, a identificadores canned donde había que evitarlas, y las dos dimensiones pasaron a ser aleatoriedad y más aleatoriedad.
La historia es más compleja. Microsoft contrató a una de las personas clave de Apollo para crear MSRPC para Windows NT, y de ahí también surgieron los GUID. Los GUID tienen una disposición de campos distinta a la de los UUID y, a diferencia de lo que dicen muchas fuentes, no son de endianidad mixta. Microsoft suele usar GUID canned no solo para identificar mensajes RPC transitorios, sino para casi cualquier cosa que necesite identificadores bien conocidos, como clases COM, códecs multimedia, etc. Ejemplo: https://gix.github.io/media-types/
Perdón por enlazar dos veces mi repositorio en el mismo hilo de comentarios, pero empecé a recopilar esta historia en el README de mi biblioteca de UUID y debería retomarlo. Apollo empezó en 1980 y el borrador del RFC de UUID de Leach/Salz recién apareció en 1998, así que hay muchísima historia que quedó fuera de los estándares modernos: https://github.com/okeeblow/DistorteD/blob/NEW%E2%80%85SENSA...
UUID v4 no es más que un generador de bytes aleatorios con guiones en posiciones determinadas. No hace falta usarlo; se puede ahorrar espacio generando bytes aleatorios directamente.
También se reducen cosas innecesarias como los guiones y la información de versión.
Es parecido a una dirección IPv4, que es un número de 32 bits, donde la notación de “cuatro grupos separados por puntos” es una de sus representaciones. Si piensas en un UUID como un formato de cadena, ya tienes mal entendido el concepto más básico de UUID. Incluso si solo quieres un identificador aleatorio, me parece elegante que un UUID aleatorio tenga unos pequeños bits de bandera que indiquen “esto fue pensado como aleatorio”. Es útil cuando encuentras un identificador aislado y sin contexto.
Se puede debatir si es útil crear espacios de nombres distintos entre los diferentes métodos de generación, pero la probabilidad de que un generador aleatorio común produzca un UUIDv4 válido es solo de 1/16. Claro que, si quieres hacer tu propio generador de UUID, configurar correctamente los bits es algo trivial.
En Go basta con
uuid.New().String(), pero leer datos aleatorios concrypto/randy convertirlos a base64 o hex requiere más líneas y más esfuerzo.Recomiendo no usar las versiones basadas en MAC. En teoría eso podría aplicar a todas salvo v4 y v7, pero v1 es la peor.
v3 también tiene el problema de que MD5 está gravemente roto.
No conocía los detalles fuera de la versión 4, pero lo que de verdad parece faltar y sería útil es un método que use datos SHA256 y un contador, algo parecido a PBKDF2.
Podría servir como identificador derivado que preserve la privacidad, y también permitiría demostrar de forma laxa que un UUID determinado se derivó de cierta semilla.
Más allá de eso, probablemente vas a querer una salida más larga.
Simplemente usa v7.
Ahora es el turno de que los expertos en seguridad digan que no.
Para muchos usos sería muy útil poder volver a procesar los datos y generar el mismo ID, pero no conozco una forma estándar de lograrlo.