2 puan yazan GN⁺ 2024-05-08 | 1 yorum | WhatsApp'ta paylaş
  • Go 1.22, math/rand ve math/rand/v2 için varsayılan rastgele sayı kaynağını kriptografik olarak güçlü bir üreteç ile değiştirerek, crypto/rand kullanılması gereken yerlerde yapılan hataların etkisini büyük ölçüde azaltıyor
  • Eski Go 1 üreteci, 607 adet uint64 durum kullanan bir lineer geri beslemeli kaydırma yazmacı olduğundan, yalnızca 607 çıktı gözlemlenirse geçmiş ve gelecek değerler yeniden oluşturulabiliyordu
  • math/rand/v2 içindeki PCG-DXSM, istatistiksel rastgelelik kalitesini ve durum boyutunu iyileştirse de, gizli değerler için gereken öngörülemezliği garanti etmiyor
  • Yeni ChaCha8Rand, 32 baytlık seed, her 16 blokta yeniden anahtarlama ve çekirdek başına 300 bayt durum kullanıyor; math/rand/v2, math/rand'ın bir kısmı ve map hash seed'lerinde uygulanıyor
  • Performans maliyeti sınırlı: ChaCha8Rand, Go 1 üretecinden daha yavaş olsa da en fazla 2 kat içinde kalıyor ve tipik sunucularda fark 3 ns'yi aşmadığından çoğu program için güvenlik kazanımı daha büyük

Go 1.22'nin değiştirdiği rastgele sayı varsayılanları

  • Go 1.22, math/rand ve math/rand/v2 için varsayılan olarak kriptografik olarak güçlü sözde rastgele sayı üreteci kullanacak şekilde değiştirildi
  • Amaç, geliştiricilerin crypto/rand gerekli olan yerlerde yanlışlıkla math/rand kullanması durumunda oluşacak zararı azaltmak
  • Go'nun rastgele sayı API'leri geleneksel olarak iki kategoriye ayrılıyor
    • math/rand: simülasyon, örnekleme, sayısal analiz, kriptografik olmayan rastgele algoritmalar, fuzzing, shuffle, üstel backoff gibi işler için kullanılan istatistiksel rastgelelik
    • crypto/rand: anahtar ve token gibi öngörülemezlik gereken durumlar için kriptografik rastgelelik

İstatistiksel rastgeleliğin neden yeterli olmadığı

  • İstatistiksel rastgele sayı üreteçleri, temel istatistik testlerini geçerse birçok kriptografik olmayan kullanım için yeterli olabilir
  • Ancak algoritmayı bilen bir gözlemci yeterli sayıda çıktı görürse, sonraki diziyi tahmin edebilir
  • Unix V3'ün srand ve rand işlevleri, daha sonra C ve çeşitli dillerdeki rastgele sayı API'lerini etkileyen erken bir örnekti
    • Durum tek bir tamsayı seed ile ayarlanıyordu
    • Sonraki değer, lineer eşlenik üreteç (LCG) yöntemiyle hesaplanıyordu
    • İç durum çok basit olduğundan, tek bir çıktıdan bile gelecekteki değerleri kolayca hesaplamak mümkündü
  • LCG'de sabitler, olası çıktıların tekrar etmeden önce bir kez üretilmesi için seçilebilse de, düşük bitlerin kısa döngülerle tekrar etmesi gibi bir zayıflık vardır

Go 1 üretecinin yapısı ve zayıflıkları

  • Go 1'in math/rand üreteci, lineer geri beslemeli kaydırma yazmacı ailesindendir
  • İç durum, 607 adet uint64 içeren vec slice'ından oluşur
    • vec[606] “tap”tir
    • vec[334] “feed”dir
    • Sonraki değeri üretirken tap ve feed toplanarak x oluşturulur, x feed konumuna yazılır ve ardından döndürülür
  • Gerçek uygulamada maliyeti azaltmak için tüm slice taşınmaz, yalnızca tap ve feed konumları geriye kaydırılır
    • Sonraki değeri üretmek için iki çıkarma, iki koşullu toplama, iki load, bir toplama ve bir store gerekir
  • Döndürülen değer iç durum vektörünün bir öğesi olduğundan, 607 çıktı okunduğunda tüm durum açığa çıkar
    • Aynı vec doldurulup algoritma çalıştırılırsa gelecekteki değerler tahmin edilebilir
    • Algoritma tersten çalıştırılırsa geçmiş değerler de yeniden oluşturulabilir
  • Go 1 üreteci güvenlik amaçlı tasarlanmamıştır ve üretilen sayıların kalitesi de başlangıç vec kurulumuna bağlıdır

