Générateur d’UUID
Générez des UUID à l’unité ou par cinquante : v4 aléatoires, ou v7 ordonnés dans le temps, dont l’horodatage en fait de meilleures clés de base de données.
122 bits aléatoires. Ne révèle rien sur sa date de création.
Génération…
Ce qu’est un UUID et pourquoi il existe
Un UUID — Universally Unique Identifier, appelé GUID dans la documentation Microsoft — est une valeur de 128 bits écrite sous forme de 32 chiffres hexadécimaux dans le regroupement familier 8-4-4-4-12. Sa raison d’être est de permettre à des systèmes distincts de frapper des identifiants de façon indépendante, sans la moindre coordination, tout en étant sûrs que les résultats n’entreront pas en collision. C’est ce qui le distingue d’une colonne auto-incrémentée : deux serveurs, deux clients mobiles hors ligne dans un avion et une tâche de fond peuvent tous créer des enregistrements au même instant sans demander la permission à personne.
L’unicité est ici probabiliste et non garantie. La version 4 laisse 122 bits à l’aléa, un espace assez vaste pour que, même après avoir généré des milliards de valeurs, la probabilité d’une répétition reste très en deçà de celle qu’un disque corrompe silencieusement les données. En pratique, vous pouvez la considérer comme unique ; les mathématiques ne sont pas le maillon faible.
Version 4 contre version 7 — le choix qui compte
La version 4 est aléatoire de bout en bout. Elle ne transporte aucune information : ni la date de création, ni l’auteur, ni l’ordre. C’est soit sa plus grande force, soit son défaut central, selon l’endroit où vous la placez.
La version 7, normalisée par le RFC 9562 en 2024, remplace les 48 premiers bits par un horodatage Unix en millisecondes et remplit le reste d’aléa. Comme le temps vient en premier et que la valeur se lit de gauche à droite, trier des identifiants v7 comme du texte brut revient aussi à les trier chronologiquement.
La différence n’est pas cosmétique. Les bases de données conservent les clés primaires dans un index B-tree trié. Insérez des clés v7 et chaque nouvelle ligne atterrit au bord droit de l’arbre, à côté de la précédente : les pages que vous écrivez restent en mémoire et l’index grandit proprement. Insérez des clés v4 et chaque écriture tombe à une position aléatoire ; la base touche une page différente à chaque fois, le taux de succès du cache chute et l’index se fragmente. Sur une table volumineuse et sollicitée, l’écart de débit en insertion est considérable — d’où l’adoption si rapide de v7 pour les clés primaires.
- Choisissez v7 pour les clés primaires, les identifiants d’événements et de journaux, et tout ce que vous voudrez trier ou interroger par plage de dates de création.
- Choisissez v4 quand l’identifiant apparaît dans un contexte non fiable et ne doit rien laisser filtrer — y compris le fait qu’un enregistrement a été créé juste avant un autre.
- L’une ou l’autre convient pour un identifiant de corrélation, une clé d’idempotence ou un nom de fichier, où l’ordre n’a pas d’importance.
La contrepartie, c’est précisément cette fuite : un identifiant v7 indique à quiconque le voit, à la milliseconde près, quand il a été créé. Pour l’ID d’une ligne, c’est généralement anodin et souvent utile. Pour un jeton de réinitialisation de mot de passe ou un lien de partage public, c’est une information que vous n’aviez pas l’intention de publier — et ceux-là ne devraient pas être des UUID du tout, mais des jetons aléatoires issus d’un générateur de secrets dédié.
L’ordre au sein d’une même milliseconde
Une subtilité qui piège beaucoup d’implémentations de v7 : le matériel moderne génère bien plus d’un identifiant par milliseconde. Si deux valeurs partagent un horodatage, leur ordre est décidé par les bits aléatoires qui suivent — autrement dit, au hasard. Générez-en cinquante dans une boucle serrée et vous obtenez cinquante valeurs seulement approximativement ordonnées, perdant exactement la propriété pour laquelle vous aviez choisi v7.
Le RFC 9562 y répond par un compteur monotone, et cet outil l’implémente : les 12 bits qui suivent immédiatement l’horodatage s’incrémentent au sein d’une milliseconde, si bien qu’un lot est strictement croissant et non approximativement. Si le compteur se remplit — plus de 4096 valeurs dans la même milliseconde — le générateur emprunte la milliseconde suivante plutôt que de boucler et d’émettre une valeur qui se trierait avant sa devancière. Il traite de la même façon un recul de l’horloge, ce qui arrive lors des corrections NTP.
En lisant une valeur v7 de gauche à droite, avec 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b pour exemple :
- 0190a1b2-c3d4 — l’horodatage Unix sur 48 bits en millisecondes. Comme il vient en premier, l’ordre du texte est l’ordre du temps.
- 7 — le chiffre de version, qui fait de cette valeur un v7 et non un v4.
- e5f — le compteur monotone sur 12 bits, qui s’incrémente au sein d’une même milliseconde.
- 8 — les bits de variante, fixés par le RFC 9562 pour tout UUID moderne (toujours 8, 9, a ou b).
- a9b-0c1d2e3f4a5b — les 62 bits restants, purement aléatoires.
Stocker et utiliser des UUID
La forme canonique est en minuscules avec tirets, et le RFC 9562 demande aux générateurs d’émettre exactement cela — raison pour laquelle cet outil ne propose aucune option de mise en forme. Vous rencontrerez néanmoins d’autres graphies : en majuscules et entre accolades dans l’outillage Microsoft, et sans tirets là où quelqu’un a voulu une colonne plus courte. Ce sont les mêmes 128 bits, et les comparaisons devraient ignorer la casse.
C’est au stockage que cela compte vraiment. Un UUID fait 16 octets, mais sa forme texte en fait 36 : le stocker en chaîne double donc largement l’espace occupé dans la ligne et, plus important encore, dans chaque index qui l’inclut. Utilisez un type natif là où il en existe un :
uuid -- PostgreSQL : type natif de 16 octets BINARY(16) -- MySQL : compact ; CHAR(36) gaspille 20 octets/ligne uniqueidentifier -- SQL Server crypto.randomUUID() // JavaScript : v4 seulement, contexte sécurisé requis uuid.uuid4() / uuid7() # Python : v4 dans la bibliothèque standard ; v7 via une bibliothèque
Une dernière mise en garde : un UUID identifie, il n’autorise pas. Parce qu’ils sont indevinables, il est tentant de considérer comme privée une URL non listée qui en contient un. Mais les identifiants fuient — par les journaux, l’historique du navigateur, les en-têtes referrer et les captures d’écran — donc tout ce qui a réellement besoin d’être protégé requiert toujours une vraie vérification des droits derrière.
Comment savoir si un UUID est un v4 ou un v7
On vous remet le plus souvent un identifiant sans la moindre note indiquant d’où il vient, et vous n’en avez pas besoin : la version est écrite dans la valeur elle-même. Les deux font 32 chiffres hexadécimaux dans le même groupement 8-4-4-4-12, la différence n’est donc pas dans la forme — elle tient à deux chiffres isolés à des positions fixes, et tout le reste en découle.
- Le premier chiffre du troisième groupe est le chiffre de version. Un 4 à cet endroit signifie version 4, un 7 signifie version 7, et aucune autre partie de la valeur n’a son mot à dire.
- Le premier chiffre du quatrième groupe porte les bits de variante et vaut 8, 9, a ou b dans les deux versions : il ne vous dira donc jamais laquelle vous tenez. Ce qu’il vous dit, c’est que la valeur suit bien le RFC 9562 ; toute autre chose à cette position est une disposition plus ancienne, ou n’est pas un UUID.
- Si le chiffre de version est un 7, les douze premiers chiffres sont l’heure de création : un compte sur 48 bits de millisecondes depuis le début de 1970, écrit en hexadécimal.
- Si c’est un 4, il n’y a rien de plus à lire. Un v4 n’encode ni heure, ni machine, ni ordre — précisément la propriété pour laquelle vous l’avez choisi.
Prenez la valeur que décompose la section ci-dessus, 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b. Son troisième groupe s’ouvre sur un 7 : c’est donc une version 7, et ses douze premiers chiffres sont 0190a1b2c3d4 — convertissez ce nombre hexadécimal en décimal, confiez-le au Convertisseur d’horodatage Unix, et vous obtenez un après-midi de juillet 2024. À côté, 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d ouvre son troisième groupe sur un 4, et ses propres douze premiers chiffres sont des données aléatoires qui ne décodent rien. Les deux ne s’accordent que sur un point : tous deux ouvrent leur quatrième groupe sur l’un des quatre chiffres qu’autorisent les bits de variante.
Le v7 résiste-t-il aux collisions autant que le v4 ?
La question est légitime, car le v7 contient réellement moins d’aléa. La version 4 consacre 122 de ses 128 bits à des données aléatoires. La version 7 en consacre 48 à l’horodatage et, ici, 12 de plus au compteur monotone, ce qui laisse 62 bits aléatoires — un peu plus de la moitié. Lu comme un chiffre nu, cela ressemble à un net recul.
- Au sein d’un même lot issu de cet outil, une répétition n’est pas improbable : elle est impossible. Les valeurs qui partagent une milliseconde reçoivent des valeurs de compteur différentes, et celles qui n’en partagent pas portent des horodatages différents ; il ne peut donc pas y en avoir deux identiques. C’est de l’arithmétique, pas de la probabilité.
- Entre deux machines qui génèrent au même instant, les chances relèvent au pire du problème des anniversaires sur 62 bits, qui s’équilibre à peu près à la racine carrée de l’espace : de l’ordre de deux milliards de valeurs, et toutes dans une seule et même milliseconde.
- Entre deux millisecondes différentes, une collision de v7 n’est pas seulement improbable : elle est impossible, puisque les chiffres de tête eux-mêmes diffèrent.
La comparaison honnête n’est donc pas 122 bits contre 62. C’est une loterie tirée encore et encore pendant toute la vie du système, face à une loterie distincte et bien plus petite tenue à l’intérieur de chaque milliseconde et jetée quand la milliseconde s’achève. Le second dispositif est le plus solide, et la raison de préférer le v4 reste celle que donne la section de comparaison : non pas les collisions, mais le fait qu’un v7 annonce tout haut quand il a été créé.
Faire passer une table existante du v4 au v7
La question qui suit le choix du v7 est de savoir quoi faire des lignes déjà présentes dans la table, et le rassurant est que la colonne, elle, n’a rien à changer. Les deux versions sont les mêmes 128 bits sous la même forme texte de 36 caractères : une colonne uuid de PostgreSQL, un BINARY(16) ou un CHAR(36) accueillent un mélange sans s’en apercevoir. Vous commencez à générer du v7 pour les nouvelles lignes et vous vous arrêtez là ; il n’y a ni étape de migration ni reprise de l’existant.
- Ce que vous obtenez tout de suite : toute ligne insérée à partir de maintenant porte un horodatage en tête, si bien que les nouvelles clés atterrissent côte à côte à une extrémité de l’index au lieu de s’éparpiller dessus. Ce gain concerne l’endroit où vont les nouvelles écritures, et il est là dès la première insertion.
- Ce qui n’arrivera jamais : les lignes déjà présentes resteront à jamais sans ordre. Rien ne peut déposer une heure de création dans une valeur qui n’en a jamais reçu, et réémettre chaque identifiant reviendrait à réécrire chaque clé étrangère qui pointe vers lui — un travail bien plus lourd qu’un changement de générateur, et qui vaut rarement la peine pour le seul index.
- Ce à quoi il faut faire attention : trier la colonne cesse de vouloir dire une seule chose. Un compte de millisecondes est un petit nombre pour un champ de 48 bits ; les clés v7 se rassemblent donc en une bande étroite dans le bas de la plage, tandis que les clés v4 sont réparties sur toute son étendue, l’une d’elles tombant de temps à autre au milieu.
C’est ce dernier point qui mord : une requête qui trie sur la clé paraît juste sur les données récentes et rend silencieusement compte des anciennes de travers. S’il vous faut un ordre unique sur toute la table, ajoutez une colonne d’heure de création et triez dessus, et laissez l’identifiant redevenir un identifiant. Le mélange reste au moins lisible pendant ce temps : le chiffre de version figure dans chaque valeur, et une requête peut donc distinguer les deux époques sans seconde colonne lorsqu’il le faut.
Questions fréquentes
- Faut-il utiliser v4 ou v7 ?
- Utilisez v7 pour les clés primaires et tout ce que vous trierez par date de création : l’horodatage de tête garde les insertions groupées en fin d’index au lieu de les disperser. Utilisez v4 quand l’identifiant ne doit absolument rien révéler, pas même sa date de création.
- Deux UUID peuvent-ils être identiques ?
- C’est possible mais extraordinairement improbable. La version 4 compte 122 bits aléatoires : même après des milliards de valeurs générées, la probabilité d’une collision reste très inférieure à celle que le stockage les corrompe silencieusement.
- Que sont devenues les versions 1, 3 et 5 ?
- La version 1 encode un horodatage et l’adresse MAC de la machine, ce qui divulgue l’identité matérielle et ne peut de toute façon pas être produit dans un navigateur. Les versions 3 et 5 dérivent un UUID de façon déterministe à partir d’un espace de noms et d’un nom, via MD5 ou SHA-1 — utile quand une même entrée doit toujours donner le même identifiant, mais c’est un autre travail que d’en générer un nouveau.
- Un UUID est-il assez sûr pour servir de jeton secret ?
- Un UUID v4 est indevinable, mais un v7 encode ouvertement son heure de création, et ni l’un ni l’autre n’est conçu comme un identifiant d’authentification. Pour les réinitialisations de mot de passe, les jetons de session ou les liens de partage, générez un secret aléatoire dédié et vérifiez les droits côté serveur plutôt que de compter sur la difficulté à deviner l’identifiant.
- Pourquoi mon lot de v7 n’est-il pas parfaitement trié dans d’autres outils ?
- Parce que beaucoup d’implémentations font l’impasse sur le compteur monotone. Quand plusieurs valeurs partagent une milliseconde, leur ordre revient aux bits aléatoires qui suivent. Cet outil implémente le compteur du RFC 9562 : un lot généré ici est strictement croissant.
- Comment stocker un UUID en base de données ?
- Dans un type natif de 16 octets là où il en existe un — uuid en PostgreSQL, uniqueidentifier en SQL Server, BINARY(16) en MySQL. Stocker à la place la forme texte de 36 caractères double largement l’espace occupé dans la ligne et dans chaque index contenant la colonne.
- Sont-ils générés sur vos serveurs ?
- Non. Ils sont générés dans votre navigateur avec crypto.getRandomValues, la source cryptographique d’aléa de la plateforme — celle qu’utilise crypto.randomUUID. Aucune valeur n’est envoyée où que ce soit, et recharger la page produit un jeu entièrement nouveau.
- Peut-on savoir quand un UUID v7 a été créé ?
- Oui, et la valeur suffit. Ses douze premiers chiffres hexadécimaux sont un compte de millisecondes depuis le début de 1970 : convertissez-les en décimal et confiez le résultat au Convertisseur d’horodatage Unix. Un v4 n’a pas ce champ ; les mêmes douze chiffres y sont aléatoires et ne décodent rien.
- Le v7 a-t-il moins de bits aléatoires que le v4 ?
- Oui — 62 ici contre les 122 du v4, parce que l’horodatage et le compteur prennent la place. Cela ne rend pas une collision plus probable en pratique : deux valeurs v7 ne peuvent se heurter que si elles ont été créées dans la même milliseconde, ces 62 bits sont donc dépensés à l’intérieur d’une milliseconde et non sur toute la vie du système ; et au sein d’un même lot issu de cet outil, le compteur rend une répétition impossible plutôt que simplement improbable.
- Des UUID v4 et v7 peuvent-ils cohabiter dans la même colonne ?
- Oui. Ce sont les mêmes 128 bits sous la même forme texte : rien ne change dans le schéma et il n’y a pas de migration — vous générez du v7 à partir de maintenant et vous laissez les anciennes lignes tranquilles. La seule chose à surveiller est le tri : les nouvelles lignes sont entre elles dans l’ordre de création, mais les anciennes, aléatoires, sont dispersées autour, si bien que trier sur la clé ne donne pas un ordre chronologique pour la table entière.
- Que sont les versions 6 et 8 des UUID ?
- Le RFC 9562 les définit toutes deux à côté du v7. La version 6 est la version 1 dont les champs d’horodatage ont été réordonnés pour que la valeur se trie chronologiquement ; elle vise les systèmes déjà engagés sur le v1 — le RFC dit que tout le reste devrait prendre le v7. La version 8 est un emplacement volontairement ouvert pour des dispositions maison, où seuls les bits de version et de variante sont fixés et où les 122 restants vous appartiennent. Cet outil ne génère ni l’une ni l’autre.
Outils connexes
- Générateur de jetons
Générez des clés, des secrets et des phrases de passe sûrs.
- Générateur de données factices
Des données de test avec graine, dont les clés de contrôle et les IBAN sont justes.
- Générateur de QR codes
Chaque décision d’encodage est visible : mode, version, niveau, masque.