3 puan yazan GN⁺ 2024-08-27 | 1 yorum | WhatsApp'ta paylaş
  • UUID'nin v1'den v8'e kadar 8 sürümü vardır; daha yüksek sayı daha yeni ya da daha iyi olduğu anlamına gelmez, yalnızca farklı üretim yöntemlerinin RFC 9562'de tanımlandığını gösterir
  • Yaygın seçenekler genellikle v4 ve v7'ye indirgenir; v4 rastgele ID'ler için varsayılan seçimdir, v7 ise oluşturulma zamanına göre sıralama gerektiğinde uygundur
  • v1 ve v6 aynı bileşenleri kullanır, ancak v6 alan sırasını değiştirerek sıralandığında oluşturulma zamanına göre dizilmesini sağlar
  • v3 ve v5, girdi verisini hash'leyerek UUID üretir; v3 MD5, v5 ise SHA-1 kullanır ve olası girdi değerleri arasında DNS ile URL bulunabilir
  • Mümkünse v1·v6 yerine v7 kullanmak, girdi verisine dayalı UUID gerekiyorsa v5'i, tamamen kullanıcı tanımlı UUID gerekiyorsa v8'i değerlendirmek pratik bir yaklaşımdır

UUID sürümlerine göre üretim yöntemleri

  • UUID sürümleri v1'den v8'e kadar uzanır ve hepsi RFC 9562'de tanımlanmıştır
  • Zaman tabanlı UUID'ler

    • UUID Version 1, timestamp, monoton sayaç ve MAC adresi kullanılarak üretilir
    • UUID Version 6, v1 ile aynı verileri kullanır ancak sıralandığında oluşturulma zamanına göre dizilmesi için düzeni değiştirir
    • UUID Version 7, timestamp ve rastgele verilerle üretilir
  • Rastgele·kullanıcı tanımlı UUID'ler

    • UUID Version 4, tamamen rastgele veriyle üretilir ve birçok kişinin UUID denince aklına gelen biçime en yakın sürümdür
    • UUID Version 8, tüm sürümlerde zorunlu olan version/variant alanları dışında tamamen kullanıcı tanımlıdır
  • Girdi verisinin hash'ine dayalı UUID'ler

    • UUID Version 3, kullanıcının sağladığı verinin MD5 hash'i ile üretilir
      • RFC'deki olası girdi değerleri arasında DNS ve URL vardır
    • UUID Version 5, kullanıcının sağladığı verinin SHA-1 hash'i ile üretilir
      • v3'te olduğu gibi DNS ve URL girdi adayı olabilir
  • Ayrılmış UUID'ler

    • UUID Version 2, güvenlik kimlikleri için ayrılmıştır ve bilinen bir ayrıntısı yoktur

Gerçek seçim ölçütleri

  • Çoğu durumda seçenek v4 veya v7'dir
  • Yalnızca rastgele bir ID gerekiyorsa v4 uygun varsayılan seçimdir
  • ID'nin sıralanabilir olması gerekiyorsa v7 düşünülebilir
    • Örneğin UUID bir veritabanı anahtarı olarak kullanılacaksa v7 aday olabilir
  • v5 veya v8, UUID içine kendi verinizi yerleştirmek istediğiniz durumlara daha yakındır
    • Bu tür durumlarda kullanıcı çoğunlukla buna ihtiyaç duyduğunu zaten bilir
  • RFC'ye göre v7, v1 ve v6'yı iyileştirir; bu yüzden mümkünse v1·v6 yerine v7 kullanılmalıdır
    • v1 veya v6 gerçekten gerekiyorsa v6 kullanılabilir
  • v2, belirtilmemiş güvenlik amaçları için ayrılmıştır
  • v3, daha güçlü hash kullanan v5 ile yer değiştirmiştir; v3'ün gerekli olduğu durumlarda da kullanıcı büyük olasılıkla bunun farkındadır