PCG'nin iyileştirdikleri ve kalan sınırlamalar

  • math/rand/v2, daha modern bir istatistiksel rastgele sayı üreteci olarak Melissa O’Neill'ın PCG yaklaşımını benimser
  • Go'daki PCG, 128 bitlik bir LCG temeline dayanır ve scramble işleviyle 128 bitlik durumu 64 bit çıktıya indirger
  • Go, teklif tartışmaları sırasında O’Neill'ın önerisine dayanarak çarpma tabanlı bir scramble kullanmıştır
    • Bu biçim PCG-DXSM olarak adlandırılır
    • Numpy de bu PCG biçimini kullanır
  • PCG'nin durumu, Go 1 üretecine kıyasla çok daha küçüktür
    • Go 1 üreteci: 607 adet uint64
    • PCG: iki adet uint64
  • PCG başlangıç durumuna daha az duyarlıdır ve çeşitli istatistik testlerinden geçer, ancak öngörülemezliği garanti etmez
    • PCG-XSL-RR tersine çevrilebilir
    • PCG-DXSM'in de tersine çevrilebilir olması şaşırtıcı sayılmaz
  • Gizli değer üretimi için PCG yerine başka bir üreteç gerekir

Kriptografik rastgelelik ve işletim sisteminin rolü

  • Kriptografik rastgelelik, üretim yöntemi bilinse ve geçmişte çok sayıda çıktı görülse bile gözlemci açısından pratikte tahmin edilemez olmalıdır
  • Kripto protokolleri, gizli anahtarlar, modern ticaret ve çevrimiçi gizlilik kriptografik rastgeleliğe dayanır
  • Gerçek rastgelelik kaynağını işletim sistemi sağlar
    • Fare, klavye, disk, ağ zamanlaması gibi fiziksel aygıtlardan rastgelelik toplar
    • Son dönemde CPU'nun doğrudan ölçtüğü elektriksel gürültü de kullanılır
  • İşletim sistemi yeterli rastgelelik, örneğin en az 256 bit topladığında, hash veya kriptografik algoritmalarla uzun rastgele diziler üretir
  • Geçmişte daha çok /dev/random gibi aygıt dosyaları kullanılırdı, ancak güncel işletim sistemleri artık doğrudan sistem çağrıları sağlar
  • Go'nun crypto/rand paketi işletim sistemi farklılıklarını gizler ve aynı arayüz olan rand.Read işlevini sunar

ChaCha8Rand tasarımı

  • Go 1.22'deki yeni üreteç ChaCha8Rand, Daniel J. Bernstein'ın ChaCha akış şifresinin hafifçe değiştirilmiş bir biçimidir
  • ChaCha'nın TLS ve SSH'de de kullanılan ChaCha20 biçimi yaygın olarak kullanılır
  • Jean-Philippe Aumasson'un Too Much Crypto çalışmasına göre 8 turlu ChaCha8 de güvenlidir ve ChaCha8 yaklaşık 2,5 kat daha hızlıdır
  • ChaCha8Rand, ChaCha8'i rand.Source olarak kullanmak için üretilen blokları girdiye XOR'lamak yerine doğrudan rastgele akış olarak kullanır
    • Bu, tamamı 0 olan veriyi şifrelemek veya çözmekle aynıdır

