سؤال

ما مدى أمان استخدام UIID لتحديد شيء فريد (أنا أستخدمه للملفات التي تم تحميلها إلى الخادم)؟ كما أفهمها، إنها تعتمد على أرقام عشوائية. ومع ذلك، يبدو لي أنه بالنظر إلى الوقت الكافي، فإنه سيكرر نفسه في نهاية المطاف، فقط من خلال فرصة نقية. هل يوجد نظام أفضل أو نمط من نوع ما لتخفيف هذه المشكلة؟

هل كانت مفيدة؟

المحلول

امن جدا:

تشير التقديرات إلى أن الخطر السنوي لشخص معين يجري ضربه نيزك فرصة واحدة في 17 مليار دولار، مما يعني أن الاحتمال يبلغ حوالي 0.00000000006 (6 × 10−11)، أي ما يعادل احتمالات إنشاء بضع عشرات من تريليونات من Uuids في عام ولديها مكررة واحدة. وبعبارة أخرى، فقط بعد توليد مليار يويدز كل ثانية في المائة سنة القادمة، فإن احتمال إنشاء مكرر واحد فقط سيكون حوالي 50٪.

مذكرة قانونية:

ومع ذلك، فإن هذه الاحتمالات تعقد فقط عند إنشاء Uuids باستخدام انتروبيا كافية. خلاف ذلك، يمكن أن يكون احتمال التكرارات أعلى بكثير، لأن التشتت الإحصائي قد يكون أقل. عندما تكون المعرفات الفريدة مطلوبة للتطبيقات الموزعة، بحيث لا تصطدم UUIDS حتى عندما يتم دمج البيانات من العديد من الأجهزة، يجب أن تكون عشوائية البذور والمولدات المستخدمة في كل جهاز موثوقين بحياة التطبيق. حيثما غير ممكن، توصي RFC4122 باستخدام متغير مساحة الاسم بدلا من ذلك.

المصدر: احتمال uuid عشوائي للتكرارات الجزء من مقال ويكيبيديا حول معرفات فريدة عالميا (يرتبط الرابط إلى مراجعة من ديسمبر 2016 قبل التحرير إعادة صياغة القسم).

انظر أيضا القسم الحالي حول نفس الموضوع على نفس مقالة المعرف الفريد عالميا، الاصطدامات.

نصائح أخرى

إذا كان ذلك عن طريق "إعطاء وقت كاف" تقصد 100 عام وأنت تخلقها بمعدل مليار ثانية، ثم نعم، لديك فرصة بنسبة 50٪ من الاصطدام بعد 100 عام.

هناك أكثر من نوع واحد من UUID، لذلك "كم هو آمن" يعتمد على أي نوع (الذي استدعاء المواصفات UUID "الإصدار") الذي تستخدمه.

  • الإصدار 1 هو الوقت المناسب بالإضافة إلى العنوان UUID. تحتوي 128 بت تحتوي على 48 بت لعنوان MAC لبطاقة الشبكة (التي تم تعيينها بشكل فريد من قبل الشركة المصنعة) وساعة 60 بت بدقة 100 نانو ثانية. تلك الساعة يلتف في 3603 م لذلك تكون هذه Uuids آمنة على الأقل حتى ذلك الحين (ما لم تكن بحاجة إلى أكثر من 10 ملايين شخص جديد في الثانية أو شخص ما باستخدام بطاقة الشبكة الخاصة بك). أقول "على الأقل" لأن الساعة تبدأ في 15 أكتوبر 1582، لذلك لديك حوالي 400 عام بعد أن يلتف على مدار الساعة من قبل أن يكون هناك إمكانية صغيرة من الازدواجية.

  • الإصدار 4 هو الرقم العشوائي uuid. هناك ست قطع ثابتة وبقية UUID هي 122 بت من العشوائية. يرى ويكيبيديا أو أي تحليل آخر يصف كيف غير مرجح للغاية.

  • يستخدم الإصدار 3 MD5 والإصدار 5 يستخدم Sha-1 لإنشاء تلك البتات 122، بدلا من مولد رقم عشوائي أو عشوائي عشوائي. لذلك من حيث السلامة، يشبه الإصدار 4 مشكلة إحصائية (طالما تتأكد من أن الخوارزمية Digest تتمثل دائما فريدة من نوعها).

  • يشبه الإصدار 2 الإصدار 1، ولكن مع وجود ساعة أصغر لذلك فهو سوف يتراجع في وقت أقرب وقت. ولكن نظرا لأن الإصدار 2 Uuids مخصصة ل DCE، يجب أن لا تستخدم هذه.

