Hashing, verileri sabit uzunlukta benzersiz bir özet (hash) değerine dönüştüren tek yönlü bir matematiksel işlemdir. C# ve .NET Framework, güvenlik, veri bütünlüğü kontrolü ve dijital imzalar gibi çeşitli alanlarda hashing işlemlerini gerçekleştirmek için yerleşik kütüphaneler sunar. Bu makalede, hashing kavramını, yaygın algoritmaları, kullanım senaryolarını ve C#’ta nasıl uygulanacağını detaylı şekilde ele alacağız.
Hashing, herhangi bir boyuttaki veriyi alıp, sabit boyutta (örneğin 128-bit, 256-bit gibi) özet bir değere dönüştüren tek yönlü bir dönüşümdür. Bu özet değere “hash” denir. Önemli özellikleri:
- Tek Yönlülük: Hashlenmiş bir veriden orijinal veriye ulaşmak (tersine mühendislik) neredeyse imkânsızdır.
- Deterministik Olması: Aynı girdiden her zaman aynı hash değeri üretilir.
- Çakışma İhtimalinin Düşüklüğü: Farklı girdilerin aynı hash değerini üretme olasılığı çok düşüktür.
- Hızlı Hesaplanabilirlik: Hash algoritmaları genellikle hızlı çalışır.
Hashing ve Şifreleme Arasındaki Farklar
- Şifreleme: Veriyi geri alınabilir şekilde dönüştürür (decrypt edilebilir).
- Hashing: Tek yönlüdür; hashlenmiş veriden orijinal veri elde edilemez. Bu yüzden özellikle şifre saklama gibi durumlarda tercih edilir.
C#’ta Hashing Algoritmaları
C#’ta veri güvenliğini sağlamak ve verinin bütünlüğünü kontrol etmek için çeşitli hashing algoritmaları kullanılabilir. İşte en yaygın olanları:
MD5
128-bit hash değeri üretir. Hızlıdır ancak günümüz güvenlik standartlarına göre zayıftır. Veri bütünlüğü kontrolü ve checksum hesaplamaları gibi senaryolarda kullanılır, ancak şifreleme amaçlı kesinlikle önerilmez.
public static string ComputeMD5(string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
}
}
SHA Serisi (SHA-1, SHA-256, SHA-512)
SHA algoritmaları, MD5’e göre daha güvenlidir. Özellikle SHA-256 ve SHA-512, modern uygulamalarda veri bütünlüğü ve dijital imza işlemleri için sıklıkla tercih edilir. Dosya bütünlüğü, dijital imzalar ve mesaj özetleri oluşturma işlemleri.
public static string ComputeSHA256(string input)
{
using (SHA256 sha256 = SHA256.Create())
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = sha256.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
}
}
HMAC (Hash-based Message Authentication Code)
Bir anahtar kullanarak hash hesaplar, bu sayede hem verinin hem de anahtarın doğruluğu kontrol edilebilir. API güvenliği, token imzalama ve mesaj bütünlüğü doğrulama gibi alanlarda kullanılır.
public static string ComputeHMACSHA256(string message, string key)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
{
byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
return Convert.ToHexString(hashBytes);
}
}
PBKDF2 (Password-Based Key Derivation Function 2)
Şifre hashleme işlemleri için yaygın kullanılan, salt ve iterasyon sayısını kullanarak hesaplama yapan güvenli bir algoritmadır. Özellikle kullanıcı şifrelerinin güvenli şekilde saklanmasında kullanılır. ASP.NET Core Identity, PBKDF2 algoritmasını varsayılan olarak kullanır.
public class PBKDF2Hasher
{
private const int Iterations = 10000;
private const int SaltSize = 16;
private const int KeySize = 32;
public static string HashPassword(string password)
{
byte[] salt = RandomNumberGenerator.GetBytes(SaltSize);
byte[] hash = Rfc2898DeriveBytes.Pbkdf2(
Encoding.UTF8.GetBytes(password),
salt,
Iterations,
HashAlgorithmName.SHA256,
KeySize);
return $"{Convert.ToBase64String(salt)}:{Convert.ToBase64String(hash)}";
}
public static bool VerifyPassword(string password, string hashedPassword)
{
string[] parts = hashedPassword.Split(':');
if (parts.Length != 2) return false;
byte[] salt = Convert.FromBase64String(parts[0]);
byte[] hash = Convert.FromBase64String(parts[1]);
byte[] computedHash = Rfc2898DeriveBytes.Pbkdf2(
Encoding.UTF8.GetBytes(password),
salt,
Iterations,
HashAlgorithmName.SHA256,
KeySize);
return CryptographicOperations.FixedTimeEquals(computedHash, hash);
}
}
ASP.NET Core Identity içinde yerleşik bir hashleme formatı sunar. Bu format, PBKDF2 (Password-Based Key Derivation Function 2) algoritmasını kullanarak şifreleri hashler. .NET’in sunduğu bu standart hash formatı, salt, hash, ve iterasyon sayısını içeren özel bir yapıdadır.
.NET Identity tarafından oluşturulan hash formatı aşağıdaki gibidir:
$HASH_VERSION$PRF$ITERATION_COUNT$SALT$HASH
Bu format beş ana bileşenden oluşur:
- Hash Version (
$HASH_VERSION$
): Hash formatının hangi versiyon olduğunu belirtir. Genelliklev3
kullanılır. - PRF (Pseudo Random Function) (
$PRF$
): Kullanılan hashleme algoritmasıdır. Genellikle HMACSHA256, HMACSHA512 gibi algoritmalar kullanılır. - Iteration Count (
$ITERATION_COUNT$
): Hashleme işlemi kaç tekrar yapılmış, bunu belirtir. Genellikle 10000+ iterasyon kullanılır. - Salt (
$SALT$
): Rastgele üretilen ve hashlemeye eklenen bir veri parçasıdır. Her şifre için farklıdır. - Hash (
$HASH$
): PBKDF2 algoritması ile üretilen ve şifrenin hashlenmiş halidir.
Örnek Bir .NET Hash Formatı
Aşağıda .NET tarafından üretilmiş bir hash örneği verilmiştir:
$ASP.NET Identity V3$HMACSHA256$10000$TYUS2zS9XAexAxv3P35qYw==$5Mn6T27lRqfl7/IRc2Hz9A==
Bu string’i Split('$')
ile böldüğümüzde her bir bileşeni ayrıştırabiliriz.
BCrypt
Salt’ı dahili olarak yöneten, iterasyon sayısını artırma imkânı sunan adaptif bir algoritmadır. NuGet paketleri aracılığıyla C# ortamında kullanılabilir.
.NET için BCrypt.Net-Next adlı NuGet paketi ile kullanabilirsiniz:
string hashedPassword = BCrypt.Net.BCrypt.HashPassword("MySecurePassword!");
bool isValid = BCrypt.Net.BCrypt.Verify("MySecurePassword!", hashedPassword);
Argon2
Günümüzde şifre hashleme için en güvenli algoritmalardan biri olarak öne çıkar. Hem CPU hem de RAM kullanımını ayarlayarak saldırılara karşı ekstra güvenlik sağlar. Argon2, C#’ta üçüncü parti kütüphaneler ile entegre edilebilir. Hem CPU hem de RAM tüketimini artırarak brute-force saldırılarını zorlaştırır.
public class Argon2Hasher
{
public static byte[] HashPassword(string password)
{
using (var hasher = new Argon2id(Encoding.UTF8.GetBytes(password)))
{
hasher.Salt = Encoding.UTF8.GetBytes("RandomSaltValue");
hasher.DegreeOfParallelism = 8;
hasher.MemorySize = 65536;
hasher.Iterations = 4;
return hasher.GetBytes(32);
}
}
}
Sonuç: Hangi Hash Algoritması Ne İçin Kullanılmalı?
Algoritma | Kullanım Alanı | Güvenlik Düzeyi |
---|---|---|
PBKDF2 | Şifre saklama (ASP.NET Identity) | ✅ Güvenli |
BCrypt | Şifre saklama | ✅ Güvenli |
Argon2 | Şifre saklama (Modern) | ✅ En güvenli |
SHA-256 / SHA-512 | Veri bütünlüğü, dijital imza | ⚠️ Şifre saklamak için uygun değil |
HMAC (HMAC-SHA256) | Mesaj doğrulama, JWT imzalama | ✅ Güvenli |
MD5 | (Önerilmez) | ❌ Güvensiz |
Öneriler
- Şifre saklamak için PBKDF2, BCrypt veya Argon2 kullanın.
- Veri bütünlüğü için SHA-256 veya SHA-512 kullanın.
- API güvenliği için HMAC-SHA256 gibi algoritmalar kullanın.
- MD5 ve SHA-1 gibi eski algoritmaları kullanmayın!