Quel est le caractère unique de UUID?

dans quelle mesure est-il sûr D'utiliser UUID pour identifier quelque chose de manière unique (je l'utilise pour les fichiers téléchargés sur le serveur)? Si je comprends bien, il est basé sur des nombres aléatoires. Cependant, il me semble qu'avec assez de temps, il finirait par se répéter, par pur hasard. Est-il un meilleur système ou un modèle type pour pallier ce problème?

323
demandé sur Jason 2009-07-20 22:06:40

10 réponses

très sûr:

le risque annuel qu'une personne donnée soit frappée par une météorite est estimé à une chance sur 17 milliards, ce qui signifie la probabilité est d'environ 0.00000000006 (6 × 10 -11 ), équivalent à la cote de créer quelques dizaines de trillions D'UUIDs par an et d'en avoir un dupliquer. En d'autres termes, seulement après avoir généré 1 milliard de tous les Uuid deuxième pour les 100 prochaines années, la probabilité de créer juste un double serait d'environ 50%.

avertissement:

cependant, ces probabilités ne tiennent que lorsque les UUIDs sont générés en utilisant une entropie suffisante. Sinon, la probabilité de doublons la dispersion statistique pourrait être nettement plus élevée, être inférieur. Lorsque des identificateurs uniques sont requis pour les applications, de sorte que les UUIDs ne se heurtent pas, même lorsque les données de nombreux les périphériques sont fusionnés, le caractère aléatoire des semences et des générateurs utilisés chaque dispositif doit être fiable pour la durée de vie de l'application. Où ceci n'est pas faisable, RFC4122 recommande l'utilisation d'une variante d'espace de noms plutôt.

Source: la probabilité UUID aléatoire de doublons section de L'article de Wikipedia sur les identificateurs universellement uniques (le lien mène à une révision à partir de décembre 2016 avant d'éditer retravaillé la section).

Voir aussi la section actuelle sur le même sujet dans le même article identifiant universellement unique, Collisions .

315
répondu Martijn Pieters 2018-09-06 12:15:59

si par" assez de temps " vous voulez dire 100 ans et que vous les créez à un taux d'un milliard par seconde, alors oui, vous avez 50% de chance d'avoir une collision après 100 ans.

124
répondu rein 2009-07-20 18:14:13