لذلك لجميع المشاكل العملية أنها آمنة. إذا كنت غير مرتاح من ترك الأمر إلى الاحتمالات (على سبيل المثال، فإن نوع الشخص الذي تشعر بالقلق إزاء تدمير الأرض من قبل كويكب كبير في حياتك)، فقط تأكد من استخدام الإصدار 1 Uuid ويضمن أن تكون فريدة من نوعها ( في حياتك، ما لم تكن تخطط للعيش 3603 آخر).

فلماذا لا يستخدم الجميع بسهولة الإصدار 1 Uuids؟ وذلك لأن الإصدار 1 Uuids تكشف عن عنوان MAC للماكينة، ويمكن أن تكون يمكن التنبؤ بها - شيئان قد يكون له آثار أمنية على التطبيق باستخدام تلك Uuids.

قد تعتمد الإجابة على هذا إلى حد كبير على الإصدار UUID.

يستخدم العديد من مولدات UUID رقما عشوائيا الإصدار 4. ومع ذلك، العديد من هذه الاستخدامات Pseudo مولد رقم عشوائي لتوليدها.

إذا تم استخدام PRNG المصنفة بشكل سيئ مع فترة صغيرة لتوليد UUID أود أن أقول إنها ليست آمنة للغاية على الإطلاق.

لذلك، فهي آمنة فقط مثل الخوارزميات المستخدمة لتوليدها.

على الجانب الآخر، إذا كنت تعرف الإجابة على هذه الأسئلة، فما أعتقد أن الإصدار 4 Uuid يجب أن يكون آمنا جدا للاستخدام. في الواقع، أنا أستخدمه لتحديد كتل على نظام ملفات كتلة الشبكة وحتى الآن لم يكن لديه اشتباك.

في حالتي، فإن PRNG أستخدمه هو الإعصار Mersenne وأنا حريص على الطريقة التي يتم بها المصور من مصادر متعددة بما في ذلك / DEV / Urandom. لدى Mersenne Twister فترة 2 ^ 19937 - 1. ستكون فترة طويلة جدا قبل أن أرى تكرار UUID.

نقلا عن ذلك ويكيبيديا:

وبالتالي، يمكن لأي شخص إنشاء UUID واستخدامه لتحديد شيء بثقة معقولة أن المعرف لا يستخدم أبدا عن غير قصد من قبل أي شخص لأي شيء آخر

استمر في توضيح تفصيل جيد للغاية حول مدى جودة آمنة في الواقع. حتى الإجابة على سؤالك: نعم، إنها آمنة بما فيه الكفاية.

تستخدم المخططات UIID عموما ليس فقط عنصر عشوائي زائف، ولكن أيضا وقت النظام الحالي، ونوعي من معرف الأجهزة الفريد في كثير من الأحيان إذا كان ذلك متاحا، مثل عنوان شبكة MAC.

الهدف بأكمله من استخدام UUID هو أنك تثق به للقيام بعمل أفضل لتوفير معرف فريد مما ستتمكن من القيام به. هذا هو نفس الأساس المنطقي وراء استخدام مكتبة تشفير الطرف الثالث بدلا من التدحرج الخاصة بك. قد تكون تفعل ذلك بنفسك أكثر متعة، لكنها عادة ما تكون مسؤولة عن القيام بذلك.

تم القيام به لسنوات. لا تدير مشكلة.

عادة ما قمت بإعداد DB الخاص بي للحصول على جدول واحد يحتوي على جميع المفاتيح والتواريخ المعدلة ومثل هذا. لم تنفذ في مشكلة مفاتيح مكررة على الإطلاق.

