İçeriğe geç
Rastgelelik

Kriptografide Rastgelelik: Math.random Neden Güvenli Değil?

Güncellendi: Son kontrol: Eylül 2026 5 dk okuma

Kısaca cevap

Kriptografide rastgele değerlerin yalnızca dağınık görünmesi yetmez, tahmin edilemez olmaları gerekir. Math.random(), Python random veya C# Random gibi sıradan üreteçler istatistiksel olarak düzgün görünse de çıktıları tahmin edilebilir; bu yüzden anahtar, şifre veya doğrulama kodu için güvenli değildir. Kriptografik rastgele sayı üretme işini işletim sisteminin CSPRNG'sine bağlanan crypto.getRandomValues(), secrets, RandomNumberGenerator, SecureRandom ve random_int() gibi işlevlere bırakın.

Bu sayfada

Kriptografi neden rastgeleliğe ihtiyaç duyar?

Modern şifreleme algoritmaları herkes tarafından bilinir; gizli olan yalnızca anahtardır. Saldırgan anahtarı tahmin edebiliyorsa, AES-256 gibi güçlü bir algoritma kullanmanızın hiçbir önemi kalmaz. Kriptografide rastgelelik bu yüzden bir ayrıntı değil, güvenliğin temelidir. Rastgele üretilmesi gereken başlıca değerler şunlardır:

  • Anahtarlar: AES anahtarları, RSA için seçilen asal sayılar ve eliptik eğri özel anahtarları.
  • IV ve nonce değerleri: NIST'e göre CBC modunda IV tahmin edilemez olmalıdır; GCM modunda ise aynı anahtarla aynı IV'nin tekrar kullanılması güvenliği neredeyse tamamen ortadan kaldırabilir.
  • Tuzlar (salt): Şifreleri saklarken her kullanıcıya eklenen rastgele değerler; ayrıntılar hash ve şifre saklama yazısında.
  • Belirteçler (token): Oturum çerezleri, şifre sıfırlama bağlantıları, API anahtarları, e-posta doğrulama kodları.
  • Şifreler ve PIN'ler: Bir şifre üreticisinin ürettiği şifre, yalnızca kullandığı kaynak kadar güçlüdür.

Bu değerlerin ortak noktası, saldırganın onları görmeden önce tahmin edememesi gerektiğidir. Rastgeleliğin genel tanımı için Rastgelelik Nedir? yazısına bakabilirsiniz.

Sıradan PRNG neden yetmez?

Bilgisayarlar belirlenimci çalıştığı için çoğu rastgele sayı, bir başlangıç değerinden (tohum) formülle hesaplanır. Bu tür üreteçlere PRNG (sözde rastgele sayı üreteci) denir. Oyun ve simülasyon için tasarlanmış bir PRNG'nin hedefi hızlı olmak ve istatistik testlerinden geçmektir; saldırgana karşı dayanıklı olmak değil.

Sorun iki yerden çıkar. Birincisi, tohum tahmin edilebilirse (ör. o anki saat) dizinin tamamı yeniden üretilebilir. İkincisi, bazı PRNG'lerin iç durumu yeterince çıktı gözlemlenerek hesaplanabilir; bundan sonra üretilecek her sayı bilinir. Python belgeleri, random modülünün kullandığı Mersenne Twister için "kriptografik amaçlar için tamamen uygun değil" der. Java belgesi de java.util.Random örneklerinin kriptografik olarak güvenli olmadığını belirtir.

Eski bazı kaynaklarda sıradan sözde rastgele üreteçlerin "pratikte kriptografi için yeterince güvenli" olduğu yazar. Bu yanlıştır: istatistiksel olarak düzgün görünmek, tahmin edilemez olmak anlamına gelmez. Üreteç türlerinin ve tohum kavramının ayrıntılı anlatımını Bilgisayarlar rastgele sayıyı nasıl üretir? yazısında bulabilirsiniz.

CSPRNG nedir?

CSPRNG (kriptografik olarak güvenli sözde rastgele sayı üreteci), yine bir algoritmadır ama iki farkı vardır. Birincisi, işletim sisteminin donanım olaylarından ve varsa işlemcinin donanım üretecinden topladığı öngörülemez verilerle (entropi) tohumlanır. İkincisi, önceki çıktıların tamamı bilinse bile sonraki çıktının tahmin edilemeyeceği şekilde tasarlanır. NIST'in SP 800-90A standardında tanımlanan CTR_DRBG ve HMAC_DRBG gibi yapılar bu türdendir.

