Read in 13 min read, written by Emre Cebeci
TABLE OF CONTENTS
Argon2 vs bcrypt: .NET’te Temel Parola Hashleme Rehberi
Giriş: Neden Parola Hashleme?
Kullanıcı parolalarını düz metin (plain-text) olarak saklamak ciddi bir güvenlik açığıdır. Bir veri ihlali durumunda, parolalar doğrudan kötü niyetli kişilerin eline geçebilir. Parola hashleme, bu riski ortadan kaldırmak için kullanılır. Parola, tek yönlü (one-way) fonksiyonlardan geçirilir ve geri çözülemez hale gelir.
Algoritmalara Genel Bakış
bcrypt Nedir?
bcrypt, Blowfish algoritması temelli bir parola hashleme fonksiyonudur. 1999 yılında tanıtılmıştır ve yıllarca endüstri standardı olmuştur. Ana parametresi cost
değeridir. Bu değer, hash fonksiyonunun kaç kez çalıştırılacağını belirler ve doğrudan işlem süresini etkiler.
Avantajları:
- Kullanımı basittir
- Legacy sistemlerde güvenli kabul edilir.
Dezavantajları:
- Hash üretimi sırasında bellek tüketimi düşüktür → Bu da özellikle GPU ile yapılan brute-force saldırılarına karşı daha savunmasız olmasına neden olur
- Sadece
cost
parametresi alabilir, parametre esnekliği düşüktür.
Argon2 Nedir?
Argon2, 2015'te Password Hashing Competition (PHC) kazananı olan modern bir algoritmadır. 3 türe sahiptir:
- argon2d: GPU saldırılarına dayanıklıdır ancak side-channel’a açık olabilir
- argon2i: Side-channel’a karşı dayanıklı, bellek erişimi rastgele yapılır
- argon2id: argon2d ve argon2i’nin hibrit biçimidir. Hem güvenli hem dengelidir → önerilen türdür
Avantajları:
- Bellek ve CPU dostu, özelleştirilebilir parametrelerle çalışır
- GPU gücü ile yapılan saldıralara karşı daha dayanıklı
- Modern güvenlik standartlarına uygundur.
Dezavantajları:
- bcrypt’a göre başlangıçta doğru parametrelerle yapılandırılması gerekir
- Farklı ortamlarda tutarlılık sağlamak için ayarların dikkatle seçilmesi gerekir.
OWASP Tavsiyeleri
OWASP’in Parola Hashleme Tavsiyesi
Bu karşılaştırmayı yaparken OWASP’in önerilerini temel aldım. OWASP diyor ki:
Yani işin özü şu: parola hashlemek sadece parolayı gizlemek değil; veri tabanı ele geçirilirse saldırganın işini iyice zorlaştırmak demektir.
Bu noktada Argon2, modern ve güçlü bir algoritma olarak öne çıkıyor. Eğer Argon2 kullanılamıyorsa, OWASP scrypt’i öneriyor.
Yine de, bcrypt hâlâ birçok legacy sistemde de facto standart. Bu yüzden bu yazıda Argon2 ile bcrypt’i, OWASP’in önerdiği ayarlarla karşılaştıracağım.
Benchmark Sonuçları
BenchmarkDotNet paketiyle gerçekleştirdiğim testlerde, Argon2id algoritması OWASP’nin önerdiği minimum ayarlarla çalıştırıldığında bcrypt’e kıyasla yaklaşık %47.5 daha yavaş (85.08 ms vs. 57.70 ms) sonuç vermektedir. Ancak lane
değeri 2 yapıldığında bu fark %3.5 seviyelerine (59.75 ms vs. 57.70 ms) kadar düşmektedir.
Bu da gösteriyor ki: doğru parametre seçimi kritik öneme sahiptir. Yanlış yapılandırmalar ya performansı düşürebilir ya da güvenlik seviyesini zayıflatabilir.
Testte kullanılan Argon2CustomHash
methodunu düzenleyerek, farklı ayarlarla performans karşılaştırması yapabilir ve kendi sisteminize en uygun konfigürasyonu belirleyebilirsiniz.
.NET’te Uygulamak
.NET’te bcrypt ve Argon2 Paketlerinin Kurulumu
bcrypt için BCrypt.Net-Next paketini kullandım.
bashdotnet add package BCrypt.Net-Next
Argon2 için Isopoh’un paketini kullandım
bashdotnet add package Isopoh.Cryptography.Argon2
bcrypt ile Parola Hashleme & Doğrulama
c#public class PasswordHasher
{
public string BcryptHash(string password)
{
return BCrypt.Net.BCrypt.HashPassword(password, workFactor: 12); // OWASP minimum 10 önerir
}
public bool BcryptVerify(string password, string hashedPassword)
{
return BCrypt.Net.BCrypt.Verify(password, hashedPassword);
}
}
Argon2id ile Parola Hashleme & Doğrulama
c#using Isopoh.Cryptography.Argon2;
public class PasswordHasher
{
// Hashleme (OWASP Ayarları: 19 MiB bellek, 2 iterasyon, 1 paralellik)
public static string Argon2Hash(string password)
{
// Rastgele salt olustur
var salt = GenerateSalt(16);
var argon2Config = new Argon2Config
{
Type = Argon2Type.HybridAddressing, // Argon2id
Password = System.Text.Encoding.UTF8.GetBytes(password),
MemoryCost = 19456, // 19 MiB (19456 KB)
TimeCost = 2,
Lanes = 1, // Paralellik
Threads = 1, // Thread sınırı
HashLength = 32,
Salt = salt
};
var argon2A = new Argon2(argon2Config);
using (SecureArray<byte> hashA = argon2A.Hash())
{
return argon2Config.EncodeString(hashA.Buffer);
}
}
// Doğrulama
public bool Argon2Verify(string password, string hashedPassword)
{
return Argon2.Verify(hashedPassword, password);
}
// Salt oluşturma
private static byte[] GenerateSalt(int size = 16)
{
var salt = new byte[size];
using (var rng = System.Security.Cryptography.RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
return salt;
}
}
Gelişmiş Konular
Password Rehashing: Parolaları Sessizce Yeniden Hashlemek
Yeni algoritma ya da parametrelerle daha güvenli veya hızlı bir parola hashleme yapılandırmasına geçtiğinizde, eski parolalar hâlâ eski ayarlarla saklanmaya devam eder. Çünkü hash işlemi tek yönlüdür — yani bir parolayı yeniden yapılandırmak için onu tekrar düz metin hâlinde bilmeniz gerekir. Ama veritabanınızda sadece hash vardır, parola yoktur.
İşte bu noktada devreye “password rehashing” girer. Kullanıcı sisteme giriş yaptığında, yani parolasını doğru şekilde girdiğinde, bu fırsatı değerlendirip parolayı yeni algoritma veya parametrelerle yeniden hashleyebilirsiniz. Bu işlem arka planda sessizce gerçekleşir ve kullanıcı herhangi bir şey fark etmez.
RFC 9106: İleri Okuma Önerisi
RFC 9106, Argon2'in teknik detaylarını ve parametre optimizasyonunu açıklar. Özelliklikle Section 4, Parametre seçiminin güvenlik üzerindeki etkilerini analiz etmektedir. RFC 9106'nın teknik tavsiyelerini inceleyerek parametreleri ölçeklendirebilirsiniz.
https://datatracker.ietf.org/doc/html/rfc9106#section-4
Bonus: bcrypt’in 72 Byte Sınırı Hakkında
bcrypt algoritmasının çoğu implementasyonunda, hashleme işlemi sadece parolanın ilk 72 byte’ını dikkate alır. Yani 72 byte sonrasını hesaplama işlemine dahil etmez. Burada ayrıca önemi olan husus: 72 sayısı karakter sayısı değil, byte sınırıdır.
- ASCII karakterler genelde 1 byte yer kaplar, bu nedenle yalnızca ASCII karakterlerden oluşan bir parola en fazla 72 karakter uzunluğunda olmalıdır.
- Ancak
ş
,ü
,ğ
,€
,😊
gibi ASCII dışı karakterler UTF-8 kodlamada 2 ile 4 byte yer kaplar. Bu durumda aynı sınır, çok daha kısa karakter uzunluklarında aşılabilir.
Örnekler:
abcABC123! → 10 karakter, tamamı ASCII → 10 byte
şifreGüçlü! →
- ‘ş’, ‘ü’, ‘ç’, ‘ü’ Türkçe karakterleri UTF-8'de 2 byte yer kaplar → 4 × 2 = 8 byte
- Diğer 7 karakter ASCII’dir → 7 × 1 = 7 byte
- Toplam 15 byte
“Parola😊123” →
- 9 ASCII karakter → 9 byte
- Emoji (😊) → 4 byte
- Toplam 13 byte
Bu nedenle bcrypt kullanan sistemlerde 72 karakter sınırı koymak yanıltıcı olabilir. Bu sınırı karakter sayısına göre değil, byte cinsinden kontrol etmek gerekir. Aksi takdirde parolanın sonunda 72 byte sonrasındaki karakterler truncate edilir ve bu çok düşük bir olaslık da olsa güvenlik açığına yol açabilir.
Tabii ki 72 byte veriden collision saldırısı gibi bir şeyin mümkün olup olmayacağı ayrı bir tartışma konusudur.
Sonuç
Güvenlik, algoritma seçiminin yanı sıra bu seçimin OWASP standartlarına uygun parametrelerle desteklenmesiyle sağlanır.
Parola güvenliğinde doğru algoritma seçimi, sisteminizin direncini belirleyen kritik bir adımdır. Argon2id, OWASP tarafından açıkça önerilen modern bir seçenek olarak öne çıkıyor; GPU tabanlı saldırılara karşı üstün direnci, bellek optimizasyonu ve parametre esnekliğiyle güvenlikle performansı dengeliyor. Doğru yapılandırıldığında, bcrypt’ten yalnızca %3.5 daha yavaş çalışarak kaynak tüketimini makul seviyede tutabilir. Lakin o testte Argon2id, bcrypt’e kıyasla 20.000 kat daha fazla bellek daha fazla bellek kullanır, bu da düşük kaynaklı sistemlerde performans sorunlarına yol açabilir. Argon2, yüksek bellek tüketimiyle saldırganların özel donanım (GPU/ASIC) avantajını kırmayı amaçlayan kasıtlı bir tasarım benimser.
Ancak bcrypt, basit yapısı ve yaygın legacy destekle hâlâ geçerli bir alternatif; özellikle OWASP’in belirttiği work factor'ü 10 veya üzeri
ile saldırı maliyeti artırılabilir.
OWASP, yeni sistemlerde Argon2id kullanımını mümkün olduğunca zorunlu kılarken, geçiş sürecinde kullanıcı girişlerinde “rehashing” ile eski hashleri sessizce güncellemeyi önerir. Sonuç olarak, yüksek güvenlik gerektiren projelerde OWASP’in belirlediği Argon2id parametreleri temel alınmalı; eski sistemlerde bcrypt kullanılıyorsa work factor
tavsiye edilen değerde tutulmalıdır.
Not: OWASP’in güncel kılavuzlarını takip etmek ve düzenli denetimler yap(tır)mak, sisteminizi gelecekteki tehditlere karşı korumanın en etkili yoludur. Bu makalede yer alan bilgiler ve bulgular zamanla geçerliliğini yitirebilir.
Kaynaklar
Password Storage - OWASP Cheat Sheet Series
GitHub - mheyman/Isopoh.Cryptography.Argon2: Fully managed .Net Core implementation of Argon2
RFC 9106: Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications