Gereksinimler ve Ön Hazırlık
Uygulamaya başlamadan önce bilgisayarınızda Node.js'in güncel bir LTS (Long Term Support) sürümünün yüklü olması gerekir. Projenizi başlatmak ve Bcrypt kütüphanesini kurmak için aşağıdaki adımları takip edin.
Terminalinizi açın ve proje klasörünüzde şu komutları çalıştırın:
# Proje klasörünü oluşturun
mkdir node-security-auth
cd node-security-auth
# Projeyi başlatın
npm init -y
# Bcrypt kütüphanesini yükleyin
npm install bcrypt
Bu işlemlerden sonra node_modules klasörü ve package.json dosyanız oluşacaktır. Artık Bcrypt kütüphanesini projenize dahil etmeye hazırsınız.
Bcrypt Nedir ve Neden Kullanmalıyız?
Bcrypt, parolaları şifrelemek için tasarlanmış, "yavaş" bir hashleme algoritmasıdır. Neden "yavaş" olması bir avantajdır? Çünkü saldırganlar "brute-force" (kaba kuvvet) yöntemiyle şifreleri kırmaya çalışırken, algoritmanın yavaşlığı sayesinde saniyede denenebilecek şifre sayısı ciddi oranda düşer.
Bcrypt, her parola için otomatik olarak bir "salt" (tuz) ekler. Salt, parolanın başına veya sonuna eklenen rastgele veridir. Bu sayede aynı şifreye sahip iki kullanıcının veritabanındaki hash değerleri birbirinden tamamen farklı olur. Bu yöntem, "Rainbow Table" (önceden hesaplanmış hash tabloları) saldırılarını imkansız hale getirir.
| Özellik | Bcrypt | MD5 / SHA1 |
|---|---|---|
| Güvenlik Seviyesi | Yüksek (Ayarlanabilir) | Çok Düşük (Kırılabilir) |
| Salt Desteği | Dahili ve Otomatik | Yok (Manuel gerekir) |
| Hız | Yavaş (Güvenli) | Çok Hızlı (Güvensiz) |
Adım Adım Parola Hashleme İşlemi
Kullanıcı kayıt olurken parolasını düz metin (plain text) olarak almamalıyız. Bunun yerine Bcrypt kullanarak bu parolayı geri döndürülemez bir hash değerine dönüştürmeliyiz. Aşağıdaki örnekte, bcrypt.hash metodunun nasıl kullanılacağını görüyoruz.
const bcrypt = require('bcrypt');
const plainPassword = 'kullanici_sifresi_123';
const saltRounds = 12; // İşlem zorluğu (cost factor)
async function hashPassword(password) {
const hash = await bcrypt.hash(password, saltRounds);
console.log('Oluşturulan Hash:', hash);
return hash;
}
hashPassword(plainPassword);
Buradaki saltRounds değeri, algoritmanın ne kadar karmaşık çalışacağını belirler. 12 değeri, günümüz donanımları için güvenlik ve performans arasında ideal bir dengedir.
Güvenlik Doğrulaması: Parola Karşılaştırma
Kullanıcı giriş yapmaya çalıştığında, veritabanından gelen hash değeri ile kullanıcının girdiği parolayı karşılaştırmamız gerekir. Bcrypt, bu işlem için bcrypt.compare metodunu sunar. Bu metod, hash'in içindeki salt değerini otomatik olarak ayıklar ve girilen parolayı aynı salt ile tekrar hashleyerek karşılaştırır.
const bcrypt = require('bcrypt');
async function verifyPassword(inputPassword, storedHash) {
const isMatch = await bcrypt.compare(inputPassword, storedHash);
if (isMatch) {
console.log('Giriş başarılı!');
} else {
console.log('Hatalı parola!');
}
}
// Örnek kullanım:
// verifyPassword('kullanici_sifresi_123', '$2b$12$...');
Bu işlem, veritabanında saklanan hash değerini asla çözmeye çalışmaz; sadece girilen verinin doğruluğunu kanıtlar. Bu, güvenlik açısından en kritik noktadır.
Kritik Güvenlik Uyarısı: Parolaları veritabanında asla düz metin (plain text) olarak tutmayın. Ayrıca, hashleme işlemi sırasında kullanılan
saltRoundsdeğerini çok yüksek tutmak, sunucunuzun CPU kullanımını aşırı artırarak "Denial of Service" (DoS) saldırılarına zemin hazırlayabilir. 10 ile 12 arası değerler çoğu uygulama için yeterlidir.
Yaygın Hatalar ve Debug İpuçları
Geliştiricilerin Bcrypt kullanırken yaptığı en yaygın hata, asenkron işlemleri yönetememektir. Bcrypt fonksiyonları Promise tabanlıdır, bu yüzden async/await yapısını doğru kullanmalısınız.
Hata durumunda şu kontrolleri yapın:
- Hash değerinin veritabanında tam olarak kaydedildiğinden emin olun (bazen karakter limitleri hash'i kesebilir).
saltRoundsdeğerinin bir sayı olduğundan emin olun.- Karşılaştırma yaparken parametre sırasını karıştırmayın (ilk parametre düz metin, ikincisi hash olmalıdır).
// Hatalı Kullanım Örneği
// const isMatch = await bcrypt.compare(storedHash, inputPassword); // Yanlış!
// Doğru Kullanım
const isMatch = await bcrypt.compare(inputPassword, storedHash); // Doğru!
Üretim Ortamı İçin İleri Düzey İpuçları
Uygulamanızı canlıya alırken, hashleme işlemini kullanıcı girişinden bağımsız bir servis katmanında yönetmek mimari açıdan daha temizdir. Ayrıca, bcryptjs kütüphanesini tercih ederseniz, C++ derleyicisine ihtiyaç duymadan saf JavaScript ile çalışabilirsiniz; ancak performans için yerel (native) bcrypt kütüphanesi önerilir.
// Servis katmanı örneği
const authService = {
async register(password) {
return await bcrypt.hash(password, 12);
},
async login(password, hash) {
return await bcrypt.compare(password, hash);
}
};
Sıkça Sorulan Sorular
Bcrypt hash değerini geri çözebilir miyim?
Hayır, Bcrypt tek yönlü bir hashleme algoritmasıdır. Parolanın geri döndürülmesi matematiksel olarak mümkün değildir, bu yüzden unutulan parolalar için "şifre sıfırlama" mekanizması kurmalısınız.
Salt değerini veritabanında ayrıca saklamalı mıyım?
Gerek yoktur. Bcrypt, oluşturduğu hash değerinin içine salt bilgisini zaten gömer. bcrypt.compare fonksiyonu bu bilgiyi otomatik olarak okur.
Neden SHA-256 yerine Bcrypt kullanmalıyım?
SHA-256 çok hızlı bir algoritmadır. Hızlı olması, saldırganların saniyede milyonlarca deneme yapmasına olanak tanır. Bcrypt ise kasıtlı olarak yavaşlatılmıştır.
SaltRounds değerini ne zaman artırmalıyım?
Sunucu donanımınız güçlendikçe veya zaman içerisinde işlemci gücü arttıkça, güvenlik seviyesini korumak için bu değeri 13 veya 14'e çıkarabilirsiniz.
Bcrypt her dilde aynı sonucu mu verir?
Evet, Bcrypt standart bir algoritmadır. Node.js'de oluşturduğunuz bir hash'i, başka bir dildeki (Python, PHP vb.) Bcrypt kütüphanesi ile doğrulayabilirsiniz.
Bcrypt Performans Optimizasyonu ve Ölçeklendirme Stratejileri
Bcrypt, doğası gereği "yavaş" olacak şekilde tasarlanmış bir algoritmadır. Bu yavaşlık, kaba kuvvet (brute-force) saldırılarını zorlaştırmak için kasıtlı bir özelliktir. Ancak, yüksek trafikli bir uygulamada saltRounds değerini çok yüksek tutmak, sunucunuzun CPU kaynaklarını tüketebilir ve kullanıcı deneyimini olumsuz etkileyebilir. Performans ve güvenlik arasındaki dengeyi kurmak için aşağıdaki stratejileri izleyebilirsiniz.
Asenkron İşlemlerin Önemi
Node.js tek iş parçacıklı (single-threaded) bir yapıya sahiptir. Eğer bcrypt.hashSync gibi senkronize metotları kullanırsanız, hashleme işlemi bitene kadar Event Loop tamamen bloke olur. Bu durum, aynı anda siteye giren diğer kullanıcıların yanıt alamamasına neden olur. Her zaman asenkron metotları tercih etmelisiniz.
// Yanlış: Event Loop'u bloke eder
const hash = bcrypt.hashSync(password, 12);
// Doğru: Event Loop'u bloke etmez
bcrypt.hash(password, 12, (err, hash) => {
if (err) throw err;
// İşleme devam et
});
Hashleme İşlemlerini Worker Thread'lere Taşıma
Eğer uygulamanızda çok yoğun parola doğrulama trafiği varsa, ana işlem hattını (Main Thread) rahatlatmak için worker_threads modülünü kullanarak hashleme işlemlerini arka planda farklı bir thread üzerinde çalıştırabilirsiniz. Bu, özellikle CPU yoğunluklu işlemlerde uygulamanızın yanıt süresini (latency) ciddi oranda iyileştirir.
Bcrypt Uygulamalarında Güvenlik Testleri ve Doğrulama
Uygulamanızı canlıya almadan önce, Bcrypt yapılandırmanızın doğru çalıştığından emin olmak için birim testleri (unit tests) yazmak hayati önem taşır. Özellikle saltRounds değerinin sisteminizdeki donanım ile uyumlu olup olmadığını test etmelisiniz.
Jest ile Parola Doğrulama Testi
Aşağıdaki örnek, Jest kütüphanesi kullanarak bir parola hashleme ve doğrulama sürecinin nasıl test edileceğini göstermektedir:
const bcrypt = require('bcrypt');
describe('Parola Güvenlik Testleri', () => {
test('Parola hashlenmeli ve doğru parola ile eşleşmeli', async () => {
const password = 'GuvenliSifre123!';
const hash = await bcrypt.hash(password, 10);
const isMatch = await bcrypt.compare(password, hash);
expect(isMatch).toBe(true);
});
test('Yanlış parola ile doğrulama başarısız olmalı', async () => {
const password = 'GuvenliSifre123!';
const hash = await bcrypt.hash(password, 10);
const isMatch = await bcrypt.compare('YanlisSifre', hash);
expect(isMatch).toBe(false);
});
});
Güvenlik Denetimi ve Bağımlılık Yönetimi
Bcrypt kütüphanesinin güncel kalması, olası güvenlik açıklarına karşı korunmanızı sağlar. Projenizdeki bağımlılıkları düzenli olarak denetlemek için şu komutu kullanmayı alışkanlık haline getirin:
# Projenizdeki güvenlik açıklarını tarar
npm audit
# Güvenlik açıklarını otomatik olarak düzeltmeye çalışır
npm audit fix
Unutmayın ki Bcrypt tek başına bir "gümüş kurşun" değildir. Parola güvenliği; veritabanı şifrelemesi, HTTPS kullanımı, rate limiting (istek sınırlama) ve çok faktörlü kimlik doğrulama (MFA) gibi katmanlı bir güvenlik stratejisinin sadece bir parçasıdır.
Sonuç
Node.js ile Bcrypt kullanarak şifreleme yapmak, uygulamanızın güvenliğini sağlamak için atabileceğiniz en önemli adımdır. Bu rehberde hashleme mantığını, saltRounds kullanımını ve güvenli karşılaştırma yöntemlerini öğrendiniz. Bir sonraki adım olarak, bu yapıyı bir JWT (JSON Web Token) mekanizması ile birleştirerek güvenli bir oturum yönetimi oluşturmayı araştırmanızı öneririm.
Sorumluluk Reddi: Bu makalede paylaşılan kodlar eğitim amaçlıdır. Yazılım güvenliği sürekli güncellenen bir alandır. Uygulamanızı yayına almadan önce bağımlılıklarınızı (npm audit) kontrol etmeyi ve güvenlik duvarı (WAF) gibi ek katmanlar kullanmayı unutmayın.


Yorumlar (0)
Yorum Yaz