العيب الوحيد الذي لديه هو عندما تكتب بعض الاستفسارات للعثور على بعض المعلومات بسرعة أنك تقوم بالكثير من نسخ ولصق المفاتيح. ليس لديك سهلة من السهل تذكر المعرفات بعد الآن.

إليك مقتطف اختبار لك لاختباره لا يناسكه. مستوحاة من تعليق @ Scalabl3

شيء مضحك هو، هل يمكن أن تولد 2 على التوالي كانت متطابقة، بالطبع بمستويات العقل من الصدفة والحظ والتدخل الإلهي، ولكن على الرغم من الاحتمالات غير المهتملة، فلا يزال ممكنا! : د نعم، لن يحدث ذلك. فقط قول لتسلية التفكير في تلك اللحظة عندما أنشأت مكررة! لقطة شاشة فيديو! - Scalabl3 أكتوبر 20 '15 في 19:11

إذا كنت تشعر أنك محظوظ، تحقق من مربع الاختيار، فهذا فقط يتحقق من المعرف الذي تم إنشاؤه حاليا. إذا كنت ترغب في التحقق من تاريخ، اترك الأمر غير محدود. يرجى ملاحظة، قد تنفد من ذاكرة الوصول العشوائي في مرحلة ما إذا تركتها دون التحقق. حاولت أن أجعلها وحدة المعالجة المركزية ودية حتى تتمكن من إحباطها بسرعة عند الحاجة، فقط اضغط على زر Snippet Run مرة أخرى أو اترك الصفحة.

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/>

أنا أتفق مع الإجابات الأخرى. Uuids آمنة بما فيه الكفاية لجميع الأغراض العملية تقريبا1, وبالتأكيد لك.

ولكن لنفترض (افترض) أنها ليست كذلك.

هل يوجد نظام أفضل أو نمط من نوع ما لتخفيف هذه المشكلة؟

فيما يلي بضع نهج:

  1. استخدام UUID أكبر. على سبيل المثال، بدلا من أجزاء عشوائية 128، استخدم 256 أو 512 أو ... كل بت تضيفها إلى A TYPE-4 Style Uuid سيقلل من احتمال تصادم بنصف، على افتراض أن لديك مصدر موثوق للتروب فيه2.

  2. قم ببناء خدمة مركزية أو موزعة تقوم بإنشاء UUIDs وتسجيلها كل واحد تم إصداره على الإطلاق. في كل مرة يقوم فيها بإنشاء واحدة جديدة، فهو يتحقق من أن Uuid لم يصدر من قبل. ستكون هذه الخدمة مستقيمة من الناحية الفنية للتنفيذ (على ما أفكر) إذا افترضنا أن الأشخاص الذين يديرون الخدمة كانت جديرة بالثقة، غير قابلة للتنفيذ، إلكترونيتا. لسوء الحظ، ليسوا ... خاصة عندما يكون هناك إمكانية تداخل الحكومات. لذلك، هذا النهج ربما غير عملي، وقد يكون3 مستحيل في العالم الحقيقي.


1 - إذا قررت تفرد Uuids ما إذا كانت الصواريخ النووية تم إطلاقها في عاصمة بلادك، فإن الكثير من زملائك مواطنين لن يكونوا مقتنعين ب "الاحتمال منخفض للغاية". ومن هنا مؤهل "كل شيء تقريبا".

2 - وهنا سؤال فلسفي بالنسبة لك. هل أي شيء عشوائي حقا؟ كيف نعرف ما إذا كان الأمر كذلك هو الكون كما نعرفها محاكاة؟ هل هناك إله قد يصور "قرص" قوانين الفيزياء لتغيير النتيجة؟

3 - إذا كان أي شخص يعرف بأي أوراق بحثية في هذه المشكلة، فيرجى التعليق.

لا أعرف إذا كان هذا يهم لك، ولكن ضع في اعتبارك ذلك GUIDs فريدة من نوعها عالميا، لكن السلاحيات من Guids ليست كذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top