il y a plus d'un type D'UUID, donc" comment sûr "dépend du type (que les spécifications D'UUID appellent" version") que vous utilisez.

  • la Version 1 est l'adresse UUID plus MAC basée sur le temps. Les 128 bits contiennent 48 bits pour l'adresse MAC de la carte réseau (qui est attribuée de manière unique par le fabricant) et une horloge de 60 bits avec une résolution de 100 nanosecondes. Cette horloge wraps en 3603 A. D. ainsi ces UUIDs sont sûr au moins jusqu'à ce moment-là (sauf si vous avez besoin de plus de 10 millions de nouveaux UUIDs par seconde ou quelqu'un clone votre carte réseau). Je dis "au moins" parce que l'horloge commence à 15 octobre 1582, donc vous avez environ 400 ans après les enveloppements de l'horloge avant qu'il n'y ait même une petite possibilité de duplications.

  • Version 4 est le nombre aléatoire UUID. Il y a six bits fixes et le reste de L'UUID est de 122 bits aléatoires. Voir Wikipedia ou une autre analyse qui décrit à quel point un duplicata est très improbable.

  • la Version 3 utilise MD5 et la Version 5 utilise SHA-1 pour créer ces 122 bits, au lieu d'un générateur de nombres aléatoires ou pseudo-aléatoires. Donc en termes de sécurité, C'est comme si la Version 4 était un problème statistique (tant que vous vous assurez que ce que l'algorithme de digest traite est toujours unique).

  • Version 2 est similaire à la Version 1, mais avec un horloge plus petite donc il va envelopper beaucoup plus tôt. Mais puisque les UUID Version 2 sont pour DCE, vous ne devriez pas les utiliser.

donc pour tous les problèmes pratiques ils sont sûrs. Si vous n'êtes pas à l'aise de le laisser aux probabilités (par exemple, vous êtes le type de personne inquiète de la terre se détruire par un grand astéroïde dans votre vie), assurez-vous juste que vous utilisez une version 1 UUID et il est garanti d'être unique (dans votre vie, sauf si vous prévoyez de vivre après 3603 A. D.).

alors pourquoi tout le monde n'utilise-t-il pas simplement la Version 1 UUIDs? C'est parce que les UUIDs de la Version 1 révèlent l'adresse MAC de la machine sur laquelle ils ont été générés et ils peuvent être prévisibles -- deux choses qui pourraient avoir des implications de sécurité pour l'application utilisant ces UUIDs.

86
répondu Hoylen 2011-08-07 02:58:51

la réponse à cette question peut dépendre largement de la version UUID.

beaucoup de générateurs UUID utilisent un nombre aléatoire version 4. Cependant, beaucoup d'entre eux utilisent Pseudo Un générateur de nombres aléatoires pour les générer.

si un PRNG mal semé avec une petite période est utilisé pour générer L'UUID je dirais que ce n'est pas très sûr du tout.

par conséquent, il est seulement aussi sûr que les algorithmes utilisés pour le générer.

sur le de l'autre côté, si vous connaissez la réponse à ces questions, je pense qu'une version 4 uuid devrait être très sûre à utiliser. En fait, je l'utilise pour identifier les blocs sur un système de fichiers de bloc réseau et jusqu'à présent n'ont pas eu de conflit.

dans mon cas, le PRNG que j'utilise est un Mersenne twister et je fais attention à la façon dont il est semé qui est à partir de sources multiples y compris /dev/urandom. Mersenne twister a une période de 2^19937-1. Ça va prendre très longtemps avant que je voir une répétition uuid.

16
répondu Matt 2012-01-04 04:24:02

citation de Wikipedia :

ainsi, n'importe qui peut créer un UUID et utiliser pour identifier quelque chose avec confiance raisonnable que le identifiant ne sera jamais involontairement utilisé par quelqu'un pour rien d'autre

Il explique en très bon détail sur la façon dont il est réellement. Donc, pour répondre à votre question: Oui, c'est assez sûr.

14
répondu Dave Vogt 2009-07-20 18:10:51

les schémas UUID utilisent généralement non seulement un élément pseudo-aléatoire, mais aussi le temps système actuel, et une sorte d'identifiant matériel souvent unique si disponible, comme une adresse MAC réseau.

le but de L'utilisation de UUID est que vous lui faites confiance pour faire un meilleur travail de fournir une identification unique que vous-même serait en mesure de le faire. C'est la même logique derrière l'utilisation d'une bibliothèque de cryptographie de tierce partie plutôt que de rouler votre propre. Le faire soi-même peut être plus amusant., mais il est généralement moins responsable de le faire.

8
répondu Parappa 2009-07-20 18:53:46

le fait depuis des années. N'exécutez jamais un problème.

j'ai habituellement mis en place mes DB pour avoir une table qui contient toutes les clés et les dates modifiées et autres. Je n'ai jamais rencontré de problème de double des clés.

Le seul inconvénient qu'il a, c'est quand vous écrivez quelque requêtes pour trouver des informations rapidement vous faire beaucoup de copier et de coller des clés. Tu n'as plus la petite carte facile à mémoriser.

5
répondu Posthuma 2009-07-20 18:58:05

voici un extrait de test pour vous de tester son uniquenes. inspiré par le commentaire de @scalabl3

la chose drôle est, vous pourriez générer 2 dans une rangée qui étaient identiques, bien sûr à des niveaux époustouflants de coïncidence, chance et intervention divine, mais malgré les chances insondables, c'est encore possible! :D Oui, ça ne marchera pas. je dis juste pour le plaisir de penser à ce moment où tu as créé un double! Capture d'écran de la vidéo! - scalabl3 Oct 20 ' 15 à 19: 11

si vous vous sentez chanceux, cochez la case, elle ne vérifie que les id générés actuellement. Si vous souhaitez une vérification de l'histoire, laissez-la libre. S'il vous plaît noter, vous pourriez manquer de ram à un moment donné si vous le laissez non vérifié. J'ai essayé de le rendre compatible avec cpu pour que vous puissiez avorter rapidement si nécessaire, appuyez simplement sur le bouton run snippet ou quittez la page.

Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); }
  Math.trueRandom = (function() {
  var crypt = window.crypto || window.msCrypto;

  if (crypt && crypt.getRandomValues) {
      // if we have a crypto library, use it
      var random = function(min, max) {
          var rval = 0;
          var range = max - min;
          if (range < 2) {
              return min;
          }

          var bits_needed = Math.ceil(Math.log2(range));
          if (bits_needed > 53) {
            throw new Exception("We cannot generate numbers larger than 53 bits.");
          }
          var bytes_needed = Math.ceil(bits_needed / 8);
          var mask = Math.pow(2, bits_needed) - 1;
          // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111

          // Create byte array and fill with N random numbers
          var byteArray = new Uint8Array(bytes_needed);
          crypt.getRandomValues(byteArray);

          var p = (bytes_needed - 1) * 8;
          for(var i = 0; i < bytes_needed; i++ ) {
              rval += byteArray[i] * Math.pow(2, p);
              p -= 8;
          }

          // Use & to apply the mask and reduce the number of recursive lookups
          rval = rval & mask;

          if (rval >= range) {
              // Integer out of acceptable range
              return random(min, max);
          }
          // Return an integer that falls within the range
          return min + rval;
      }
      return function() {
          var r = random(0, 1000000000) / 1000000000;
          return r;
      };
  } else {
      // From http://baagoe.com/en/RandomMusings/javascript/
      // Johannes Baagøe <baagoe@baagoe.com>, 2010
      function Mash() {
          var n = 0xefc8249d;

          var mash = function(data) {
              data = data.toString();
              for (var i = 0; i < data.length; i++) {
                  n += data.charCodeAt(i);
                  var h = 0.02519603282416938 * n;
                  n = h >>> 0;
                  h -= n;
                  h *= n;
                  n = h >>> 0;
                  h -= n;
                  n += h * 0x100000000; // 2^32
              }
              return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
          };

          mash.version = 'Mash 0.9';
          return mash;
      }

      // From http://baagoe.com/en/RandomMusings/javascript/
      function Alea() {
          return (function(args) {
              // Johannes Baagøe <baagoe@baagoe.com>, 2010
              var s0 = 0;
              var s1 = 0;
              var s2 = 0;
              var c = 1;

              if (args.length == 0) {
                  args = [+new Date()];
              }
              var mash = Mash();
              s0 = mash(' ');
              s1 = mash(' ');
              s2 = mash(' ');

              for (var i = 0; i < args.length; i++) {
                  s0 -= mash(args[i]);
                  if (s0 < 0) {
                      s0 += 1;
                  }
                  s1 -= mash(args[i]);
                  if (s1 < 0) {
                      s1 += 1;
                  }
                  s2 -= mash(args[i]);
                  if (s2 < 0) {
                      s2 += 1;
                  }
              }
              mash = null;

              var random = function() {
                  var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
                  s0 = s1;
                  s1 = s2;
                  return s2 = t - (c = t | 0);
              };
              random.uint32 = function() {
                  return random() * 0x100000000; // 2^32
              };
              random.fract53 = function() {
                  return random() +
                      (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
              };
              random.version = 'Alea 0.9';
              random.args = args;
              return random;

          }(Array.prototype.slice.call(arguments)));
      };
      return Alea();
  }
}());

Math.guid = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)    {
      var r = Math.trueRandom() * 16 | 0,
          v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
  });
};
function logit(item1, item2) {
    console.log("Do "+item1+" and "+item2+" equal? "+(item1 == item2 ? "OMG! take a screenshot and you'll be epic on the world of cryptography, buy a lottery ticket now!":"No they do not. shame. no fame")+ ", runs: "+window.numberofRuns);
}
numberofRuns = 0;
function test() {
   window.numberofRuns++;
   var x = Math.guid();
   var y = Math.guid();
   var test = x == y || historyTest(x,y);

   logit(x,y);
   return test;

}
historyArr = [];
historyCount = 0;
function historyTest(item1, item2) {
    if(window.luckyDog) {
       return false;
    }
    for(var i = historyCount; i > -1; i--) {
        logit(item1,window.historyArr[i]);
        if(item1 == history[i]) {
            
            return true;
        }
        logit(item2,window.historyArr[i]);
        if(item2 == history[i]) {
            
            return true;
        }

    }
    window.historyArr.push(item1);
    window.historyArr.push(item2);
    window.historyCount+=2;
    return false;
}
luckyDog = false;
document.body.onload = function() {
document.getElementById('runit').onclick  = function() {
window.luckyDog = document.getElementById('lucky').checked;
var val = document.getElementById('input').value
if(val.trim() == '0') {
    var intervaltimer = window.setInterval(function() {
         var test = window.test();
         if(test) {
            window.clearInterval(intervaltimer);
         }
    },0);
}
else {
   var num = parseInt(val);
   if(num > 0) {
        var intervaltimer = window.setInterval(function() {
         var test = window.test();
         num--;
         if(num < 0 || test) {
    
         window.clearInterval(intervaltimer);
         }
    },0);
   }
}
};
};
Please input how often the calulation should run. set to 0 for forever. Check the checkbox if you feel lucky.<BR/>
<input type="text" value="0" id="input"><input type="checkbox" id="lucky"><button id="runit">Run</button><BR/>
4
répondu Tschallacka 2016-08-19 11:56:48

