.NET Üzerinde Kriptografi

.NET platformu üzerinde geliştirdiğiniz uygulamaları nasıl daha güvenli hale getirebileceğimize bu yazımızla kısa bir başlangıç yapıyoruz.

Bugünlerde bilgisayar dünyasında en çok konuşulan konulardan biri kriptografi, yani şifreleme. İki tarafın kulak misafiri kaygısı olmaksızın haberleşmelerini sağlayan bu teknoloji, özellikle son birkaç yılda İnternet''in yaygınlaşmasıyla önem kazandı. .NET platformu üzerinde gelistirdiğiniz uygulamaları nasıl daha güvenli hale getirebileceğimize bu yazımızla kısa bir başlangıç yapıyoruz.

İyi bir kriptografik sistem, bilgilerinizin İnternet ya da başka her hangi bir ortam üzerinden iletilirken başkaları tarafından görülse bile anlaşılmamasını sağlar. Şekil 1''de görüldügü gibi, böyle bir sistem dört bileşenden oluşur:

Şekil 1 Kriptoğrafik Sistem
Şekil 1

1. Gönderen ve alan dışında kimsenin görmesi istenmeyen bir mesaj.
2. Sadece mesajı gönderen ve alanda bulunan, baska kimsenin bilmediği bir anahtar.
3. Anahtarı kullanarak mesajı şifreleyecek ya da deşifreleyecek bir algoritma.
4. İçinden geçen mesajların isteyen herkes tarafından görülebileceği, güvensiz bir ortam -mesela İnternet.

Bu modelin dayandığı tek varsayım, kulak misafirinin anahtar olmadan şifrelenmiş mesajdan orijinali elde etmesinin çok zor oluşudur. Durum böyle olunca izinsiz dinleyicinin yapabileceği tek şey, anahtar olabilecek bütün olasılıkları şifrelenmiş ileti üzerinde teker teker denemek oluyor. Tabi, mesajı gönderen ve alan, tahmin edilmesi zor ve uzun bir anahtar seçerek bu metodu rahatlıkla etkisiz hale getirebilirler.

Günümüzde kullanılan kriptografik algoritmalar iki ana gruba ayrılmakta: simetrik ve asimetrik. Bu iki grup arasindaki fark, simetrik algoritmaların hem şifrelemek hem de deşifrelemek icin aynı anahtarı kullanmalarına karşın, asimetrik algoritmaların iki farklı anahtar kullanmaları. Gönderen mesajı iki anahtardan herhangi biriyle şifreleyebilir. Ama alan, gönderen hangi anahtarları kullanırsa kullansın, mesajı çözmek için diğer anahtarı kullanmak zorundadır.

Microsoft .NET Platformu beraberinde dört simetrik kriptografi algoritması ile geliyor. Butun bu algoritmalar System.Security.Cryptography aduzayındaki sınıflarca sağlaniyor. Sözkonusu algoritmaların özelliklerini Şekil 2''de özetledik. Bu yazıdaki program örneğinde simetrik kriptografinin en eski standartlarından biri olan DES''i kullanacağız. Ama örnek program .NET platformu ile gelen her simetrik algoritma için geçerli.

Şekil 2: .NET Platformu ile gelen simetrik algoritmalar

Algoritma Sağlayan .NET Sınıfı Blok Uzunluğu (bit) Anahtar Uzunluğu (bit)
DES DESCryptoServiceProvider 64 64
RC2 RC2CryptoServiceProvider 64 40 - 128 (8''in katı olmalı)
Rijndael RijndaelManaged 128, 192 veya 256 128, 192 veya 256
TripleDES TripleDESCryptoServiceProvider 64 128 veya 192

Hemen her simetrik algoritma mesajı blok blok şifreler. Farzedelim, gönderenin mesajı "Saat 10''da buluşalım". Bu mesaj 20 bayt''tan oluşuyor. Eger DES''i kullanırsak, 8 bayt''tan oluşan 3 bloğa ihtiyacımız olacak:

Blok Numarası Blok İçeriği
1 Saat 10''
2 da buluş
3 alım