ChaCha8Rand'deki değişiklikler

  • ChaCha8Rand, 32 baytlık bir seed değerini ChaCha8 anahtarı olarak kullanır
  • ChaCha8, 64 baytlık bloklar üretir ve hesaplama sırasında bloklar 16 adet uint32 olarak ele alınır
  • Normal uygulamalarda SIMD komutlarıyla 4 blok aynı anda hesaplanabilir, ancak bunları XOR girdisi olarak kullanmak için interleaved blokların yeniden ayrıştırılması gerekir
    • ChaCha8Rand, bu interleaved blokların kendisini rastgele akış olarak tanımlayarak unshuffle maliyetini ortadan kaldırır
  • ChaCha8'in blok sonlandırma aşamasında belirli değerler her uint32 üzerine eklenir
    • Bunların yarısı anahtar malzemesi, yarısı ise bilinen sabitlerdir
    • ChaCha8Rand, bilinen sabitleri yeniden eklemeyerek son toplamanın yarısını ortadan kaldırır
  • Her 16. üretilen blokta son 32 bayt, sonraki 16 blok için anahtar olarak kullanılır
    • Bu yeniden anahtarlama bir tür ileri güvenlik sağlar
    • Üretecin bellekteki tüm durumu açığa çıksa bile yalnızca son yeniden anahtarlamadan sonraki değerler geri elde edilebilir; geçmiş değerlere ulaşılamaz
  • Go, ChaCha8Rand C2SP spesifikasyonunu ve test vakalarını yayımlayarak, aynı seed ile farklı uygulamaların da Go uygulamasıyla aynı tekrar üretilebilirliği paylaşmasını sağlar

Standart kütüphanede uygulandığı yerler

  • Go runtime, işletim sisteminin sağladığı kriptografik rastgelelikle seed edilmiş çekirdek başına ChaCha8Rand durumu tutar
    • Her çekirdek için durum boyutu 300 bayttır
    • 16 çekirdekli bir sistemde bu, tek bir paylaşımlı Go 1 üreteci durumunun 4.872 bayta yakın seviyededir
    • Çekirdek başına durum sayesinde kilit rekabeti olmadan hızlı rastgelelik üretilebilir
  • math/rand/v2 paket işlevleri her zaman ChaCha8Rand kullanır
    • Örnek: rand.N, rand.Float64
  • math/rand paket işlevleri, rand.Seed çağrılmamışsa ChaCha8Rand kullanır
    • Örnek: rand.Intn, rand.Float64
    • rand.Seed çağrılırsa uyumluluk için Go 1 üretecine geri dönülmesi gerekir
  • Runtime, yeni map'lerin hash seed'ini önceki wyrand tabanlı üreteç yerine ChaCha8Rand ile seçer
    • Saldırgan, map uygulamasındaki belirli hash işlevini bilirse, girdileri hazırlayarak map'i karesel zamanlı davranışa zorlayabilir
    • Tek bir global seed yerine map başına seed kullanmak başka dejeneratif davranışları da önler
    • Map seed'i için kriptografik rastgeleliğin zorunlu olup olmadığı net değildir, ancak bu geçiş basit ve ihtiyatlı bir tercihti
  • Ayrı bir ChaCha8Rand örneğine ihtiyaç duyan kodlar rand.ChaCha8 oluşturabilir

Güvenlik hatalarının etkisini azaltmak

  • Go, güvenlik sorunlarına yol açan yaygın hataları azaltmayı veya ortadan kaldırmayı hedefleyerek varsayılan olarak güvenli kod yazımını destekler
  • Go 1.20'de math/rand içindeki Read deprecated olduğunda, bazı geliştiricilerin anahtar malzemesi üretimi gibi crypto/rand gerektiren yerlerde math/rand kullandığı ortaya çıktı
  • Go 1.20'de bu tür hatalar ciddi güvenlik sorunlarıydı
    • Anahtarın nerede kullanıldığı
    • Anahtarın nasıl sızdırıldığı
    • Diğer rastgele sayı çıktılarının saldırgana anahtar türetmek için ipucu verip vermediği araştırılmalıydı
  • Go 1.22'de aynı hata hâlâ bir hatadır, ancak bir güvenlik felaketine dönüşme ihtimali azalır
  • Yine de gizli değerler için crypto/rand kullanmak daha iyidir
    • İşletim sistemi çekirdeği rastgele değerleri daha iyi koruyabilir
    • Çekirdek üretece sürekli yeni entropi ekler
    • Çekirdek uygulamaları daha fazla incelemeye tabi tutulmuştur