Je ne sais pas si cela vous importe, mais gardez à l'esprit que GUIDs sont globalement uniques, mais les substrats de GUIDs ne sont pas .

2
répondu Grant Wagner 2009-07-20 22:18:54

je suis d'accord avec les autres réponses. Uuid sont suffisamment sûrs pour presque toutes fins pratiques 1 , et certainement pour le vôtre.

mais supposons (hypothétiquement) qu'ils ne le soient pas.

Est-il un meilleur système ou un modèle type pour pallier ce problème?

voici quelques approches:

  1. utilisez un plus grand UUID. Par exemple, au lieu de 128 bits aléatoires, utilisez 256 ou 512 ou... Chaque bit que vous ajoutez à un UUID de type 4 réduira la probabilité d'une collision de moitié, en supposant que vous avez une source fiable d'entropie 2 .

  2. construisez un service centralisé ou distribué qui génère des UUID et enregistre chaque UUID émis. Chaque fois qu'il génère un nouveau, il vérifie que l'UUID n'a jamais été publié avant. Un tel service serait techniquement simple à mettre en œuvre (je pense) si nous avons supposé que les personnes dirigeant le service étaient absolument fiables, Incorruptibles, etc. Malheureusement, ils ne le sont pas ... surtout quand il y a la possibilité de gouvernements d'intervenir. Ainsi, cette approche est probablement impraticable, et peut être 3 impossible dans le monde réel.


1 - Si l'unicité des UUID déterminait si des missiles nucléaires ont été lancés sur la capitale de votre pays, beaucoup de vos concitoyens ne seraient pas convaincus par "la probabilité est extrêmement faible". D'où ma qualification de "presque tout".

2-et voici une question philosophique pour vous. Est jamais vraiment aléatoire? Comment savoir si elle ne l'était pas? C'est l'univers tel que nous le connaissons une simulation? Est-il un Dieu qui pourrait "ajuster" l' les lois de la physique pour modifier un résultat?

3 - Si quelqu'un sait de documents de recherche sur ce problème, s'il vous plaît commentaire.

1
répondu Stephen C 2018-09-06 13:07:27