Yazılım dünyasında en çok karıştırılan konulardan biri şudur: "Bir veriyi korumak için hashing mi kullanmalıyım, encryption mı?" İkisi de veriyi güvenli hale getirmek için kullanılır, ama amaçları tamamen farklıdır.

Kısaca söyleyelim:

  • Hashing (özetleme), veriyi tek yönlü bir işlemler zincirinden geçirip sabit uzunlukta bir çıktı üretir.
  • Encryption (şifreleme), veriyi bir anahtar kullanarak okunamaz hale getirir; doğru anahtar varsa tekrar geri açılabilir.

Bu fark küçük görünür ama pratikte çok kritiktir. Çünkü yanlış yerde encryption kullanmak, yanlış yerde hashing kullanmak ciddi güvenlik açıklarına yol açabilir.

Hashing nedir?

Hashing, bir veriyi alıp onun kısa, sabit uzunlukta bir "özetini" üretme işlemidir. Bu özete hash değeri denir.

Buradaki "özet" kelimesi önemli: Özet, verinin kendisi değildir. Sadece o veriye ait parmak izi gibi düşünülebilir.

Örneğin:

  • Merhaba kelimesi
  • Merhaba! kelimesi

Aralarında yalnızca bir karakter fark olsa bile, hash çıktıları tamamen farklı olur.

Hashing'in temel özelliği şudur:

  • Aynı giriş her zaman aynı hash sonucunu üretir.
  • Hash çıktısından orijinal veriyi geri elde etmek pratik olarak mümkün değildir.

Bu yüzden hashing, özellikle parola saklama gibi alanlarda kullanılır.

Encryption nedir?

Encryption, veriyi bir algoritma ve bir anahtar (key, yani kilit gibi çalışan gizli bilgi) kullanarak okunamaz hale getirme işlemidir.

Encryption yapılan veri, doğru anahtar ile tekrar eski haline döndürülebilir. Bu yüzden encryption, geri döndürülebilir bir işlemdir.

Örnek olarak:

  • Kredi kartı numarası
  • Kullanıcının özel bilgileri
  • API üzerinden taşınan hassas veri

gibi şeyler encryption ile korunabilir.

Buradaki ana fikir şudur:

  • Veriyi gizlersin
  • Ama gerekirse tekrar açabilirsin

En temel fark

Aradaki farkı tek cümlede anlatmak gerekirse:

  • Hashing, veriyi saklamak için değil, doğrulamak için kullanılır.
  • Encryption, veriyi saklamak veya taşımak sırasında gizlemek için kullanılır.

Yani hashing'de amaç "Bu veri doğru mu?" sorusunu cevaplamaktır. Encryption'da amaç "Bu veriyi kimse okuyamasın" demektir.

Password için neden hashing kullanılır?

Parolalar kesinlikle encryption ile saklanmamalıdır. Doğru yaklaşım hashing'dir.

Neden?

Çünkü bir veritabanı ele geçirilirse, encryption ile saklanan parolalar anahtar da ele geçirilirse tekrar okunabilir. Ama hash'lenmiş paroladan orijinal parolayı geri çıkarmak pratik olarak mümkün değildir.

Bu nedenle sistemler genellikle şu yaklaşımı kullanır:

  1. Kullanıcının parolası alınır
  2. Parola bir salt ile birleştirilir
  3. Hash algoritması ile özetlenir
  4. Sonuç saklanır

Buradaki salt (tuz), aynı parolaya sahip iki kişinin aynı hash'i üretmesini engellemek için eklenen rastgele veridir.

Bu çok önemlidir. Aksi halde iki kullanıcı aynı parolayı kullanıyorsa, aynı hash değerine sahip olurlar ve bu güvenlik açısından kötü bir durumdur.

Encryption hangi durumlarda kullanılır?

Encryption, verinin geri açılması gerektiğinde kullanılır.

Örnekler:

  • Bankacılık verileri
  • Kişisel bilgiler
  • Uçtan uca iletişim
  • Dosya şifreleme
  • API ile taşınan hassas bilgiler

Burada veri gerektiğinde tekrar okunabilir olmalıdır. Bu nedenle hashing uygun değildir.

Örneğin kredi kartı numarasını saklıyorsan, daha sonra kullanıcıya son 4 hanesini göstermek veya bir işlemde tekrar kullanmak isteyebilirsin. Bu durumda encryption gerekir.

Hashing geri döndürülemez, encryption geri döndürülebilir

Bu ayrımın özü budur.

Hashing

  • Tek yönlüdür
  • Geri açılmaz
  • Doğrulama için uygundur

Encryption

  • Çift yönlüdür
  • Doğru anahtarla geri açılır
  • Gizleme ve taşıma için uygundur

Bu yüzden ikisini aynı kategori gibi düşünmek hata olur.

