Générateur d’UUID

Générez des UUID — v4 aléatoires ou v7 ordonnés dans le temps — à l’unité ou par lots.

Version

122 bits aléatoires. Ne révèle rien sur sa date de création.

Combien

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 librairie

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.

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.