Son blok 4 bayt''tan oluşuyor. Bu durum hakkında ne yapacağız? İki seçeneğimiz var:
· Son bloga 4 sıfır içeren bayt ekleyebiliriz (00 00 00 00).
· Son bloğa her biri eklediğimiz bayt sayısını gösteren baytlar ekleyebiliriz. (04 04 04 04).

Yukarıda belirttiğimiz yöntemlerden ilki .NET platformunda PaddingMode.Zeros, ikincisi de PaddingMode.PKCS7 değerlerine karşılık geliyor. Örnek programda PKCS7''yi tercih ettik, çünkü bu yöntem mesajı kırmak isteyenlere daha az ipucu vererek işlerini zorlaştıracak.

Anahtar olarak 8 bayt seçmek durumundayız. Bu durumda ilk akla gelen rasgele bir parola seçip bu parolanın ilk 8 karakterini bayta çevirmek. Bu yöntemle 8 baytlık anahtarı en verimli şekilde kullanmıyoruz, çünkü böyle yaparak şifreyi kırmak isteyen birinin denemek zorunda olduğu olası anahtarları kısıtlayıp işini kolaylaştırmış oluyoruz. Yine de, şimdilik bununla idare edelim.

Bir mesajı şifrelemek ya da deşifrelemek bir anlamda onu bir başka şekle dönüştürmek olduğu için ilk yapmamız gereken, sectiğimiz kriptografi sınıfından ( DESCryptoServiceProvider) bir ICryptoTransform arayüzü istemek. Mesajı şifrelemek için CreateEncryptor, çözmek için ise CreateDecryptor metodlarını kullanarak bu arayüzü elde ediyoruz.

ICryptoTransform arayüzünü elde ettikten sonra yapmamız gereken bir tek şey kalıyor, o da TransformBlock ya da TransformFinalBlock metodlarını kullanarak mesajı şifrelemek ya da çözmek. Bu arayüzün sunduğu iki yararlı özellik daha var:

· CanReuseTransform: Eğer bu özellik doğru ( true) ise, ICryptoTransform arayüzünü bir sonraki mesajlar için de kullanabiliriz. Aksi taktirde dönüştürmek istediğimiz her mesaj için yeni bir arayüz edinmek zorundayız. .NET platformu ile gelen dört simetrik algoritmanın hepsi yeniden kullanılabilir özellikte.
· CanTransformMultipleBlocks: Eger bu özellik doğru ( true) ise, mesajı TransformBlock metodunu bir döngü içinde her blok icin çağırmak yerine bütün mesajı bir defada şifreleyebilir ya da çözebiliriz.

Bu kısa baslangıçtan sonra ilk programımızı yazmaya hazırız.

System ve System.Security.Cryptography aduzaylarının yanısıra System.Text aduzayını mesaj ve anahtardaki karakterleri stringden bayta ya da bayttan stringe çevirmek için kullanıyoruz.

using System;
using System.Text;
using System.Security.Cryptography;

WriteHex metodunu herhangi bir bayt dizinini onaltılık düzende yazmak için kullanıyoruz.

static void WriteHex(byte[] array) {
for (int i = 0; i < array.Length; i++)
Console.Write(array[i].ToString("x"));
}

.NET platformu string ve bayt dizinleri arasinda kolayca dönüşüm yapabilmek için çesitli Encoding sınıfları sunuyor. Bu örnekte UTF-8 dönüşümünü kullanıyoruz.