Uygulamaların kendi CSPRNG'sini yazması gerekmez; işletim sistemi hazır bir kaynak sunar:

  • Windows: BCryptGenRandom. Microsoft'a göre varsayılan sağlayıcı NIST SP 800-90'daki CTR_DRBG yapısıyla uyumludur.
  • Linux: getrandom() sistem çağrısı (Linux 3.17 ile geldi) ve /dev/urandom. getrandom(), çekirdeğin kaynağı henüz yeterince tohumlanmamışsa açılışta bekler; sonrasında her istekte güvenli baytlar döndürür.

Programlama dillerinin güvenli işlevleri de arka planda bu kaynaklara bağlanır.

Math.random güvenli mi?

Hayır. MDN belgeleri açıkça Math.random() işlevinin kriptografik olarak güvenli sayılar sağlamadığını ve güvenlikle ilgili hiçbir iş için kullanılmaması gerektiğini söyler; yerine Web Crypto API'deki crypto.getRandomValues() önerilir. Bu işlev, işletim sisteminin yüksek entropili kaynağıyla tohumlanan bir üreteç kullanır ve verdiğiniz tam sayı dizisini güvenli değerlerle doldurur:

// Güvensiz: tahmin edilebilir
const zayifKod = Math.floor(Math.random() * 1000000);

// Güvenli: 16 baytlık (128 bit) rastgele belirteç, onaltılık gösterimde
const bayt = crypto.getRandomValues(new Uint8Array(16));
const belirtec = Array.from(bayt, b => b.toString(16).padStart(2, "0")).join("");

Tek çağrıda en fazla 65.536 bayt istenebilir. Sonucu bir aralığa indirgerken mod sapmasından kaçınmak da gerekir; bunu nasıl yapacağınızı JavaScript ile güvenli rastgele şifre üretme yazısında örnek kodla anlatıyoruz. Web Crypto ile şifreleme anahtarı üretecekseniz MDN, getRandomValues() yerine crypto.subtle.generateKey() kullanılmasını önerir.

Dillere göre güvenli ve güvensiz işlevler

DilGüvenlik için KULLANMAYINKriptografik (güvenli) seçenek
JavaScript (tarayıcı)Math.random()crypto.getRandomValues()
Pythonrandom modülüsecrets modülü (3.6+), random.SystemRandom
C# / .NETSystem.RandomRandomNumberGenerator (ör. GetInt32)
Javajava.util.Randomjava.security.SecureRandom
PHPrand(), mt_rand()random_int(), random_bytes()

Aşağıda her dilde güvenli kullanımın kısa bir örneği var:

# Python: secrets modülü
import secrets
belirtec = secrets.token_urlsafe(32)   # 32 baytlık rastgelelikten URL'de kullanılabilir belirteç
kod = secrets.randbelow(1000000)       # 0 ile 999999 arasında sayı
// C#: RandomNumberGenerator (bu iki statik metot birlikte .NET 6 ve sonrasında var)
using System.Security.Cryptography;
int kod = RandomNumberGenerator.GetInt32(0, 1000000);
byte[] anahtar = RandomNumberGenerator.GetBytes(32);
// Java: SecureRandom
import java.security.SecureRandom;
SecureRandom rng = new SecureRandom();
byte[] anahtar = new byte[32];
rng.nextBytes(anahtar);
// PHP: random_int ve random_bytes (PHP 7 ve sonrası)
$kod = random_int(0, 999999);
$belirtec = bin2hex(random_bytes(32));

Python belgesi, belirteçler için 32 baytlık (256 bit) rastgeleliği tipik kullanımlar için yeterli görür. .NET'teki GetInt32, basit mod işleminin yaratacağı sapmayı önlemek için uygun olmayan değerleri atıp yeniden çekme yöntemini kullanır. Tam şifre üretici örnekleri için Python ile güvenli rastgele şifre üretme ve C# ile rastgele şifre üretici yazılarına bakabilirsiniz.

Gerçek bir örnek: Debian OpenSSL açığı (2008)

Zayıf rastgeleliğin sonuçlarını gösteren en bilinen olaylardan biri Debian'da yaşandı. Eylül 2006'da Debian'ın OpenSSL paketine yapılan ve yalnızca Debian'a özgü hatalı bir değişiklik, rastgele sayı üretecinin girdisini neredeyse tamamen yok etti. Debian'ın açıklamasına göre üreteç yalnızca işlem numarasıyla (PID) tohumlanıyordu; her işlemci mimarisi için yalnızca 32.767 farklı rastgele sayı dizisi mümkündü.

Sorun 13 Mayıs 2008'de CVE-2008-0166 koduyla duyuruldu. Bu sürede Debian ve Ubuntu sistemlerinde üretilen SSH anahtarları, OpenVPN anahtarları, DNSSEC anahtarları, SSL/TLS sertifika anahtarları ve oturum anahtarları tahmin edilebilir hâle gelmişti. Debian, etkilenen sürümlerle üretilmiş tüm anahtarların sıfırdan yeniden oluşturulmasını istedi. Algoritmalar ve anahtar uzunlukları doğruydu; eksik olan tek şey tahmin edilemezlikti.