Hash Algoritmalarına Örnekler

Sık kullanılan hash algoritmaları şunlardır:

  • SHA-256
  • SHA-512
  • BCrypt
  • PBKDF2
  • Argon2

Burada önemli bir ayrım var:

  • SHA-256 gibi algoritmalar genel amaçlı hash algoritmalarıdır.
  • BCrypt, PBKDF2 ve Argon2 ise özellikle parola saklama için tasarlanmıştır.

Bu farkı bilmek gerekir. Çünkü parola saklarken sadece SHA-256 kullanmak çoğu zaman yeterli değildir. Neden? Çünkü hızlı çalışır ve saldırganlar çok sayıda deneme yapabilir.

Parola saklamak için yavaş ve maliyetli algoritmalar tercih edilir. Buradaki "maliyetli" ifadesi, algoritmanın hesaplama açısından daha zor olması demektir.

Encryption Algoritmalarına Örnekler

Sık kullanılan encryption algoritmaları:

  • AES
  • RSA
  • TripleDES

Bunların içinde en yaygın olanlardan biri AES'tir. AES, symmetric encryption yani simetrik şifreleme algoritmasıdır.

Simetrik şifreleme demek şudur:

  • Şifreleme için kullanılan anahtar ile
  • Şifre çözme için kullanılan anahtar aynıdır

Buna karşılık asymmetric encryption yani asimetrik şifrelemede iki ayrı anahtar bulunur:

  • Public key (açık anahtar)
  • Private key (özel anahtar)

Public key ile şifrelenir, private key ile çözülür.

Hashing ve encryption birlikte kullanılabilir mi?

Evet, kullanılabilir. Hatta gerçek sistemlerde çoğu zaman birlikte kullanılır.

Örnek:

  • Parola saklama: hashing
  • Kullanıcının hassas verisini saklama: encryption
  • API isteğinin bütünlüğünü kontrol etme: hashing veya HMAC

Burada HMAC (Hash-based Message Authentication Code), Türkçe olarak "hash tabanlı mesaj doğrulama kodu" şeklinde açıklanabilir. Bu yapı, verinin değişmediğini doğrulamak için kullanılır.

Hangi durumda hangisini seçmeliyim?

Basit karar kuralı şu:

Hashing kullan:

  • Parola saklıyorsan
  • Verinin değişip değişmediğini kontrol edeceksen
  • Kimlik doğrulama sırasında karşılaştırma yapacaksan

Encryption kullan:

  • Veriyi daha sonra tekrar okumak istiyorsan
  • Hassas bilgiyi gizlemek istiyorsan
  • Veri hem saklanacak hem de gerektiğinde çözülecekse

Bunu yanlış seçmek uygulamanın güvenlik tasarımını bozar.

C# ile hashing örneği

Aşağıdaki örnekte SHA-256 ile bir metin için hash üretiyoruz.

using System; // Temel sistem sınıflarını kullanmak için eklenir.
using System.Security.Cryptography; // Kriptografi işlemleri için gerekli sınıfları içerir.
using System.Text; // Metni byte dizisine çevirmek için kullanılır.

public class HashExample
{
    public static string ComputeSha256Hash(string input)
    {
        using (SHA256 sha256 = SHA256.Create()) // SHA-256 hash algoritması nesnesi oluşturulur.
        {
            byte[] inputBytes = Encoding.UTF8.GetBytes(input); // Metin, UTF-8 formatında byte dizisine çevrilir.
            byte[] hashBytes = sha256.ComputeHash(inputBytes); // Giriş verisinin hash değeri hesaplanır.

            StringBuilder builder = new StringBuilder(); // Hex string oluşturmak için bir metin biriktirici hazırlanır.

            for (int i = 0; i < hashBytes.Length; i++) // Hash içindeki her byte için döngü başlatılır.
            {
                builder.Append(hashBytes[i].ToString("x2")); // Her byte iki haneli hexadecimal formata çevrilip eklenir.
            }

            return builder.ToString(); // Sonuç string olarak döndürülür.
        }
    }
}

Bu kod ne yapıyor?

  • Girdi olarak bir metin alıyor
  • Metni byte dizisine çeviriyor
  • SHA-256 ile hash üretiyor
  • Çıktıyı okunabilir bir hexadecimal string olarak veriyor

Burada dikkat edilmesi gereken nokta şu: Bu hash çıktısından orijinal metni geri elde edemezsin. Bu tek yönlü işlemdir.

C# ile encryption örneği

Aşağıdaki örnekte AES kullanarak bir metni şifreliyoruz.

using System; // Temel sistem sınıfları için kullanılır.
using System.IO; // MemoryStream gibi akış sınıfları için gereklidir.
using System.Security.Cryptography; // AES gibi kriptografik sınıfları içerir.
using System.Text; // Metin ve byte dönüşümleri için kullanılır.

