Kısa cevap
Bilgisayar talimatları birebir uygular, yani yoktan rastgelelik üretemez. Ya rastgelelik testlerini geçen sayılar hesaplar (sözde rastgele sayı üreteci, PRNG) ya da fiziksel olarak öngörülemeyen bir şeyi ölçüp işler (gerçek ya da donanımsal rastgele kaynak). Modern sistemler ikisini birleştirir: işletim sistemi öngörülemeyen gürültüyü toplar ve bununla kriptografik olarak güvenli bir PRNG'yi (CSPRNG) besler; bu üreteç de gerektiği kadar sayı üretir.
Bu sayfadaki üreteç tarayıcının Web Crypto API üzerinden sunduğu güvenli kaynağı kullanır ve sonucu senin aralığına sapmasız çevirir. En küçük ve En büyük değerleri yaz, Kaç tane alanını seç ve Üret'e bas.
Burada dene: Rastgele sayı üretici
Aracın tam sayfasını açSözde rastgele üreteçler ve seed
Bir PRNG içinde bir durum (state) tutar. Her sayı istediğinde bu durumu sabit bir formülle karıştırır ve sonucun bir kısmını verir. En basit klasik tasarım olan doğrusal eşlik üreteci (LCG), bir sonraki durumu (a çarpı durum artı c) mod m olarak hesaplar. Python'daki random modülünün varsayılanı olan Mersenne Twister ya da xorshift ailesi gibi daha iyi tasarımlar çok daha kaliteli diziler üretir; Mersenne Twister ancak 2 üzeri 19.937 eksi 1 adımdan sonra kendini tekrar eder.
Seed başlangıç durumudur. Aynı seed her zaman aynı diziyi verir. Bu birçok durumda kusur değil özelliktir: bir bilim insanı simülasyonu birebir tekrar çalıştırabilir, bir oyun kısa bir seed koduyla koca bir dünyayı yeniden kurabilir, bir test hatayı tekrar üretebilir. Ama program seed'i saniye cinsinden şu anki saat gibi tahmin edilebilir bir şeyden alıyorsa saldırgan olası tüm seed'leri deneyip sayıları yeniden oluşturabilir.
Sözde rastgele ile kriptografik olarak güvenli arasındaki fark
Hızlı, genel amaçlı PRNG'ler istatistik açısından iyidir ama öngörülebilirdir: yeterince çıktıyı gören biri iç durumu yeniden kurup sonraki her sayıyı tahmin edebilir. Oyundaki bir parçacık efekti için bu sorun değildir; şifre, çekiliş ya da güvenlik anahtarı için sorundur.
| Tür | Sayılar nereden gelir | Tahmin edilebilir mi? | Tipik kullanım |
|---|---|---|---|
| Basit PRNG (LCG, xorshift, Mersenne Twister) | Bir formül ve bir seed | Evet, seed'den ya da yeterli çıktıdan | Simülasyon, oyun, grafik |
| CSPRNG | Sistem gürültüsüyle beslenen ve yenilenen bir formül | Hayır, pratikte değil | Şifre, anahtar, çekiliş, token |
| Donanımsal RNG | Isıl gürültü ya da zamanlama titreşimi gibi fiziksel gürültü | Hayır | İşletim sisteminin havuzunu beslemek |
Bilgisayarlar gerçek rastgeleliği nereden bulur?
İşletim sistemleri küçük ve öngörülemeyen olayları toplar: kesmelerin tam zamanlaması, disk ve ağ trafiği ve birçok modern işlemcide bulunan, elektriksel gürültüyü örnekleyen özel donanım üreteçleri. Bu entropi bir havuzda karıştırılır ve bir CSPRNG'yi başlatmak ve düzenli aralıklarla yeniden beslemek için kullanılır. Linux bunu getrandom ve /dev/urandom ile, Windows kendi şifreleme işlevleriyle sunar.
Bazı servisler tanıtım ya da ek güvence için daha da ileri gider. Random.org atmosferdeki radyo gürültüsünü kullanır, Cloudflare de entropi kaynaklarından biri olarak bir lav lambası duvarını kameraya çekmesiyle ünlüdür. Günlük ihtiyaçlar için işletim sisteminin üreteci şifreleme anahtarlarına bile yetecek kadar güçlüdür.
Tarayıcılar güvenli rastgele sayıyı nasıl üretir?
JavaScript'te iki seçenek var. Math.random() hızlı bir PRNG'den 0 ile 1 arasında bir sayı döndürür (güncel motorlar xorshift türü algoritmalar kullanır). Animasyonlar için yeterlidir ama öngörülemez olacak şekilde tasarlanmamıştır ve standart güvenlik konusunda hiçbir söz vermez.
crypto.getRandomValues() ise bir diziyi, işletim sisteminden beslenen tarayıcı CSPRNG'sinden gelen rastgele baytlarla doldurur. Tüm modern tarayıcılarda vardır, internetsiz çalışır ve şifre üreteçlerinin ve anahtar üreten kodun kullanması gereken yöntem budur. Tek çağrı en fazla 65.536 bayt döndürebilir, büyük işler onu tekrar tekrar çağırır. Bu üreteç de Anyfeat'teki yazı tura, zar, çark ve kura çekme araçları gibi crypto.getRandomValues kullanır.
rand() % n neden sapmalı olabilir?
Üreteç sana sabit bir aralıkta ham değerler verir, örneğin 0 ile 255 arasında bir bayt. 0 ile 5 arasında bir sayı elde etmenin akla gelen yolu, 6'ya bölümünden kalanı almaktır (değer % 6). Sorun şu: 256 değer 6 gruba eşit bölünmez. 256, 42 kere 6 artı 4'tür; bu yüzden 0 ile 3 arası kalanlar 43'er kez, 4 ve 5 ise sadece 42'şer kez çıkar. Bazı sonuçlar diğerlerinden yaklaşık yüzde 2,4 daha olası olur. Buna modülo sapması denir.
32 bitlik değerler ve küçük bir aralıkta sapma çok küçülür, ama geniş aralıklarda büyür. Standart çözüm reddetme yöntemidir: ham aralığa sığan n'in en büyük katını bul (bayt örneğinde 252), bunun ve üstündeki her ham değeri at ve yeniden çek. Kalan değerler aralığa eşit dağılır. Bu üreteç 32 bitlik değerler çeker ve eşit bölünmeyen kuyruğu reddeder; aralığındaki her sayının ihtimali tam olarak eşittir.
Benzer bir hata da güvenlik gereken yerlerde Math.floor(Math.random() * n) kullanmaktır. Yuvarlama çoğu aralık için sorun değildir ama kaynak öngörülebilirdir; şifrelerde ya da para söz konusu olan çekilişlerde kullanılmamalıdır.
Tekrarsız sayılar, karıştırma ve sık yapılan hatalar
- Tekrarsız sayılar: tekrar olmadan çekmek için tüm aralığı Fisher Yates algoritmasıyla karıştırıp ilk k tanesini al ya da çek ve tekrarları at. Tekrarsız işaretliyken bu üreteç tam olarak bunu yapar ve aralık istenen adet için küçükse söyler.
- Sapmalı karıştırma: bir listeyi rastgele karşılaştırma fonksiyonuyla sıralamak düzgün bir karıştırma vermez. Fisher Yates kullan.
- Çok sık seed vermek: bir döngü içinde PRNG'ye saati seed olarak vermek aynı sayıyı art arda birçok kez üretebilir.
- Ondalıklar: rastgele bir kesri ölçekleyerek ondalık sayı seçmek uç değerleri daha az olası yapabilir. Bu araç bunun yerine tam sayıda adım çeker (2 basamak için yüzde birler), böylece iki uç da eşit şansla dahil olur.
- Desen olmamasını beklemek: gerçek rastgele çıktıda seriler ve tekrarlar olur. Art arda iki kez 7 görmek üretecin bozuk olduğunu göstermez.