- Go 1.22,
math/randvemath/rand/v2için varsayılan rastgele sayı kaynağını kriptografik olarak güçlü bir üreteç ile değiştirerek,crypto/randkullanılması gereken yerlerde yapılan hataların etkisini büyük ölçüde azaltıyor - Eski Go 1 üreteci, 607 adet
uint64durum 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/v2iç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/randvemath/rand/v2için varsayılan olarak kriptografik olarak güçlü sözde rastgele sayı üreteci kullanacak şekilde değiştirildi - Amaç, geliştiricilerin
crypto/randgerekli olan yerlerde yanlışlıklamath/randkullanması 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 rastgelelikcrypto/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
srandverandiş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
uint64içerenvecslice'ından oluşurvec[606]“tap”tirvec[334]“feed”dir- Sonraki değeri üretirken tap ve feed toplanarak
xoluşturulur,xfeed 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ı
vecdoldurulup 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
- Aynı
- Go 1 üreteci güvenlik amaçlı tasarlanmamıştır ve üretilen sayıların kalitesi de başlangıç
veckurulumuna 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
scrambleişleviyle 128 bitlik durumu 64 bit çıktıya indirger - Go, teklif tartışmaları sırasında O’Neill'ın önerisine dayanarak çarpma tabanlı bir
scramblekullanmış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
- Go 1 üreteci: 607 adet
- 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/randomgibi 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/randpaketi işletim sistemi farklılıklarını gizler ve aynı arayüz olanrand.Readiş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.Sourceolarak 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
uint32olarak 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/v2paket işlevleri her zaman ChaCha8Rand kullanır- Örnek:
rand.N,rand.Float64
- Örnek:
math/randpaket 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
- Örnek:
- 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.ChaCha8oluş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/randiçindekiReaddeprecated olduğunda, bazı geliştiricilerin anahtar malzemesi üretimi gibicrypto/randgerektiren yerlerdemath/randkullandığı 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/randkullanmak 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/randiçin yeterli görünebilir - Ancak
math/randmevcut 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 sonrakiuint64değerini döndürmekN(1000):[0, 1000)aralığında rastgele bir sayı döndürmek
- 64 bit x86 yongada
GOARCH=386ile 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; ancakGo 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/v2algoritmasını kullanır
- Go 1'de
- 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/randyerine yanlışlıklamath/randkullanılmasından doğan yaygın sorunu azaltmak içinmath/rand'ın kendisini güçlendirmektir - npm
keypairpaketi gibi, Web Crypto API olmadığında JavaScriptMath.randomile 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
Hacker News görüşleri
Yazıda anlatıldığı gibi, rclone’da tam olarak bu hatayı yaptık
crypto/randiçindekiRead’i kullanan kodu refactor ederken import otomatik olarak değişti; muhtemelenmath/randkullanan kodla karışıncagoimportsbunumath/randolarak değiştirdiSonuç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
goimports,crypto/rand’ı tercih edecek şekilde değiştirildiği için refactor sırasında tam olarak ne olduğunu kesin bilemiyorumMuhtemelen aynı dosyada
math/rand’a özgü API kullanan kod yer almış olabilirhttps://go-review.googlesource.com/24847
Her hâlükârda bu tür şeylerin temizleniyor olmasına sevindim
math/randkullanı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österiyortext/templatevehtml/templateda 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 örneklerinmath/randkullandığını da gördümDaha da kötüsü, hepsi parolayı üretmeden hemen önce seed’i mevcut zamana göre sıfırlıyor
Kodumuzda birinin
math/randkullandığını fark ettikten sonra, bunu nereden kopyalamış olabileceğini merak edip araştırırken öğrendimgoimportsneredeyse en başından berimath/rand.Readvecrypto/rand.Readiçin özel işlem yapıyorduAncak 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 ediliyorBelki de o döneme denk gelmiş olabilir
"PredictableRand"gibi isimde bir API çağrısı sunmak o kadar zor olmasa gerekGeç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
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
crypto/rand’ın kesinlikle gerekli olduğu bir yerdemath/randkullanmışlığım varBunun 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 sessizcemath/randimport’u eklediğini fark etmedimO zamandan beri yanlış
rand’ın otomatik import edilmesini önlemek içincrypto/rand’ıcryptorandtakma adıyla import ediyorumBu 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
2016’da
goimports,math/randyerinecrypto/rand’ı tercih edecek şekilde değiştirildi (https://go-review.googlesource.com/24847); bu da Go için VSCode desteği çıkmadan önceydi2020'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
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 kullananmt_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
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/randiçindekiRead()e harcandığını ve MacBook'umda sistem çağrıları yaptığını gördümKütüphaneyi
math/randiçindekiRead()i kullanacak şekilde yamalayınca performans ciddi biçimde iyileştimath/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üyordumBu 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/randfiilenmath/randden ayırt edilemeyecek durumdaysa, ne âlâ :-)Durum boyutu hâlâ nispeten büyük (64 bayta karşı 16 bayt), ama
mt19937ya da eski Go PRNG gibi şeylerden çok daha iyiCSPRNG ç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ı
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/randokuması 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,ddde sorunsuz çalışıyorÇoğu kullanım senaryosu için
Must/panictarzı bir API'nin varsayılan olarak daha uygun olup olmadığını da merak ediyorumAyrıca Python'ın
secretspaketine (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?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:
gosecve onun uzantısı olangolangci-lint,math/randkullanımını uyarıyorhttps://github.com/securego/gosec/blob/d3b2359ae29fe344f4df5...
math/rand/v2de en sevdiğim şeylerden biri, iş yerindenolintyönergeleri ve ardından gelen PR tartışmaları olmadan kullanabilmekGü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/randkullanılmalı ve burada açıklanan iyileştirme, birininmath/rand/v2yi uygunsuz biçimde kullanması durumunda bir güvenlik ağı anlamına mı geliyor?math/rand/v2ideal değil, ama artık yanlışlıklacrypto/randkullanılması gereken yerde kullanıldığında hemen ölümcül bir güvenlik açığına dönüşmüyorYazıda da şöyle deniyor
crypto/randkullanmak 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ıklamath/randkullanmak artık bir güvenlik felaketi değildirEn 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.
İ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/randfonksiyonları 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
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.