static void Main(string[] args) {
try {
// string <-> byte[] dönüşümu icin UTF8 kullanalim
Encoding ue = new UTF8Encoding();

Algoritma olarak DES''i kullanıyor ve daha önce de gördüğümüz gibi son bloğu PKCS7 yöntemi ile uygun uzunluğa çeviriyoruz.

// Algoritma olarak DES''i kullanalım
SymmetricAlgorithm ea = new DESCryptoServiceProvider();
// Kolaylık açısından ECB ve PKCS7''yi tercih edelim
ea.Mode = CipherMode.ECB;
ea.Padding = PaddingMode.PKCS7;

BlockSize ve KeySize özellikleri anahtar ve blok uzunluklarını bit cinsinden belirttiği icin bayta çevirmemiz gerekiyor.

// Her algoritma ancak belli anahtar uzunluklarini kabul eder.
// DES: 64 bit, TripleDES: 128 ya da 192 bit ...
// Anahtar ve blok uzunluklarini bitten bayta cevirelim
int blockSize = ea.BlockSize / 8;
int keySize = ea.KeySize / 8;

// Once anahtar dizinini kuralim
byte[] key = new byte[keySize];

Örnek programda kullanıcıdan önce parolayı daha sonra da mesajı girmesini istiyor ve her iki stringi de UTF-8 dönüşümü ile bayt dizinine çeviriyoruz.

// Sonra kullanıcıdan parolayı alıp anahtar dizinine aktaralım
Console.Write("Anahtar: ");
try {
ue.GetBytes(Console.ReadLine()).CopyTo(key, 0);
} catch (ArgumentException) {
Console.WriteLine("Sectiginiz anahtar bu algoritma icin cok uzun.");
return;
}

// Anahtarı algoritmaya iletelim
ea.Key = key;

// Kullanıcı şimdi istediği mesajı girebilir
Console.Write("Mesaj: ");
byte[] message = ue.GetBytes(Console.ReadLine());

Mesajı şifrelemek için CreateEncryptor metodu ile bir dönüşüm arayüzü alıyoruz.

// Mesajı şifrelemeye başlayabiliriz. Önce bir dönüşüm arayüzü alalım:
ICryptoTransform enc = ea.CreateEncryptor();

Mesajın tamamı elimizde ve DES için CanTransformMultipleBlocks doğru. Bu yüzden mesajı blok blok şifrelemek yerine TransformFinalBlock metodunu bir kez çağırarak şifreliyoruz.

// Sonra şifreleyelim
byte[] output = enc.TransformFinalBlock(message, 0, message.Length);

// Şifreyi yazalım
Console.Write("Sifre: ");
WriteHex(output); Console.WriteLine();

Şifrelemek ile şifreyi çözmek arasındaki tek fark ICryptoTransform''u CreateDecryptor metodunu kullanarak elde etmemiz.

// Şimdi kontrol edelim
SymmetricAlgorithm da = new DESCryptoServiceProvider();
// Asağıdaki özellikler elbette ea sınıfı ile aynı olmak zorunda
da.Key = key;
da.Mode = CipherMode.ECB;
da.Padding = PaddingMode.PKCS7;
ICryptoTransform dec = da.CreateDecryptor();

byte[] check = dec.TransformFinalBlock(output, 0, output.Length);

// Çözülmüş mesajı yazalım
Console.Write("Mesajın aslı: ");
Console.WriteLine(ue.GetString(check));

Her türlü kriptografik işlem CryptographicException verebilir. Bu yüzden bütün programı bu türlü hataları yakalayan bir try-catch bloğu altında çalıştırıyoruz.

} catch (CryptographicException e) {
Console.WriteLine("Beklenmedik bir şey oldu. Ayrıntılar:");
Console.WriteLine(e.Message);
return;
}
}

Simetrik algoritmaların butun kolaylıklarına karşın çok kritik bir zayıflıkları var: Gönderici ile alıcı anahtar üzerinde nasıl anlaşacaklar? Farzedelim gönderici anahtarın "aliveli4950" olmasını istiyor. Bunu alıcıya şifreleyerek gönderemez, çünkü alıcı henüz anahtarın ne olduğunu bilmiyor; bu yüzden mesajı çözemeyecektir. Öte tarafta, gönderici anahtarı şifrelemeden de göndermez. Çünkü bu defa mesajı dinleyen herkes anahtarın ne olduğunu öğrenecek, ve bu anahtara dayanan sonraki mesajları kolayca çözebilecek. Sonuç olarak, iki tarafın anahtar üzerinde anlasmaları için bir başka yönteme ihtiyaçları var.

Bu problem günümüzde asimetrik kriptografi, ve onun en yaygın şekli olan açık anahtar şifrelemesi (public key cryptography) ile çözülüyor. Bu konu üzerinde de bir dahaki sefere duracağız.

, , ,

Arşivden

Yorum bulunmuyor.

Yorum yazabilirsiniz


* [b], [i] ve [quote] serbest