Kripto gibi görünmeyen örnekler

  • Rastgele UUID üretimi, UUID gizli bir değer olmadığından math/rand için yeterli görünebilir
  • Ancak math/rand mevcut zaman ile seed edilirse, farklı bilgisayarlar aynı anda çalıştığında aynı değerleri üretebilir
    • Mevcut zamanın yalnızca milisaniye hassasiyeti sunduğu sistemlerde bu olasılık daha yüksektir
  • Go 1.20'de işletim sistemi entropisine dayalı otomatik seed olsa bile, Go 1 üretecinin seed'i yalnızca 63 bitlik bir tamsayıdır
    • Başlangıçta UUID üreten bir program için olası ilk UUID sayısı 2⁶³ ile sınırlıdır
    • Yaklaşık 2³¹ UUID sonrasında çakışma ihtimali ortaya çıkar
  • Go 1.22'deki ChaCha8Rand, 256 bit entropi ile seed edilir
    • Olası ilk UUID sayısı 2²⁵⁶'dır
    • Çakışma endişesi gerekmez
  • Front-end sunucunun istekleri back-end sunuculara rastgele dağıttığı yük dengelemede de öngörülemez rastgelelik gerekli olabilir
    • Saldırgan atamaları gözlemleyip öngörülebilir algoritmayı biliyorsa, pahalı istekleri belirli bir back-end'e yığabilir
    • Go 1 üretecinde bu nadir ama mümkün bir sorundu
    • Go 1.22'de ise sorun olmaktan çıkar

Performans özellikleri

  • ChaCha8Rand'in güvenlik avantajlarının küçük bir maliyeti vardır, ancak performansı Go 1 üreteci ve PCG ile aynı genel aralıktadır
  • Karşılaştırılan iki işlem şunlardır
    • Uint64: rastgele akıştan bir sonraki uint64 değerini döndürmek
    • N(1000): [0, 1000) aralığında rastgele bir sayı döndürmek
  • 64 bit x86 yongada GOARCH=386 ile derlenip 32 bit modda çalıştırıldığında, PCG'nin 128 bit çarpımı nedeniyle PCG, ChaCha8Rand'den daha yavaştır
    • ChaCha8Rand 32 bit SIMD aritmetiği kullanır
  • Bazı sistemlerde Go 1: Uint64, PCG: Uint64'ten hızlıdır; ancak Go 1: N(1000), PCG: N(1000)'den yavaştır
    • Go 1'de N(1000), aralık daraltma için iki adet 64 bit tamsayı bölmesi kullanır
    • PCG ve ChaCha8'in N(1000) işlemleri çoğu durumda bölmeden kaçınan daha hızlı math/rand/v2 algoritmasını kullanır
  • Genel olarak ChaCha8Rand, Go 1 üretecinden daha yavaştır ama 2 katından fazla yavaş değildir
  • Tipik sunucularda fark 3 ns'yi geçmez ve bu farkın darboğaz olduğu program sayısı çok azdır

Sonuç

  • Go 1.22, kod değişikliği gerektirmeden programların güvenliğini artırır
  • Temel yaklaşım, crypto/rand yerine yanlışlıkla math/rand kullanılmasından doğan yaygın sorunu azaltmak için math/rand'ın kendisini güçlendirmektir
  • npm keypair paketi gibi, Web Crypto API olmadığında JavaScript Math.random ile RSA anahtar çifti üretmeye çalışan örnekler de vardır
  • Sistem güvenliği, geliştiricilerin hata yapmayacağı varsayımına dayanamaz
  • Go 1.22'nin ChaCha8Rand yaklaşımı, “matematiksel” rastgelelikte bile kriptografik olarak güçlü sözde rastgele sayı üretecinin diğer üreteçlerle rekabet edebilecek performans sunabildiğini gösterir