Kriptografik rastgele sayı seçici ne zaman gerekir?

Her rastgele seçim kriptografik bir kaynak gerektirmez. Bir oyunda düşmanın nereden çıkacağını veya bir sunumda slayt sırasını belirlerken sıradan bir üreteç yeterlidir; sonucu birinin tahmin etmesi kimseye zarar vermez. Ölçüt basittir: sonucu önceden tahmin eden ya da etkileyen biri bundan çıkar sağlayabiliyorsa, kriptografik bir kaynak kullanın.

Şifre, PIN, doğrulama kodu ve anahtar bu gruba girer. Ödüllü bir çekiliş, sınav yerleşimi veya kura gibi adaletin önemli olduğu seçimlerde de kriptografik bir seçici, sonucun dışarıdan tahmin edilmesini ve yönlendirilmesini pratikte imkânsız kılar. Yine de hiçbir üreteç, seçim sürecinin kendisinin şeffaf ve denetlenebilir olması ihtiyacını ortadan kaldırmaz.

Yazılımcılar için kontrol listesi

  • Güvenlikle ilgili her değeri (anahtar, IV, tuz, belirteç, şifre, doğrulama kodu) dilinizin kriptografik işleviyle üretin.
  • Üreteci kendiniz tohumlamayın ve saati, işlem numarasını veya kullanıcı adını tohum olarak kullanmayın.
  • Kendi "karıştırma" algoritmanızı yazmayın; işletim sisteminin test edilmiş kaynağına güvenin.
  • Aralığa indirgerken mod sapmasına dikkat edin; mümkünse secrets.randbelow, RandomNumberGenerator.GetInt32 veya random_int gibi hazır işlevleri kullanın.
  • GCM gibi modlarda aynı anahtarla aynı IV'yi asla tekrar kullanmayın.
  • Üretilen gizli değerleri günlük (log) dosyalarına yazmayın.

Sitemizdeki şifre üretici ve diğer araçlar tarayıcınızın crypto.getRandomValues() kaynağını kullanır; üretilen değerler cihazınızdan çıkmaz ve sunucuya gönderilmez. Rastgele bir sayıya ihtiyacınız varsa rastgele sayı üretici aracı da aynı kaynakla çalışır.

Sık sorulan sorular

Math.random güvenli mi?

Oyun, animasyon veya rastgele renk seçmek için sorun yoktur, ama güvenlik için güvenli değildir. MDN belgeleri Math.random() işlevinin kriptografik olarak güvenli sayılar üretmediğini ve güvenlikle ilgili hiçbir iş için kullanılmaması gerektiğini açıkça belirtir. Şifre, doğrulama kodu veya anahtar üretirken crypto.getRandomValues() kullanılmalıdır.

Kriptografik rastgele sayı nasıl üretilir?

Kendi algoritmanızı yazmak yerine işletim sisteminin kriptografik üretecine bağlanan hazır işlevleri kullanın. Tarayıcıda crypto.getRandomValues(), Python'da secrets modülü, C#'ta RandomNumberGenerator, Java'da SecureRandom, PHP'de random_int() ve random_bytes() bu iş için tasarlanmıştır.

CSPRNG nedir?

CSPRNG, kriptografik olarak güvenli sözde rastgele sayı üretecidir. Sıradan bir PRNG gibi algoritmayla çalışır, ancak işletim sisteminin topladığı öngörülemez verilerle tohumlanır ve önceki çıktılar bilinse bile sonraki çıktının tahmin edilemeyeceği şekilde tasarlanır. Anahtar, şifre ve oturum kodu üretiminde yalnızca CSPRNG kullanılmalıdır.

Python'da random mi secrets mi kullanmalıyım?

Güvenlikle ilgili her değer için secrets kullanın. Python belgelerine göre random modülü modelleme ve simülasyon için tasarlanmıştır ve Mersenne Twister algoritması kriptografik amaçlar için tamamen uygun değildir. secrets modülü Python 3.6 ile gelmiştir ve işletim sisteminin güvenli kaynağını kullanır.

Kriptografik rastgele sayı seçici ne işe yarar?

Bir listeden veya aralıktan, sonucu kimsenin önceden tahmin edemeyeceği biçimde seçim yapar. Çekiliş, kura veya şifre üretimi gibi işlerde sıradan bir üreteç yerine kriptografik bir kaynak kullanmak, sonucu dışarıdan yönlendirmeyi veya tahmin etmeyi pratikte imkânsız kılar. Sitedeki rastgele sayı üretici ve şifre üretici bu yöntemle çalışır.