public class AesExample
{
    public static byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] iv)
    {
        using (Aes aes = Aes.Create()) // AES algoritması için nesne oluşturulur.
        {
            aes.Key = key; // Şifreleme anahtarı atanır.
            aes.IV = iv; // Başlatma vektörü atanır.

            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); // Şifreleme dönüştürücüsü oluşturulur.

            using (MemoryStream ms = new MemoryStream()) // Şifreli veriyi bellekte tutmak için akış açılır.
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) // Şifreleme akışı oluşturulur.
                {
                    using (StreamWriter sw = new StreamWriter(cs)) // Metni akışa yazmak için yazıcı oluşturulur.
                    {
                        sw.Write(plainText); // Açık metin akışa yazılır.
                    }
                }

                return ms.ToArray(); // Şifreli veri byte dizisi olarak döndürülür.
            }
        }
    }

    public static string DecryptBytesToString(byte[] cipherText, byte[] key, byte[] iv)
    {
        using (Aes aes = Aes.Create()) // AES algoritması için nesne oluşturulur.
        {
            aes.Key = key; // Aynı şifreleme anahtarı atanır.
            aes.IV = iv; // Aynı başlatma vektörü atanır.

            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); // Şifre çözme dönüştürücüsü oluşturulur.

            using (MemoryStream ms = new MemoryStream(cipherText)) // Şifreli veri akışa alınır.
            {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) // Şifre çözme akışı oluşturulur.
                {
                    using (StreamReader sr = new StreamReader(cs)) // Çözülen metni okumak için okuyucu oluşturulur.
                    {
                        return sr.ReadToEnd(); // Açık metin geri döndürülür.
                    }
                }
            }
        }
    }
}

Bu örnekte önemli iki kavram var:

  • Key (anahtar): Şifreleme ve çözme için kullanılan gizli değer
  • IV (Initialization Vector, başlatma vektörü): Aynı verinin her şifrelemede aynı sonucu üretmesini zorlaştıran ek değerdir

IV, Türkçede "başlatma vektörü" diye açıklanır. Ama dikkat et: IV bir anahtar değildir. Anahtarın yerine geçmez.

Salt neden önemlidir?

Salt, hash işlemine eklenen rastgele veridir.

Mesela iki kullanıcı aynı parolayı seçerse, salt yoksa aynı hash ortaya çıkabilir. Ama salt eklenirse sonuç farklı olur.

Bu ne kazandırır?

  • Rainbow table saldırılarını zorlaştırır
  • Aynı parolayı kullanan kullanıcıları ayırt eder
  • Hash'in tahmin edilmesini zorlaştırır

Buradaki rainbow table, önceden hesaplanmış hash tabloları demektir. Saldırganlar bunları kullanarak bazı parolaları hızlıca tahmin etmeye çalışır.

Encryption'da anahtar yönetimi neden kritik?

Encryption'ın gücü algoritmadan çok, anahtarın güvenliğine bağlıdır.

Anahtar kötü yönetilirse:

  • Şifreleme anlamsız hale gelir
  • Saldırgan veriyle birlikte anahtarı da alırsa tüm güvenlik düşer

Bu yüzden anahtarlar genellikle:

  • Güvenli bir key vault içinde tutulur
  • Kod içine düz metin olarak yazılmaz
  • Log dosyalarına düşürülmez
  • Gereksiz yere paylaşılmaz

Buradaki key vault, anahtarların güvenli şekilde saklandığı yapı demektir.

Sık yapılan hatalar

1. Parolayı encryption ile saklamak

Yanlış. Parola saklama için hashing kullanılır.

2. Hassas veriyi hashleyip sonra geri okumayı beklemek

Yanlış. Hash geri döndürülemez.

3. SHA-256'yı parola hash'i için tek başına kullanmak

Eksik. Parola saklama için uygun parola hash algoritmaları tercih edilmelidir.

4. Encryption anahtarını kod içine sabitlemek

Tehlikeli. Anahtar yönetimi ayrı ele alınmalıdır.

5. Salt kullanmamak

Güvenlik zayıflar.

Sonuç

Hashing ve encryption benzer görünse de amaçları farklıdır.

  • Hashing, veriyi geri dönülmez şekilde özetler.
  • Encryption, veriyi gizler ama doğru anahtarla geri açılabilir.

Bu yüzden şu kuralı aklında tut:

  • "Bunu bir daha okumam gerekmeyecek" diyorsan: hashing
  • "Bunu sonra açmam gerekecek" diyorsan: encryption

Yazılımda güvenlik kararları küçük gibi görünür ama etkisi büyüktür. Doğru yerde doğru yöntemi kullanmak, sistemin temel güvenlik seviyesini doğrudan belirler.