1 yorum

 
GN⁺ 2024-05-08
Hacker News görüşleri
  • Yazıda anlatıldığı gibi, rclone’da tam olarak bu hatayı yaptık
    crypto/rand içindeki Read’i kullanan kodu refactor ederken import otomatik olarak değişti; muhtemelen math/rand kullanan kodla karışınca goimports bunu math/rand olarak değiştirdi
    Sonuçta güvenli rastgele sayı üreteci yerine, rclone’ın zamana göre seed ettiği deterministik bir üreteç kullanılır hâle geldi ve diff’te fark edemedik :-(
    https://www.cvedetails.com/cve/CVE-2020-28924/
    Bu yüzden bu değişikliği güçlü biçimde destekliyorum

    • Acı verici, üzgünüm. 2016’da goimports, crypto/rand’ı tercih edecek şekilde değiştirildiği için refactor sırasında tam olarak ne olduğunu kesin bilemiyorum
      Muhtemelen aynı dosyada math/rand’a özgü API kullanan kod yer almış olabilir
      https://go-review.googlesource.com/24847
      Her hâlükârda bu tür şeylerin temizleniyor olmasına sevindim
    • Ben de math/rand kullanıldığını sanan birinden zafiyet bildirimi almıştım. Aslında öyle değildi; birkaç dosyanın karıştırılmasından ibaretti, yani büyük bir mesele değildi, ama tüm bu durumun ne kadar kafa karıştırıcı olduğunu gösteriyor
      text/template ve html/template da benzer. Geriye dönüp bakınca bu tür paket adı gölgelemesi kötü bir fikirmiş
    • "secure password generation golang" diye aratınca neredeyse tüm örneklerin math/rand kullandığını da gördüm
      Daha da kötüsü, hepsi parolayı üretmeden hemen önce seed’i mevcut zamana göre sıfırlıyor
      Kodumuzda birinin math/rand kullandığını fark ettikten sonra, bunu nereden kopyalamış olabileceğini merak edip araştırırken öğrendim
    • goimports neredeyse en başından beri math/rand.Read ve crypto/rand.Read için özel işlem yapıyordu
      Ancak 2016’daki https://github.com/golang/tools/commit/0835c735343e0d8e375f0... commit’ine bakınca "rand.Read" ifadesinin "math/rand" olarak yorumlanabildiği bir dönemden söz ediliyor
      Belki de o döneme denk gelmiş olabilir
    • "PredictableRand" gibi isimde bir API çağrısı sunmak o kadar zor olmasa gerek
  • Geçen hafta spacey de https://news.ycombinator.com/item?id=40237491 adresinde paylaşmıştı, ama o gönderi https://news.ycombinator.com/item?id=40224864 gönderisinin tekrarı sanılıp yanlışlıkla gömülmüş gibi görünüyor
    İki go.dev blog yazısı aynı serinin iki parçası, ama epey farklılar. Bu yazı verimli güvenli rastgele sayı üretme algoritmaları hakkında; önceki yazı ise Go API tasarımı üzerine

  • Russell Cox düzenli olarak harika teknik blog yazıları, öneri metinleri ve işler ortaya koyuyor
    Yazma ve düşünme netliğinizi artırmak istiyorsanız Russell Cox ile başlamak iyi bir nokta

    • Onun sonlu durum otomatları ve regex serisi sayesinde bu alana iyice kapıldım
      O zamanlar Russ Cox’un kim olduğunu bile bilmiyordum, ama o yazı serisi gerçekten müthişti
      Regex implementasyonu hakkında ücretsiz erişilebilen kaynaklar arasında muhtemelen en yüksek kalitelisi; sonrasında çeşitli derleyici odaklı kitaplar geliyor, ama onlar ne ücretsiz ne de web’de kolayca aranabilir
    • Video demoları da iyi yapıyor https://research.swtch.com/acme
  • crypto/rand’ın kesinlikle gerekli olduğu bir yerde math/rand kullanmışlığım var
    Bunun sonucunda dnscrypt-proxy2’nin erken sürümlerinde statik anahtarlar kullanıldı
    Sebep, import’ları otomatik ekleyen VSCode eklentisiydi. Güvenli rastgelelik gerektiren tüm kaynak dosyalarda crypto/rand’ı doğrudan ve dikkatle import etmiştim, ama bir dosyada atlamışım; her şey derlenip düzgün çalışıyordu ve eklentinin o belirli dosyaya sessizce math/rand import’u eklediğini fark etmedim
    O zamandan beri yanlış rand’ın otomatik import edilmesini önlemek için crypto/rand’ı cryptorand takma adıyla import ediyorum
    Bu arada Zig de ChaCha8 tabanlı rastgele sayı üreteci kullanıyor; kriptografik işlemlerde kullanıcı kendi üretecini sağlayamıyor ve her zaman güvenli üreteç kullanılıyor. Test için bazı fonksiyonlar açıkça seed alıyor
    Kısıtlı ortamlar için standart kütüphanede Ascon permütasyonuna ve Reverie yapısına dayanan daha küçük bir üreteç de var

    • Sizin durumunuzda tam olarak ne olduğunu bilmiyorum, ama muhtemelen anlattığınızdan farklı olmuş olabilir
      2016’da goimports, math/rand yerine crypto/rand’ı tercih edecek şekilde değiştirildi (https://go-review.googlesource.com/24847); bu da Go için VSCode desteği çıkmadan önceydi
    • Başkası da aynı şeyi söyledi. Açıkçası import’ları otomatik ekleme pratiği tamamen tuhaf görünüyor ve adları farklı ad alanlarına ayırmanın amacını baştan bozuyor
  • 2020'lerde bile birçok programlama dilinin varsayılan rastgele sayı uygulamasının neden LFSR, MT gibi hızlı rastgele sayı üreteçleri kullandığını sık sık düşündüm
    İnsanların sözde rastgele sayı üretecine mi yoksa kriptografik olarak güvenli sözde rastgele sayı üretecine mi ihtiyaç duyduğunu bilmediğini varsayarak muhafazakâr davranmak; varsayılanı ikincisine çevirmek ve birincisine ihtiyaç duyanların bunu açıkça seçmesini sağlamak bana daha iyi görünüyor

    • PHP 8.2'nin yeni nesne yönelimli rastgele sayı API'si tam olarak bunu yaptı
      Geliştirici kullanılacak rastgele sayı motorunu açıkça seçmezse kriptografik olarak güvenli bir üreteç alıyor
      Artık zor kısım insanları yeni API'ye geçmeye ikna etmek. Dahası, küresel Mt19937 örneğini kullanan mt_rand()dan, PHP 7.0'dan beri zaten mevcut olan CSPRNG tabanlı random_int()e geçmek bile kolay değil
      [1] https://www.php.net/releases/8.2/en.php#random_extension
    • Yakın zamanda, karmaşık bir veri yapısının çeşitli bileşenleri için rastgele ID'ler üreten yeni bir Go kütüphanesi kullanmaya başladım
      Benim kullanım senaryomda on binlerce bileşen vardı; profil çıkarınca veri yapısını başlatma süresinin kayda değer bir kısmının crypto/rand içindeki Read()e harcandığını ve MacBook'umda sistem çağrıları yaptığını gördüm
      Kütüphaneyi math/rand içindeki Read()i kullanacak şekilde yamalayınca performans ciddi biçimde iyileşti
      math/randin daha hızlı olmasının yanında, belirgin bir neden yokken sistemin entropi havuzunu tüketmekten de endişeleniyordum. Bu durumda ID'lerin rastgele olması için tek gerekçe, veri yapısını serileştirip/deserileştirip daha sonra bileşen eklemekti; ben bunu yapmayı düşünmüyordum
      Bu blogda anlatılan değişiklik zamanlamasının benim deneyimimle tam olarak nasıl örtüştüğünü bilmiyorum. Belki de eski bir kütüphane sürümü kullanıyordum; şimdi crypto/rand fiilen math/randden ayırt edilemeyecek durumdaysa, ne âlâ :-)
    • Burada ChaCha8 kullanan CSPRNG için daha iyi argümanlardan biri, benchmark'larda PCG'ye göre 2 katın içinde kalması
      Durum boyutu hâlâ nispeten büyük (64 bayta karşı 16 bayt), ama mt19937 ya da eski Go PRNG gibi şeylerden çok daha iyi
      CSPRNG çok daha yavaş olsaydı, azaltılmış turlu ChaCha varyantı olmayan sıradan CSPRNG'lerde genelde olduğu gibi, varsayılan değer olarak cazibesi azalırdı
    • Birincisine ihtiyaç duyulan başka hangi durumlar var? Aklıma yalnızca yeniden üretilebilir sonuçlar gereken sabit seed geliyor. Örneğin test veya doğrulama gibi
      Seed'e ihtiyaç olmasa da insanları PRNG tarafına iten küçük bir etken daha var. CSPRNG API'lerinde sistem çağrısı hatası ya da entropi eksikliği ihtimaline karşı her zaman ele alınması gereken bir hata bulunuyor
      crypto/rand okuması pratikte ne kadar sık başarısız olur? Modern sistemlerde entropiyi tüketmek için ne kadar çok okuma yapmak gerekir? Milyarlarca istekte bile başarısızlık görmedim, dd de sorunsuz çalışıyor
      Çoğu kullanım senaryosu için Must/panic tarzı bir API'nin varsayılan olarak daha uygun olup olmadığını da merak ediyorum
      Ayrıca Python'ın secrets paketine (https://docs.python.org/3/library/secrets.html) baktım; istisna fırlatabileceğine dair hiçbir ifade yok. Pratikte bu hiç yaşanmayan bir şey mi?
    • “Açıkça vazgeçilmediği sürece sistemdeki tüm rastgele sayılar CSPRNG'den gelmeli” yaklaşımını seviyorum
      Biraz performans kaybetme karşılığında, yanlış rastgele sayı üretecini kullanıp felakete yol açmama konusunda çok daha güçlü bir güvence elde ediyorsunuz
      Neredeyse tüm dillerde geliştiricilerin hâlâ bu keskin kenara dikkat etmek zorunda olması üzücü
  • Bilmeyenler için ekleyeyim: gosec ve onun uzantısı olan golangci-lint, math/rand kullanımını uyarıyor
    https://github.com/securego/gosec/blob/d3b2359ae29fe344f4df5...

    • math/rand/v2de en sevdiğim şeylerden biri, iş yerinde nolint yönergeleri ve ardından gelen PR tartışmaları olmadan kullanabilmek
  • Güvenlik ve yeni v2 seçenekleriyle ilgili öneriyi hâlâ yorumlamaya çalışıyorum
    Blog yazısı “gizli değerler için başka bir şeye ihtiyaç var” gibi bir cümle kuruyor; ardından kriptografik rastgelelik, ChaCha8 ve sistem rastgeleliğiyle seed edilme biçimini ayrıntılı anlatıp çok “güvenli” bir izlenim veriyor
    Ama paket dokümantasyonunda şöyle yazıyor
    ... but it should not be used for security-sensitive work ... This package's outputs might be easily predictable regardless of how it's seeded. For random numbers suitable for security-sensitive work, see the crypto/rand package.
    O hâlde blog yazısı neden math/rand/v2nin “gizli değerler” için kullanılıyormuş gibi bir ima yaratıyor?
    Kısaca, hassas olan her şeyde hâlâ crypto/rand kullanılmalı ve burada açıklanan iyileştirme, birinin math/rand/v2yi uygunsuz biçimde kullanması durumunda bir güvenlik ağı anlamına mı geliyor?

    • Evet. math/rand/v2 ideal değil, ama artık yanlışlıkla crypto/rand kullanılması gereken yerde kullanıldığında hemen ölümcül bir güvenlik açığına dönüşmüyor
      Yazıda da şöyle deniyor
      crypto/rand kullanmak hâlâ daha iyidir. Çünkü işletim sistemi çekirdeği rastgele değerleri çeşitli gözetleme saldırılarına karşı gizli tutma işini daha iyi yapabilir; çekirdek üretece sürekli yeni entropi ekler ve daha fazla incelemeden geçmiştir. Ama yanlışlıkla math/rand kullanmak artık bir güvenlik felaketi değildir
  • En kötü benchmark’larda bile yeni strateji, güvenli olmayan rastgele sayı üretecinden kabaca yalnızca yarı yarıya daha yavaştı; benchmark’ların çoğunda fark çok daha küçüktü.
    Go, standart kütüphane ve onun üzerine inşa edilen uygulamalar için güvenlik ile performans dengesini iyi kuruyor. Diğer ekosistemler de bunu izlese iyi olur.
    Uygulamanızın hızlı ve güvenli olmayan rastgele sayılara ihtiyacı varsa, dahili üreteci kendiniz uygulamanız gerekir.
    Kolayca erişilebilir bir yerde güvenli olmayan rastgele sayı bulundurmak, ortadan kaldırılabilecek bir ayağa sıkma aracıdır.

    • Dürüst olmak gerekirse bu daha kötü görünüyor.
      İnsanları "random" ilkel işlevinin kriptografik olarak güvenli olduğunu varsaymaya teşvik etmek, kötü pratikleri özendirmektir.
      math/rand/v2’yi kriptografik olarak güvenli yapmak bir sorunu çözebilir; ama artık güvenlik vaat ediyor gibi görünmeyen şey “sorunsuz” hale geliyor.
      Genel olarak math/rand fonksiyonları için kriptografik olarak güvenli olduklarına dair bir teamül yoktur. Bunu değiştirip kötü kodun tesadüfen doğru çalışmasını sağlarsak, bu kadar bariz hatalar yapıyorsak başka hangi hataları yaptığımızı da perdeleyebilir.
  • Go 1’in math/rand’ını daha doğru olarak toplamalı gecikmeli Fibonacci üreteci diye adlandırmak daha yerinde olur.
    İlk duyurusu Green, Smith ve Klem’in makalesidir.
    [1] https://doi.org/10.1145/320998.321006

    • O makalede “gecikmeli” kısmından bahsedilmiyor gibi görünüyor. Ya da ben kaçırmış olabilirim.
      https://www.leviathansecurity.com/blog/attacking-gos-lagged-... bağlantısını da biliyorum; orada da gecikmeli Fibonacci üreteci deniyor.
      Rob Pike ile ben birkaç ay önce Go 1 üretecinin özgün C sürümünü yazan Don Mitchell’la e-posta üzerinden yazışıp bu algoritmayı nasıl tarif edeceğini sorduk; o da “Hatırladığım kadarıyla Jim ve ben Marsaglia’nın LFSR benzeri üretecini uygulamıştık” diye yanıtladı.
      İki açıklamanın, yani gecikmeli Fibonacci ve LFSR benzeri üretecin, farklı açılardan bakıldığında ikisinin de doğru olduğunu düşünüyorum. İkisi de olur; ama yazıda özgün yazarın açıklamasını kullanmaya karar verdim.
  • Küçük bir kusur belirtmek gerekirse, burada istatistiksel rastgelelik ile sözde rastgele sayı üreteci biraz karıştırılmış gibi.
    Wiki’deki istatistiksel rastgelelik tanımı şu: “Bir sayı dizisinde fark edilebilir bir örüntü veya düzenlilik yoksa, istatistiksel olarak rastgele denir.”
    Bu tanım gerçek rastgele sayı üretecine (TRNG) de uygulanır mı? Uygulanmasını ummalıyız. En azından uzun vadede ya da limitte böyle olmalı. Aksi halde TRNG değildir.
    TRNG uzun vadede “fark edilebilir bir örüntü veya düzenlilik içermeyen bir sayı dizisi” üretmelidir.
    Dolayısıyla istatistiksel rastgeleliğin PRNG anlamına gelmediğini, ama TRNG’ye de uygulanabileceğini söyleyebiliriz.
    Sorun, PRNG’lerin sınırlı bir istatistiksel rastgelelik biçimine sahip olup olmadığını doğrulamak için çok sayıda istatistiksel rastgelelik testi olmasından kaynaklanıyor gibi.
    Bu yüzden PRNG’yi belirtmek için “istatistiksel rastgelelik” yerine “sözde rastgele sayı üreteci” ifadesi daha uygun olurdu. Yine de çok küçük bir kusur.