1 yorum

 
GN⁺ 2024-08-27
Hacker News yorumları
  • UUID v2 ayrıntılarının olmadığı söylenen durum, sadece kötü şöhretli derecede belirsiz RFC okunduğunda geçerli: https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#t...
    Neredeyse hiç karşılaşılmasa da version 0 UUID diye bir şey de var. Sonradan başka “sürümler”in uyumlu şekilde tanımlanabilmesini sağlayan ayrılmış bitlerin kaynağı olduğu için anılmayı hak ediyor. Bununla ilgili araştırmayı UUID kütüphanemde derledim: https://github.com/okeeblow/DistorteD/blob/NEW%E2%80%85SENSA...
    Havalı olduğu için desteklemeye karar verdim ama tarih rollover’ı ve daha eski Apollo UID işleme biçimini hâlâ belirlemem gerekiyor

    • Adil olmak gerekirse RFC9562, UUID Version 2 spesifikasyonu için iki belgeye atıf yapıyor. Yine de RFC4122 bana göre fazla şifreliydi
      0-7 Variant alanında tanımlanmış tarihsel UUID türlerini insanların anlamasına yardımcı olacak bilgilendirici bir RFC taslağı üzerinde çalışmaya başlıyorum. Tartışmaya katılmak veya metni gözden geçirmek isterseniz https://github.com/yocto/draft-yocto-uuid adresine bakabilirsiniz
  • Ayrıntıları 2 dakikada bulabildim. Yazıdaki bağlantıya tıklayıp RFC 9562’nin DCE tanımı bölümüne gidiyorsunuz, oradaki ilk bağlantıdan spesifikasyona giriyorsunuz, sonra “UUID” diye aratıp Ek A’ya geçiyorsunuz; hepsi orada
    Adı kafa karıştırıcı biçimde “Universal Unique Identifier” ama gereken her şey var. En azından kendi yazısına koyduğu bağlantılara tıklayabilirdi

    • Buradan çıkarılacak iki ders var. Biri v2 UUID spesifikasyonunu okumak, diğeri de UUID’den üretildiği andaki bağlamsal bilgiyi çıkarmak
      Bağlam gereği diğer sürümlerin belli bileşenlerden üretildiği anlatılıyor; bu yüzden ilgili cümle açıkça ikincisinden söz ediyor. Biraz muğlak olsa da yanıltıcı denecek kadar değil
    • Ben de tam olarak aynı süreci yaşadım ve ayrıntılara pek dikkat etmediğini düşündüğüm için yazının tamamını hemen okumadım
      Yine de ek kısmı, dönemin bir anlık görüntüsü gibi okunması bakımından eğlenceliydi
    • Belki de yazıyı bir dil modeli yazmıştır
  • 73WakrfVbNJBaAmhQtEeDv ya da bK7nP9xM gibi kısa UUID standardı olsa güzel olurdu
    Teknik olarak bir yerde çakışma ihtimali olacağı için UUID sayılmaz ama rastgele olup aynı zamanda ezberlenebilecek kadar kısa bir ID standardı kombinasyonu istiyorum

    • Buna en yakın şey olarak ULID aklıma geliyor. 26 karakterlik base32, yani kısa; 128 bit; ayrıca sözlüksel sıralama da yapılabiliyor
      Daha popüler bir standardın olmama nedeni, bir şeylerden vazgeçmek zorunda olmanız diye düşünüyorum. 128 bit, neredeyse tüm kullanım alanlarında düşük çakışma riski sunuyor; ama daha küçüldükçe somut senaryo ile çakışmanın etkisini değerlendirmek gerekiyor, bu da standartlaştırmayı zorlaştırıyor. base64 ya da base85 gibi başka kodlamalar daha kısa olabilir ama büyük/küçük harf duyarlılığı veya URL güvenliği gibi şeylerden ödün verirsiniz: https://github.com/ulid/spec
    • Daha kompakt bir UUID gerekiyorsa mevcut UUID’leri URL-safe base64 ile 22 karakterlik biçimde gösterebilirsiniz
      Bu sadece aynı UUID’nin farklı bir gösterimi, ayrıca tersine çevrilebilir. UUID sonuçta 128 bitlik bir değer; gerçek bir dönüşümden çok alternatif bir yazımdır
    • Belki de aradığınız şey Sqids’dir. UUID’den çok daha kısa kimlikler üretir ama evrensel olarak benzersiz değildir ve tamsayı dizilerinden üretilir: https://sqids.org/
    • Genelde N bitlik rastgele sayı üretip bunu base58 ile kodluyorum. N’i ihtiyaca göre seçebilirsiniz
      Böylece bazı UUID sürümlerinin sunduğu monoton sıralama avantajını kaybedersiniz ama base58 URL için güvenlidir ve özel karakter içermez. Değerleri yine ikili olarak saklayabilirsiniz. Örneğin Postgres’te metin sütunu yerine bytea kullanabilirsiniz
    • 128 bit UUID’leri daha kısa metin biçiminde gösterebilen alternatif kodlama tekniklerini standartlaştırma çalışması sürüyor
      Tartışmaları burada görebilirsiniz: https://github.com/uuid6/new-uuid-encoding-techniques-ietf-d...
  • UUID v7 zaman damgası, Databend için büyük bir değişimdi. AWS S3’te metadata dosyalarını zaman damgasına göre hızlıca bulmak için kullanıyoruz; bu sayede vacuum benzeri işler çok daha hızlı oldu
    PR: https://github.com/datafuselabs/databend/pull/16049

    • İlginç ama zamana göre arama yapmak için UUID kullanmak benim aklıma pek gelmezdi. Ben olsam ayrı bir zaman damgası alanı tutardım
      Zamana göre sıralanan UUID’lerin büyük avantajı locality sağlamasıdır. İndekse yeni öğe eklemek çoğu zaman sona ekleme haline gelir ve rastgele eklemeye göre daha ucuz olabilir. Ama contention da artabilir; bu yüzden zaman damgasının önüne biraz rastgele bit koyup sıralı “shard”lar oluşturan hibrit bir yaklaşım da düşünülebilir. Okumalar da çoğu zaman en yeni verilere yoğunlaşır; dolayısıyla yeni verilerin bir arada olması ve cache’e iyi oturması faydalıdır
    • DynamoDB gibi anahtar-değer depoları için de çok iyi. Zaman damgası ya da ISO tarih önekli bileşik anahtarlardan çok daha temiz ve zaman damgası için ikincil indeks harcamaktan da daha iyi
  • uuid2'nin amacını anlamak zor. Böyle başka türlerin de olduğunu bilmiyordum; Xandr'a kişisel verilerimin silinmesini talep ederken uuid2'yi ilk kez gördüm: https://news.ycombinator.com/item?id=40913915
    Wikipedia'yı okuyunca bile neden bir “evrensel benzersiz tanımlayıcı” yapıp sonra birden çok tür tanımladıklarını, bunların bazılarının neden başlangıçta asıl PC'ye kadar izlenebilir olacak şekilde tasarlandığını pek anlayamıyorum. MAC kodunun bir kısmını katmak uuid2'yi daha rastgeleye mi yaklaştırıyor, yoksa başka bir sebep mi var, merak ediyorum. Gizlilik açısından bakınca, seçilebilecek karakter sayısı çok fazla olan uzun bir tanımlayıcı kullanıp çakışma olasılığını fiilen yok etmek yeterli olmaz mı diye de düşünüyorum

    • Asıl amaç, Apollo dağıtık hesaplama mimarisinde mesajları tanımlamaktı. UID ve sonrasında UUID, iki boyutun kesişimini işaretleyen tersine çevrilebilir bir yöntemdi
      Herhangi iki makine de aynı iki girdi için aynı UID/UUID'yi üretebiliyordu ve tanımlanmış mesajı alan taraf, tanımlayıcıyı tekrar özgün bileşenlerine ayırabiliyordu. Geçici mesajların etiketi olarak tasarlandığı için iki boyut zaman ve donanım kimliğiydi; başlangıçta Apollo seri numarası, daha sonra Ethernet donanım adresi gibi değerler kullanıldı
      Karışıklığın büyük kısmının, erken AEGIS uygulamalarında Apollo mühendislerinin dosya sistemi tanımlaması için “canned”, yani statik ve iyi bilinen UID'ler kullanmaya başlamasından kaynaklandığını düşünüyorum. Zamanla UUID'nin genel kullanımı, tekrarın amaçlandığı geçici tanımlayıcılardan, tekrarın önlenmesi gereken canned tanımlayıcılara tamamen kaydı ve iki boyut da rastgelelik ile bir başka rastgeleliğe dönüştü
      Tarihçe daha da karmaşık. Microsoft, Windows NT için MSRPC yapmak üzere Apollo'daki kilit isimlerden birini işe aldı ve böylece GUID de ortaya çıktı. GUID'nin alan yerleşimi UUID'den farklıdır ve pek çok kaynağın söylediğinin aksine karma endianness kullanmaz. Microsoft, geçici RPC mesajlarını tanımlayan GUID'lerin yanı sıra COM sınıfları, medya codec'leri ve iyi bilinen tanımlayıcı gerektiren neredeyse her şey için canned GUID kullanmayı sever. Örnek: https://gix.github.io/media-types/
      Aynı yorum dizisinde depoma ikinci kez bağlantı verdiğim için kusura bakmayın; ama UUID kütüphanemin README dosyasında bu tarihi toparlamaya başlamıştım ve devam etmem gerekiyor. Apollo 1980'de başladı, Leach/Salz UUID RFC taslağı ise ancak 1998'de çıktı; yani modern standartlarda yer almayan çok fazla ayrıntı var: https://github.com/okeeblow/DistorteD/blob/NEW%E2%80%85SENSA...
  • UUID v4, belirli konumlara tire koyan bir rastgele bayt üretecinden ibaret. Bunu özellikle kullanmak zorunda değilsiniz; rastgele baytları kendiniz üretip alan tasarrufu sağlayabilirsiniz
    Gereksiz tireler ve sürüm bilgisi gibi şeyler de ortadan kalkar

    • UUID, 128 bitlik bir sayıdır; tireli dize gösterimi bu sayıyı ifade etmenin yalnızca yollarından biridir
      Bu, IPv4 adresinin 32 bitlik bir sayı olması ve “noktayla ayrılmış dört grup” biçiminin onun gösterimlerinden biri olması gibi. UUID'yi bir dize biçimi olarak düşünüyorsanız, UUID hakkındaki en temel kavramı baştan yanlış kurmuşsunuz demektir. Yalnızca rastgele bir tanımlayıcı isteseniz bile, rastgele bir UUID'nin üzerinde “bu kasıtlı olarak rastgele üretildi” diyen küçük bir bayrak biti bulunmasını hoş buluyorum. Bağlamı olmayan tek bir tanımlayıcıyla karşılaştığınızda işe yarar
    • UUID v4, bunun sürüm 4 olduğunu göstermek için 4 biti de sabit bir değere ayarlar
      Farklı üretim yöntemleri arasında ayrı ad alanları oluşturmanın ne kadar faydalı olduğu tartışılabilir ama sıradan bir rastgele sayı üretecinin geçerli bir UUIDv4 üretme olasılığı yalnızca 1/16'dır. Elbette UUID üretecini kendiniz yazmak istiyorsanız, bitleri doğru ayarlamak önemsiz bir ayrıntıdır
    • Doğru, ama çoğu geliştirici için çekici olan tarafı uygulamasının basit olması. Neredeyse her dilde tek satırda çalışan bir UUID kütüphanesi var
      Go'da uuid.New().String() yeterli, ama crypto/rand ile rastgele veri okuyup bunu base64 veya hex'e çevirmek daha fazla satır ve emek gerektiriyor
  • MAC tabanlı sürümlerin kullanılmamasını öneririm. Teorik olarak v4 ve v7 dışındakilerin hepsi buna girebilir ama en kötüsü v1'dir
    v3'te de MD5'in ciddi biçimde kırılmış olması sorunu var

    • MD5, kriptografik bir hash fonksiyonu olarak “kırılmıştır”. Kriptografik olmayan bir hash fonksiyonu olarak ise hâlâ tamamen kullanılabilir durumdadır
  • 4 dışındaki ayrıntıları bilmiyordum ama gerçekten eksik olan faydalı şeyin, SHA256 verisi ve sayaç kullanan bir yöntem olduğunu düşünüyorum. PBKDF2'ye benzer bir yapı gibi
    Gizliliği koruyan türetilmiş bir tanımlayıcı olabilir ve belirli bir UUID'nin belli bir seed'den türetildiğini gevşek biçimde kanıtlamaya da yarayabilir

    • Buna gerçekten ihtiyacınız varsa, UUIDv4'ü bir kodlama biçimi olarak görüp bir kripto algoritmasıyla 122 bitlik çıktı üretir, sonra bunu UUID olarak kodlarsınız
      Bunun dışında muhtemelen daha uzun bir çıktı istemeye başlarsınız
    • v3'e benzer ama hash algoritmasının belirtilebildiği bir biçim
  • Sadece v7 kullanın
    Şimdi güvenlik uzmanı olmayanların “hayır” deme sırası gelecek

    • Oluşturulma tarihi hassas bilgi olabiliyorsa veya UUID'nin tamamen tahmin edilemez olması gerekiyorsa v4 kullanın. Bunun dışındaki durumlarda v7 kullanın
    • UUID ve ULID'de beni hep rahatsız eden şey, bildiğim kadarıyla bunları deterministik olarak üretmenin iyi bir yolunun olmaması
      Pek çok kullanımda, veriyi yeniden işleseniz bile aynı ID'yi üretebilmek çok faydalı olurdu ama bunu başarmanın standart bir yolunu bilmiyorum
    • Güvenlikle ilgili meselelerin neden bu kadar kolay geçiştirildiğini anlamıyorum