Fırat Esmer

ANLATILAN SENİN HİKAYENDİR - Karl Marx

Razer - Şikayet

Razer Logo

Şikayet temalı yazılarım, içerisinde yaşadığımız kapitalist sistem sürdükçe var olacak. Bu günkü yazımın kahramanı Razer. Umarım yazdıklarım ürünü/hizmeti satın alma noktasında olanlara yardımcı oluyordur da ben de burada kendi kendime şikayet edip deşarj olmuyorumdur.

Hikayeme direkt başlıyorum. Çocukluğumdan beri oyunlarla aram iyidir. Gerek SNES (Super Nintendo) gerekse bilgisayar hep yakın olmuştur. Oyun kategorileri arasında FPS'ye ayrı bir ilgim var. Dolayısıyla bilgisayar ürünlerinde belli parçaları FPS'ye özel almaya çalışıyorum. Başta mouse geliyor. Mouse'u da Razer DeathAdder 2013 (Model : RZ01-0084) aldım. 2014 yılının Nisan-Mayıs ayı gibi 100-130 TL fiyat aralığında aldım. Şu an ürün daha pahalı çünkü kur farkı Büyük Türkiye'de daha fazla.

Nasıl ki bir insanın en temel ihtiyaçlarının başında konut, gıda ve güvenlik geliyorsa mouse'dan da yapmasını beklediğimiz ilk şey "tıklaması"dır öyle değil mi? Mouse'tan sonuçta bu beklenir. Bu mouse bunu bir süre sonra sağlayamıyor ya da şöyle diyeyim, fazlasıyla sağlıyor. Çift tıklama sorunu. Araştırdım, baktım ki abov. İnternet dünyası kaynıyor. Kronik sorun. Herkes şikayetçi. Güncelleme öneren, temizlik yap diyen, çöpe at diyeniyle yüzlerce yorum var internette/forumlarda. Size mouse'un da fotoğrafını atacağım ki hor kullanmadığımı ve içi boş yorumlarla eleştirmediğimi görün.

Öncelikle mouse'un kullanımı için Razer'ın yazmış olduğu Synapse uygulamasından bahsedeyim. Hiçbir işe yaramıyor. Hatta çift tıklama sorununu çözmek için programı silin diyenler var. Bana bunu Razer Support'tan birisi bile söylemişti. E sileceksek ne anlamı kaldı? Sonuçta ayarlarımız, profillerimiz o uygulamada. Neyse, sildim. Olmadı. Sıkıştırılmış dosyalarla güncellemeler yolladılar, bir süre olur gibi oldu sonra yine olmadı. Sonra bir şekilde "füüüüyt" kendiliğinden düzeldi. Bir süre daha kullandım. Bu sefer sorun scroll. Scroll yaptığımda bir yukarı bir aşağı kayıyor. Aslında 2 ileri 1 geri diyelim. Aşağı scroll yapıyorsanız sonunda bir miktar yukarı, tam tersinde ise aşağı kayıyor. "Sonuçta kaç yıllık mouse, bunun da bir temizlikten geçmesi lazım" diyerek mouse'un nasıl parçalarına ayrıldığına dair video izlemeye başladım. İlk adım, mouse'un altındaki 3 vidayı sökün. O 3 vidadan hiçbirisini sökemedim. Başkalarına verdim onlar da sökemedi. Mouse'un altındaki, köşelerde bulunan ve sürtünmeyi azaltan yapışkanlı parçaları da bir daha yapıştıramadım ve hikayem burada son buldu. Sorunlar kronik olmasa onarıma göndereceğim ama... Sorunlar bitmiyor.

Aşağıdaki fotoğraflar da mouse'un son hali, az önce çektim.

Razer

Razer 2

Not

  • Razer DeathAdder 2013 kullanmadan önce başka bir Razer mouse kullanmışlığım var: Razer Diamondback. Birisi tarafından hediye edildi, bir süre sonra onun da scroll'u bozuldu ama ürün sıfır değildi. O yüzden pek de ciddiye almamıştım o sorunu,
  • Mouse belki de klavyeden sonra bilgisayarın en çok kullanılan parçası olabilir, o yüzden kolayca kirlenip bozuluyor da olabilir fakat yıllarca sorunsuzca kullandığım mouselar da oldu o yüzden...

BİR DAHA RAZER BEL-Kİ. BİR İHTİMAL. SANMIYORUM.

C# 7 - İlk Bakış

C# History

Visual Studio 2017'nin yayınlanması ile birlikte C# 7.0 da aramıza katılmış oldu. VS2017 RTM'e (son/kararlı hal) geçmeden önce dil hakkında bilgileri zaten ediniyor hatta kullanıyoruz. C# 7 ile gelen yeniliklerin yaşantımızda kullanacak kıvama gelmeden hemen önceki turumuza başlayalım.

Bahsedeceğim konular

  • Out Variables
  • Pattern Matching,
  • Tuples,
  • Local Functions,
  • Literals, Ref. Returns, Exceptions

Out Variables

  • Önceden tanımlamada var kullanılamıyor (int.TryParse(input, out var answer)),
  • Kullanmadan önce tanımlanması gerekiyor (demo),

Yukarıdaki sorunlara çözüm olarak Out Variables sunuldu.

// Eski yöntem
private static void Run()
{
	string name;
	string lastName;

	GetName(out name, out lastName);
	Console.WriteLine($"{name} {lastName}");
}

// C# 7.0 ile gelen yeni yöntem
private static void Run2()
{
	GetName(out string name, out string lastName);
	Console.WriteLine($"{name} {lastName}");
}

private static void GetName(out string name, out string lastName)
{
	name = "Fırat";
	lastName = "Esmer";
}

Pattern Matching

Pattern'in tanımı için şöyle güzel bir yorum var:

Syntactic elements that can test that a value has a certain "shape".

Bir değerin belirli bir şekle sahip olduğunu test edebilen sözdizimsel öğeler.

static void Main(string[] args)
{
	PrintSum(10);
	PrintSum2("10");
}

public static void PrintSum(object o)
{
	if (o is null) return; //Constant Pattern
	if (!(o is int i)) return; // Type Pattern (Int32)

	int sum = 0;

	for (int j = 0; j <= i; j++)
		sum += j;
}

public static void PrintSum2(object o)
{
	if (o is int i || o is string s && int.TryParse(s, out i))
	{
		int sum = 0;

		for (int j = 0; j <= i; j++)
			sum += j;
	}
}

Koşullu switch'e de bir göz atalım, burada gelen yenilik case durumunda koşul girebiliyor olmamız. Yani test edebiliyor olmamız.

class Program
{
	static void Main(string[] args)
	{
		Employee employee = new President();
		employee.Salary = 200000;
		employee.Years = 10;
		(employee as President).ManagedEmployeeNumber = 500;
		(employee as President).StockShares = 12000;

		// Switch içerisindeki sıralama önemli
		// Manager Employee'nin altında olsaydı hata alırdık
		// Kalıtım alan sınıf alınan sınıftan üstte olmalı
		switch (employee)
		{
			case President p when (p.StockShares < 10000):
				Console.WriteLine($"Düşük profilli yönetici hisse senedi payı : {p.StockShares}");
				break;

			case President p when (p.StockShares >= 10000):
				Console.WriteLine($"Yüksek profilli yönetici hisse senedi payı : {p.StockShares}");
				break;

			case Manager m:
				Console.WriteLine($"Yönetiye bağlı kişi : {m.ManagedEmployeeNumber}");
				break;

			case Employee e:
				Console.WriteLine($"Çalışan maaşı : {e.Salary}");
				break;
		}
	}
}

public class Employee
{
	public int Salary { get; set; }
	public int Years { get; set; }
}

public class Manager : Employee
{
	public int ManagedEmployeeNumber { get; set; }
}

public class President : Manager
{
	public int StockShares { get; set; }
}

Tuples

Metotlardan birden fazla değeri geri döndürmek istediğimizde aklımıza gelen en uygun yöntem out parametresi. Fakat out parametresinin de elimizi kolumuzu bağladığı bazı noktalar var. Mesela okunabilirliği zayıf, async metotlarla kullanılamıyor. Burada yardımımıza Tuple (System.Tuple<T>) yetişiyor. Tuple'ı başka bir Tuple'a convert edebilirsiniz. Tuple value type'dır (referans değil).

Öncelikle Tuples'ı kullanmak için NuGet Package kullanmamız gerektiğini belirteyim. Aşağıdaki resimde gördüğünüz gibi yüklemeyi gerçekleştirin.

System.Tuples Nuget Package

static void Main(string[] args)
{
	var numbers = GetThreeNumbers();
	// İsimlendirme işlemini biz yapmadığımız için
	// kendisi otomatik olarak yapıyor
	Console.WriteLine($"{numbers.Item1},{numbers.Item2},{numbers.Item3}");

	var numbersWithNames = GetThreeNumbersWithNames();
	Console.WriteLine($"{numbersWithNames.number1},{numbersWithNames.number2},{numbersWithNames.number3}");
}

public static (int, int, int) GetThreeNumbers()
{
	return (1, 56, 187);
}

public static (int number1, int number2, int number3) GetThreeNumbersWithNames()
{
	return (1, 56, 187);
}

Tuple ile Dictionary kullanımı

var tupleDictionary = new Dictionary<(int, int), string>();
tupleDictionary.Add((16, 21), "İki kardeşin yaşları");

// Sonuç = İki kardeşin yaşları
var result = tupleDictionary[(16, 21)];

Tuple Deconstruction örneği

static void Main(string[] args)
{
	(int number1, int number2, int number3) = GetThreeNumbers();
	Console.WriteLine($"{number1},{number2},{number3}");

	// Diğer kullanım şekli
	int _number1;
	int _number2;
	int _number3;
	(_number1, _number2, _number3) = GetThreeNumbers();
	Console.WriteLine($"{_number1},{_number2},{_number3}");
}

public static (int, int, int) GetThreeNumbers()
{
	return (1, 56, 187);
}

Local Functions

Local function, metot içerisinde metot kullanımıdır. Direkt örnekle açıklayayım, daha kolay olacaktır.

NOT : Örnekte Tuples kullanıldığı için Tuples başlığındaki gibi yükleme işlemini yapmanız gerekiyor.

static void Main(string[] args)
{
	// Fibonacci => 1, 1, 2, 3, 5, 8
	// Mevcut değerin bir önceki değer ile toplamı bir sonraki
	// değeri vermekte
	Console.WriteLine(Fibonacci(6));
	Console.Read();
	// Sonuç (6-1) + 8 = 13
}

public static int Fibonacci(int x)
{
	if (x < 0)
		throw new ArgumentException("Değer en az sıfır olmalı",
									nameof(x));

	return Fib(x).current;

	(int current, int previous) Fib(int i)
	{
		if (i == 0) return (1, 0);
		var (current, previous) = Fib(i - 1);
		return (current + previous, current);
	}
}

Literals, Ref. Returns, Exceptions

static void Main(string[] args)
{
	// Sonuç => 5781231
	Console.WriteLine(GetNumber());

	// Referans Return
	int[] numbers = { 1, 3, 5, 7, 9, 11 };
	ref int position = ref Substitute(5, numbers);
	position = -30;
	Console.WriteLine(numbers[2]);

	// Sonuç => Fırat
	Employee employee = new Employee("Fırat");
	Console.WriteLine(employee.Name);
	// Sonuç => Hata / Exception
	Employee employee2 = new Employee(null);
	Console.WriteLine(employee.Name);

	Console.Read();
}

// Literal: Altçizgi (underscore) seperator (ayırıcı)
// olarak değil dönüş tipi olarak dönüyor
private static int GetNumber()
{
	return 5_7_8_123_1;
}

// Reference Return örneği
private static ref int Substitute(int value, int[] numbers)
{
	for (int i = 0; i < numbers.Length; i++)
		if (numbers[i] == value)
			return ref numbers[i];

	throw new IndexOutOfRangeException("Bulunamadı!");
}

// Exception as expression örneği
public class Employee
{
	public string Name { get; }
	public Employee(string name) => Name = name ?? throw new ArgumentNullException();
}

Son olarak

C# 7 yenilikler listesini Microsoft Documents üzerinden incelemek için => https://docs.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7

.NET Dünyasında Kriptografi

Kriptografi Nedir? Neden ve Nerede Kullanılır?

Kriptografi, en geniş anlamıyla bilgileri gizlemektir. Fiziksel dünyadaki bilginin elektronik dünyaya taşınması ile ortaya çıkan güvenlik endişelerini gidermek için kullanıldığında söz bize, yazılımcılara düşer. Hepimiz gündelik hayatta güvenlik önlemleri altında hayatımıza devam ediyoruz. Bilgisayarınızı açtığınızda kim olduğunuzu kanıtlamak veya alışveriş sitesinde kredi kartı ile alışveriş yapmak bunlara verilebilecek en basit örneklerdir. Her iki işlemde de belirli parametreler (kredi kartı no. veya kullanıcı adı ve parolası) belirli adreslere gönderilip kontrol edilirken şifrelenirler.

Encryption & Decryption

Gizleme işlemine şifreleme diğer bir adıyla da encryption, şifrelenen mesajın şifresinin kaldırılmasına (okunması) ise decryption denir.
Örneğin, size bir mesaj gönderildiğini, bu mesajın şifrelendiğini ve anahtarın sadece mesajı gönderen kişide ve sizde olduğunu düşünün. Böylece mesaj vericinin elinden çıktığı andan alıcının eline ulaştığı ana kadar şifrelenmiş olacaktır. (Aynı şifreleme algoritmasının kullanıldığı bu işleme simetrik anahtar algoritması diğer adıyla symmeric encryption denir. İleride değineceğim.)

Encryption

Mesajın gönderilmeden önce şifrelenmesi

Decryption

Mesajın alıcıya ulaşmadan önce şifrenin kaldırılması

Kriptografinin Ana Konseptleri

  • Gizlilik: Yaptığınız işin içeriğinde kullanılan parametrelerin ne olduğunun asla bilinmemesi,
  • Bütünlük: İşlemin başından sonuna kadar şifrelenmiş verinin değişime uğramadan gideceği adrese ulaşması,
  • Reddedilmeme: Şifrelemeyi gerçekleştiren kişinin doğrulama adına imzasının olması,
  • Kimlik: Gizliliğin olduğu herhangi bir ortama erişim için kanıtlanmış kimlik.

> Rastgele Sayılarla Kriptografi

  • Şifreleme anahtarı oluşturmak için kullanılır,
  • Bazı sistemlerde cihazın sahip olduğu donanım bilgisi şifreleme işlemlerinde kullanılır. Mesela MAC ethernet adresi gibi. Donanımda bunun kullanılamadığı durumlar da söz konusu. Burada devreye yazılım tabanlı şifreleme girmeli. Bu yöntem için tamamen "rastgele" denemez,
  • Rastgelelik durumu insan etkileşimi ile oluşturulabilir,
  • Sunucu uygulamaları için uygun değildir çünkü manipülasyona açıktır. O yüzden belirli bir algoritma ya da donanıma ait bilgiler kullanılmalıdır.

Donald. E.Knuth adlı bilgisayar bilimcinin "Subtractive Random Number Generator" çalışması temel alınmıştır. Daha fazla bilgi için => The Art of Computer Programming

            // Farklı .NET Framework versiyonlarında
            // farklı değerler üretir (aynı seed değerler
            // olsa da)

            // Deterministtir, öngörülebilir

            Random rnd = new Random(350);

            for (int i = 0; i < 10; i++)
                Console.Write("{0,3}   ",rnd.Next(-10, 11));

            Console.Read();

System.Random ve Sorunları

  • Microsoft, uygulamanızda tek bir System.Random sınıfı instance'ı kullanılmasını öneriyor. Bkz. Random Class,
  • System.Random thread safe değildir (tek thread kullanımına dikkat edin aksi takdirde 0 değeri dönebilir),

Rastgele Numaraları RNGCryptoServiceProvider sınıfı ile kullanırsanız daha güvenli şifreleme işlemleri gerçekleştirirsiniz. System.Random'a göre performans açısından daha yavaştır fakat tamamen rastgeledir.

        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
                // Base64 işlemi daha okunabilir hale gelmesi için uygulanıyor
                Console.WriteLine($"Rastgele Numara {i + 1}: {Convert.ToBase64String(GenerateRandomNumber(32))}");

            Console.ReadLine();
        }

        public static byte[] GenerateRandomNumber(int length)
        {
            // 256-bit şifreleme için
            // Length = 32 (32 byte * 8 bit = 256 bit)
            using (var randomNumberGenerator = new RNGCryptoServiceProvider())
            {
                var randomNumber = new byte[length];
                randomNumberGenerator.GetBytes(randomNumber);

                return randomNumber;
            }
        }

RNGCryptoServiceProvider

> Hashing Algoritmaları İle Kriptografi

  • Verilen parametreyi kolayca hash'leyip hazırlar,
  • Hash'lenmiş bir veriyi ilk haline çevirmek için kullanılamaz, tek yönlüdür,
  • Hash'lenmiş verinin, orijinal halinde yapılacak en ufak bir değişiklik, tamamen farklı bir değerin üretilmesine sebep olacaktır,
  • İki farklı parametre aynı hash değeri üretemez (parmak izi örnek verilebilir, eşi yoktur),

.NET uygulamarında kullanılabilecek hash çeşitleri

Hashing Algorithms

  • Hashing ile geri döndürme işlemi yapılamaz. Yani, şifreli bir mesajı tekrar orijinal parametre haline çeviremezsiniz. Encryption'da bu mümkün. Yön farkları buradan gelmektedir,
  • Orijinal parametre değişmedikçe hash işlemi yapıldıkça üretilecek değerler aynı olacaktır (tek bir karakteri bile değişse, çok farklı bir değer üretileceğini belirtmiştik),

MD5

  • 1991 yılında MD4'un yerini almıştır,
  • 128-bit,
  • 1996 yılında ilk açık bulundu, 2004 yılında bulunan açıkların sayısı arttı. Kriptografcılar SHA gibi diğer yöntemlerin kullanılmasını öneriyor (çok nadir de olsa iki farklı veri seti aynı hash değer üretebiliyordu),
  • Yine de eski uygulamalarda kullanılmaktadır.

SHA (Secure Hash Algorithm)

  • SHA-1, NSA (National Security Agency) tarafından geliştirildi. 160 bit uzunluktadır. Bulunan sorunlardan ötürü daha fazla gelişimi sürmedi,
  • SHA-2, SHA-256 ve SHA-512 ailelerini temsil eder. SHA-256 256-bit, SHA-512 542-bit. NSA tarafından geliştirilmiştir,
  • SHA-3, 2012 yılında non-NSA yarışması sonucu doğmuştur. SHA-2'nin sahip olduğu hash uzunluğuna sahiptir. .NET Framework tarafından desteklenmemektedir. Üçüncü parti yazılımlarla ekleme yapmak mümnkün (.NET Framework desteği olmadığı için üzerinde durmayacağım).
        // Aşağıda belirtilen kriptografi sınıfları aynı
        // Interface'i kullanmakta => HashAlgorithm

        public static byte[] ComputeHashSHA1(byte[] toBeHashed)
        {
            using (var sha1 = SHA1.Create())
                return sha1.ComputeHash(toBeHashed);
        }

        public static byte[] ComputeHashSHA256(byte[] toBeHashed)
        {
            using (var sha256 = SHA256.Create())
                return sha256.ComputeHash(toBeHashed);
        }

        public static byte[] ComputeHashSHA512(byte[] toBeHashed)
        {
            using (var sha512 = SHA512.Create())
                return sha512.ComputeHash(toBeHashed);
        }

        public static byte[] ComputeHashMD5(byte[] toBeHashed)
        {
            using (var md5 = MD5.Create())
                return md5.ComputeHash(toBeHashed);
        }

Hashed Message Authentication Codes (HMAC)

Diğer adı hash MAC olan yöntemle verinizin bütünlüğü yine bir anahtar aracılığıyla kontrol edilebilir. Anahtar (input) kullanılarak şifrelenmiş veriniz, aynı anahtar kullanılarak tekrar üretilecek şifre değeri ile aynı olur ve tutarlılık kontrolü yapılabilir. Temel seviyedeki hash şifreleme sistemine göre daha az etkilidir. MD5 veya SHA ailesi kullanılarak şifreleme yapılır. Bu şifreleme yöntemine karşı en çok yapılan saldırı tipi Brute Force'tur.

HMAC

private const int KeySize = 64;

public static byte[] GenerateKey()
{
	using (var randomNumberGenerator = new RNGCryptoServiceProvider())
	{
		var randomNumber = new byte[KeySize];
		randomNumberGenerator.GetBytes(randomNumber);

		return randomNumber;
	}
}

//HMACxx sınıfına key verilmezse tamamen rastgele değer üretir

/*HMACxx sınıfına verilecek parametrenin uzunluğu olarak 64 bit
 kullanılması öneriliyor. Düşükse tamamlanır, fazlaysa kırpılır.
*/

public static byte[] ComputeHMACSHA1(byte[] toBeHashed, byte[] key)
{
	using (var hmac = new HMACSHA1(key))
		return hmac.ComputeHash(toBeHashed);
}

public static byte[] ComputeHMACSHA256(byte[] toBeHashed, byte[] key)
{
	using (var hmac = new HMACSHA256(key))
		return hmac.ComputeHash(toBeHashed);
}

public static byte[] ComputeHMACSHA512(byte[] toBeHashed, byte[] key)
{
	using (var hmac = new HMACSHA512(key))
		return hmac.ComputeHash(toBeHashed);
}

public static byte[] ComputeHMACMD5(byte[] toBeHashed, byte[] key)
{
	using (var hmac = new HMACMD5(key))
		return hmac.ComputeHash(toBeHashed);
}

> Şifre Depolama Yöntemleri

  • Şifresiz Kayıt

Kesinlikle uygulanmaması gereken depolama şekli. Eğer şifrelenmesi gereken veriniz şifresiz bir şekilde yolculuk ediyor ve gideceği noktada yine şifrelenmemiş bir şekilde kayıt altında tutuluyorsa, sisteminizde çok büyük güvenlik zafiyeti vardır. Sisteme erişim halinde hassas verileriniz çıplak bir şekilde sergileniyor olacak (plain text).

Clear Text Storage

  • Encryption

Uygulamalarımızda hassas verilerin veritabanına şifreli olarak kaydedilmesi, veritabanına erişim sonrası yaşanacak sorunları bir nebze azaltacaktır. Fakat encrypt edilen bir verinin, tekrar kullanımı için decrypt edilmesi lazım. Yani şifre oluşturulurken kullanılan anahtar sözcüğün (key) de yönetimi söz konusu. Veritabanına kaydedilmiş şifreli verinin decrypt edilememesi gerekir. Çünkü anahtar çalınırsa tüm kilitler açılır.

Encryption

  • Hash

Encryption'dan daha güvenilir ve kullanışlı olan hash yönteminin de kendince sorunlar var. Önce artılarına bakalım; hash işlemi geri çevrilemediği için şifrelenmeden önceki halinin ne olacağı bilinemiyor böylece sisteme sızılması durumunda veriler kötü niyetli kişiler için anlamsız oluyor. Ayrıca key kullanılmadığı, tamamen rastgele değerler üretildiği için key management gibi bir sorun da yok.

  1. Brute Force Attack : Saldıran kişi, farklı kombinasyonlarla üretilmiş hash değerini sisteminizde kaydedilmiş herhangi bir kayıtla eşleşmesi için sürekli deneyecektir. Kulağa eşleşmesi neredeyse imkansızmış gibi geldiğinin farkındayım fakat teknolojinin nimetlerinden yararlanarak milyonlarca kaydı çok kısa süre içerisinde çoktan eşleştirmiş oluyorlar (o yüzden kullanılmış, herkes tarafından bilinen 12345 gibi şifreleri kullanmayın).
  2. Rainbow Table Attack :  Farklı şifrelerin hashlenmiş hallerini üzerinde bulunduran büyük bir kaynak (key-value ve GB'larca olması mümkün) ve bu kaynaktan sisteme girilmeye çalışıldığını düşünün,
  • Salted Hashes

Hash kullanarak yarattığınız değerlere kendi kombinasyonlarınızı da uygulayabilirsiniz. Mesela hash'lemek istediğiniz parametrenin byte dizisi ile yine kendi yarattığınız rastgele (random) sayıların byte dizisini birleştirebilir (combine) ve bu birleşimi hash'leyebilirsiniz. Böylece Brute Force ve Rainbow Table saldırılarında önceden hashlenmiş değerlerin sizinki ile uyuşması, ya da tahmin edilebilir olması zorlaşacaktır.

Password Salt Hashing

public static byte[] GenerateSalt()
{
	const int saltLength = 32;

	using (var randomNumberGenerator = new RNGCryptoServiceProvider())
	{
		var randomNumber = new byte[saltLength];
		randomNumberGenerator.GetBytes(randomNumber);

		return randomNumber;
	}
}

private static byte[] Combine(byte[] first, byte[] second)
{
	var value = new byte[first.Length + second.Length];

	Buffer.BlockCopy(first, 0, value,0, first.Length);
	Buffer.BlockCopy(second, 0, value, first.Length, second.Length);

	return value;
}

private static byte[] HashPasswordWithSalt(byte[] toBeHashed, byte[] salt)
{
	using (var sha256 = SHA256.Create())
	{
		return sha256.ComputeHash(Combine(toBeHashed, salt));
	}
}
  • Password-Based Key Derivation Function (PBKDF2)

Hash fonksiyonun salt ile birlikte kullanımı bile bizim için yeteri kadar güvenli bir ortam oluşturmuyor. Bunun sebebi ise her geçen gün işlemcilerin veya bilgisayarların giderek daha da hızlanması ile Brute Force ve Rainbow Table saldırılarının tehlikeli boyutlara gelmiş olması (bkz. Moore Yasası) Haliyle bize daha güvenli bir yöntem lazım. Burada devreye RSA Public Key Cryptographic Standards serisi devreye giriyor. Diğer adı Internet Engineering Task Force's RFC 2898'dır.

PBKDF, parametreyi (şifrelenecek veri, password) alır, üstüne salt ekler daha sonra ise belirtilen sayıda algoritmanın üreteceği değeri daha da karmaşık hale getirir. Böylece saldırılara karşı daha da güvenilir, karmaşık ve denendiği halde eşleşmesi çok daha uzun süre alacak bir değer üretilecektir. (LastPass, şifrelerinizi tek bir yerde toplayan ve yönetilebirliği artıran bir uygulama. JavaScript client için 5bin, server-side için 100bin iterasyon kullanmış bkz. LastPass Password Iterations (PBKDF2))

NOT

  1. 64bit (8byte) salt uzunluğu öneriliyor,
  2. Sisteminizi performans açısından zorlamayacak sayıda yineleme (iterasyon) işlemi yapılmalı,
  3. Moore Yasası baz alınırsa, her iki senede yineleme sayısını iki kat artıracak şekilde işlemlerinizi gerçekleştirin,
  4. Salt hiçbir yöntemde gizli olma zorunluluğu taşımaz.

PBKDF2

static void Main(string[] args)
{
	string password = "Kompleks Şifre Örneği";

	HashPassword(password, 100);
	HashPassword(password, 1000);
	HashPassword(password, 10000);
	HashPassword(password, 100000);

	Console.Read();
}

public static byte[] GenerateSalt()
{
	using (var randomNumberGenerator = new RNGCryptoServiceProvider())
	{
		var randomNumber = new byte[32];
		randomNumberGenerator.GetBytes(randomNumber);

		return randomNumber;
	}
}

private static void HashPassword(string passwordToHash, int iterationNumber)
{
	Stopwatch stopwatch = new Stopwatch();
	stopwatch.Start();

	var hashedPassword = HashPassword(Encoding.UTF8.GetBytes(passwordToHash), GenerateSalt(), iterationNumber);

	stopwatch.Stop();

	Console.WriteLine($"Parametre : {passwordToHash}");
	Console.WriteLine($"Parametrenin Hash'li Hali : {Convert.ToBase64String(hashedPassword)}");
	Console.WriteLine($"Yineleme sayısı : {iterationNumber}, geçen süre : {stopwatch.ElapsedMilliseconds} ms");
	Console.WriteLine();
}

private static byte[] HashPassword(byte[] password, byte[] salt, int iterationNumber)
{
	// Rfc2898DeriveBytes sınıfı PBKD fonksiyonudur
	using (var rfc2898 = new Rfc2898DeriveBytes(password, salt, iterationNumber))
		return rfc2898.GetBytes(32);
}

Çıktısı =>

PBKDF2 Örnek Çıktısı

> Simetrik Şifreleme (Symmetric Encryption)

Çift yönlü şifrelemede kısaca değindik, birazdan farklı şifreleme tekniklerine bakacağız ama yine de kısaca değinelim.

Hızlı, güvenilir fakat yine ortada anahtar olan, anahtar ile tüm şifrelemelerin çözülebildiği bir şifreleme türü. Tüm simetrik şifreleme sınıfları SymmetricAlgorithm abstract sınıfını miras alır. Hızlı ve güvenlidir. Encrypt ve decrypt işlemlerinde aynı anahtarı kullanıyor olmasından ötürü simetrik denmektedir.

Simetrik Şifreleme

  • Data Encryption Standard (DES)
    IBM tarafından geliştirilmiştir. 64 bitlik key vardır fakat algoritma 56 bitlik kısmını kullanır. Güvenilirliğini test etmek için açılan meydan okuma yarışmasının (DESCHALL) 96. gününde şifre kırılmıştır. (Yarışma ve yaşanan hack olayı için daha fazla bilgiyi bu kitapta bulabilirsiniz => Brute Force: Cracking the Data Encryption Standard)

    DES
    static void Main(string[] args)
    {
    	string password = "Kompleks Şifre Örneği";
    
    	var key = GenerateRandomNumber(8);
    	var iv = GenerateRandomNumber(8);
    
    	var encrypted = Encrypt(Encoding.UTF8.GetBytes(password), key, iv);
    	var decrypted = Encoding.UTF8.GetString(Decrypt(encrypted, key, iv));
    
    	Console.WriteLine($"Orijinal hali : {password}");
    	Console.WriteLine($"Şifrelenmiş hali : {Convert.ToBase64String(encrypted)}");
    	Console.WriteLine($"Şifresi çözülmüş hali : {decrypted}");
    
    	Console.Read();
    }
    
    private static byte[] GenerateRandomNumber(int length)
    {
    	using (RNGCryptoServiceProvider randomNumberGenerator = new RNGCryptoServiceProvider())
    	{
    		var randomNumber = new byte[length];
    		randomNumberGenerator.GetBytes(randomNumber);
    
    		return randomNumber;
    	}
    }
    
    private static byte[] Encrypt(byte[] dataToEncrypt, byte[] key, byte[] iv)
    {
    	using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
    	{
    		des.Key = key;
    		des.IV = iv;
    
    		using (MemoryStream memoryStream = new MemoryStream())
    		{
    			CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateEncryptor(), 
    										CryptoStreamMode.Write);
    
    			cryptoStream.Write(dataToEncrypt, 0, dataToEncrypt.Length);
    			cryptoStream.FlushFinalBlock();
    
    			return memoryStream.ToArray();
    		}
    	}
    }
    
    private static byte[] Decrypt(byte[] dataToDecrypt, byte[] key, byte[] iv)
    {
    	using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
    	{
    		des.Key = key;
    		des.IV = iv;
    
    		using (MemoryStream memoryStream = new MemoryStream())
    		{
    			CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateDecryptor(), 
    											CryptoStreamMode.Write);
    
    			cryptoStream.Write(dataToDecrypt, 0, dataToDecrypt.Length);
    			cryptoStream.FlushFinalBlock();
    
    			return memoryStream.ToArray();
    		}
    	}
    }
    DES

  • Triples DES
    DES'in güvenilirliği sorgulanmaya başladıktan sonra yeni bir şifreleme algoritmasının temelleri de atılmış oldu. DES'e göre en büyük farklılığı yine DES'i uyguluyor olması fakat üstüne farklı 2-3 anahtarın ekleniyor olması. Birinci adımda anahtar ile oluşturulan şifreye, ikinci anahtar eklenerek tekrardan şifreleniyor (2. veya 3. anahtar. Şifrelenmiş halinden orjinal haline geri döndürmek için kullandığınız anahtar sırasını tersten işlemeniz gerekiyor.)

    Triple DES
    static void Main(string[] args)
    {
    	string password = "Kompleks Şifre Örneği";
    
    	// 3 key kullanımı
    	// 24 / 8 = 3 tane 64bit anahtar
            // 32 verirseniz hata alırsınız. Maksimum : 3 anahtar
    	// UNUTMA : 56bit kullanılıyor
    	var key = GenerateRandomNumber(24);
    	var iv = GenerateRandomNumber(8);
    
    	var encrypted = Encrypt(Encoding.UTF8.GetBytes(password), key, iv);
    	var decrypted = Encoding.UTF8.GetString(Decrypt(encrypted, key, iv));
    
    	Console.WriteLine($"Orijinal hali : {password}");
    	Console.WriteLine($"Şifrelenmiş hali : {Convert.ToBase64String(encrypted)}");
    	Console.WriteLine($"Şifresi çözülmüş hali : {decrypted}");
    
    	Console.Read();
    }
    
    private static byte[] GenerateRandomNumber(int length)
    {
    	using (RNGCryptoServiceProvider randomNumberGenerator = new RNGCryptoServiceProvider())
    	{
    		var randomNumber = new byte[length];
    		randomNumberGenerator.GetBytes(randomNumber);
    
    		return randomNumber;
    	}
    }
    
    private static byte[] Encrypt(byte[] dataToEncrypt, byte[] key, byte[] iv)
    {
    	using (TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider())
    	{
    		tripleDES.Key = key;
    		tripleDES.IV = iv;
    
    		using (MemoryStream memoryStream = new MemoryStream())
    		{
    			CryptoStream cryptoStream = new CryptoStream(memoryStream, tripleDES.CreateEncryptor(), 
    											CryptoStreamMode.Write);
    
    			cryptoStream.Write(dataToEncrypt, 0, dataToEncrypt.Length);
    			cryptoStream.FlushFinalBlock();
    
    			return memoryStream.ToArray();
    		}
    	}
    }
    
    private static byte[] Decrypt(byte[] dataToDecrypt, byte[] key, byte[] iv)
    {
    	using (TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider())
    	{
    		tripleDES.Key = key;
    		tripleDES.IV = iv;
    
    		using (MemoryStream memoryStream = new MemoryStream())
    		{
    			CryptoStream cryptoStream = new CryptoStream(memoryStream, tripleDES.CreateDecryptor(), 
    										CryptoStreamMode.Write);
    
    			cryptoStream.Write(dataToDecrypt, 0, dataToDecrypt.Length);
    			cryptoStream.FlushFinalBlock();
    
    			return memoryStream.ToArray();
    		}
    	}
    }
    Triple DES

  • Advanced Encryption Standard (AES)
    DES'in yerini alması için 2001 yılında kullanılmaya başlanmıştır. DES'in aksine Feistel Network kullanmaz. 128 bit girdi, 128, 192 veya 256 bitlik anahtar (sırasıyla 10, 12,14 yineleme yapar) kullanır. AES, en çok güvenilen şifreleme yöntemlerinden birisidir. Değiştirme-Karıştırma yöntemi ile çok karmaşık bir değer üretilir. Şifrenin kırılması için gerekli süre adına şuan bulunan süper bilgisayarlar kullanılsa bile evrenin yaşından daha fazla vakit alacağı söyleniyor. (256bit = 1.1x1077 ihtimal)

    AES

    static void Main(string[] args)
    {
    	string password = "Kompleks Şifre Örneği";
    
    	var key = GenerateRandomNumber(32);
    	var iv = GenerateRandomNumber(16);
    
    	var encrypted = Encrypt(Encoding.UTF8.GetBytes(password), key, iv);
    	var decrypted = Encoding.UTF8.GetString(Decrypt(encrypted, key, iv));
    
    	Console.WriteLine($"Orijinal hali : {password}");
    	Console.WriteLine($"Şifrelenmiş hali : {Convert.ToBase64String(encrypted)}");
    	Console.WriteLine($"Şifresi çözülmüş hali : {decrypted}");
    
    	Console.Read();
    }
    
    private static byte[] GenerateRandomNumber(int length)
    {
    	using (RNGCryptoServiceProvider randomNumberGenerator = new RNGCryptoServiceProvider())
    	{
    		var randomNumber = new byte[length];
    		randomNumberGenerator.GetBytes(randomNumber);
    
    		return randomNumber;
    	}
    }
    
    private static byte[] Encrypt(byte[] dataToEncrypt, byte[] key, byte[] iv)
    {
    	using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
    	{
    		aes.Key = key;
    		aes.IV = iv;
    
    		using (MemoryStream memoryStream = new MemoryStream())
    		{
    			CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), 
    										CryptoStreamMode.Write);
    
    			cryptoStream.Write(dataToEncrypt, 0, dataToEncrypt.Length);
    			cryptoStream.FlushFinalBlock();
    
    			return memoryStream.ToArray();
    		}
    	}
    }
    
    private static byte[] Decrypt(byte[] dataToDecrypt, byte[] key, byte[] iv)
    {
    	using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
    	{
    		aes.Key = key;
    		aes.IV = iv;
    
    		using (MemoryStream memoryStream = new MemoryStream())
    		{
    			CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), 
    										CryptoStreamMode.Write);
    
    			cryptoStream.Write(dataToDecrypt, 0, dataToDecrypt.Length);
    			cryptoStream.FlushFinalBlock();
    
    			return memoryStream.ToArray();
    		}
    	}
    }
    AES

> Asimetrik Şifreleme (Asymmetric Encryption)

Simetrik şifrelemenin hızlı ve güvenilir olduğundan bahsetmiştik fakat anahtar yönetimi sorunu mevcut. Anahtara sahip kişinin verebileceği hasar, tüm şifreleri kırabilmesiyle başlıyor. Bunun çözümü asimetrik şifrelemede. Asimetrik şifreleme de iki çeşit anahtar var. Birisi açık (public) diğeri ise kapalı (private). Bu iki anahtar birbiri ile (matematiksel olarak) bağlantılı ve sadece private anahtarın saklanması gerekiyor. Public key herkesin erişimine açıkken, private key sadece alıcıya aittir. Public key ile encrypt, private key ile decrypt yapılıyor. Peki private key'in ele geçirilmesi ile yaşanacak sorunlar nasıl önleniyor? Şöyle; private key'e sahip olan kişi, hangi public key'e bağlı olduğunu bilmiyor çünkü anahtar değişimi yok. Simetrik şifrelemeye göre dezavantajı ise işlemin daha yavaş olması. Sebebi ise daha kompleks bir yapıda olması.

Asimetrik Şifreleme

  • RSA (Rivest, Shamin ve Adelman)
    • İsmini, tekniğin mucitlerinden almaktadır. RSA Security LLC firmasının bir ürünüdür,
    • RSA, diğer simetrik şifrelemelerle kullanılabilir. Birazdan hibrit şifrelemede bu konuya değineceğim,
    • 1024, 2048 ve 4096 bit anahtar kullanır. Günümüz koşullarında en az 2048 bitlik anahtar kullanılması öneriliyor. 1024 bitlik anahtar zayıf görülüyor,
    • Açık ve kapalı anahtarlar asal sayı temellidir,
    • Encryption ve decryption işlemleri matematik operasyonlarından oluşuyor, yavaş olmasının sebebi de budur (modüler matematik, çarpımların ayrımı, iki asal sayının çarpımı).

      İki farklı kullanımı mevcut. İlki, XML çıktı alabileceğiniz (ToXmlString()) veya in-memory saklayabileceğiniz provider kullanmak diğeri ise Microsoft'un kendi konteyner (container) yapısını kullanmak. Böylece yaratılan key kullanıcıya bağlanabilir, kullanıcı silindiği zaman bu bilgiler de silinir. Diğer bir avantajı ise korumak istediğiniz bir uygulamayı, sistemi veya birden fazla uygulama grubunu korumak için bir kullanıcıya (örnek : admin) bunu bağlamak. NOT : Yaratılan keyler açık şekilde bilgisayarda tutulmamalı.
private RSAParameters _publicKey;
private RSAParameters _privateKey;

private void AssignKey()
{
	using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
	{
		// Konteyner kullanımı
		rsa.PersistKeyInCsp = false;
		// Public için parametre false
		_publicKey = rsa.ExportParameters(false);
		// Private için parametre true
		_privateKey = rsa.ExportParameters(true);
	}
}

private byte[] EncryptData(byte[] dataToEncrypt)
{
	byte[] cipherBytes;

	using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
	{
		rsa.PersistKeyInCsp = false;
		// Encrypt için public
		rsa.ImportParameters(_publicKey);

		cipherBytes = rsa.Encrypt(dataToEncrypt, false);
	}

	return cipherBytes;
}

private byte[] DecryptData(byte[] dataToDecrypt)
{
	byte[] plain;

	using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
	{
		rsa.PersistKeyInCsp = false;

		rsa.ImportParameters(_privateKey);
		// Decrypt için private
		plain = rsa.Decrypt(dataToDecrypt, true);
	}

	return plain;
}

               Konteyner kod örneği =>

const string ContainerName = "Konteyner";

private void AssignKey()
{
	CspParameters cspParams = new CspParameters(1);
	cspParams.KeyContainerName = ContainerName;
	cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
	cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";

	var rsa = new RSACryptoServiceProvider(cspParams) { PersistKeyInCsp = true };
}

private byte[] EncryptData(byte[] dataToEncrypt)
{
	byte[] cipherBytes;

	var cspParams = new CspParameters { KeyContainerName = ContainerName };

	using (var rsa = new RSACryptoServiceProvider(2048, cspParams))
		cipherBytes = rsa.Encrypt(dataToEncrypt, false);

	return cipherBytes;
}

private byte[] DecryptData(byte[] dataToDecrypt)
{
	byte[] plain;

	var cspParams = new CspParameters { KeyContainerName = ContainerName };

	using (var rsa = new RSACryptoServiceProvider(2048, cspParams))
		plain = rsa.Decrypt(dataToDecrypt, false);

	return plain;
}

// Konteynerdaki anahtarları silme işlemi
//private void DeleteKeyInCsp()
//{
//    var cspParams = new CspParameters { KeyContainerName = ContainerName };
//    var rsa = new RSACryptoServiceProvider(cspParams) { PersistKeyInCsp = true };

//    rsa.Clear();
//}

> Hibrid Şifreleme (Hybrid Encryption)

  • Simetrik şifrelemede anahtar paylaşımı riskli,
  • Asimetrik şifrelemede ise simetrik şifrelemeye göre anahtar paylaşımı daha güvenilir fakat işlem yavaş.

İki şifreleme yönteminin de dahil edildiği, daha güvenilir ve iyi bir çözüm sunmak adına hibrid şifreleme yapmak mümkün. Simetrik şifreleme anahtarının asimetrik şifreleme (RSA gibi) ile şifrelenmesi. Ortaya çıkan bu unique anahtara Session Key denir. Örnek için AES + RSA kodu yazılabilir, tekrar tekrar yazmamak adına pas geçiyorum.

> Dijital İmza (Digital Signature)

Kriptografinin ilkeleri konusunda bahsedilen reddedilmeme ilkesi dijital imza ile alakalıdır. Dijital imza, size, yaratılan mesajın bir sahibi olduğunu ve buna güvenmeniz için gerekli sebepleri barındırdığını belirten ibaredir. Kısacası dijital imza, uygun bir private key ile bir kullanıcı tarafından yaratıldığının en belirgin ve güvenilir ifadesidir. Asimetrik şifreleme tabanlıdır.

  • Public ve private key'lerden oluşur,
  • İmzalama işlemi private key ile gerçekleşir,
  • Doğrulama işlemi public key ile gerçekleşir.

.NET Framework'te dijital imza 3 sınıf kullanır:

  1. RSACryptoServiceProvider,
  2. RSAPKCS1SignatureFormatter,
  3. RSAPKCS1SignatureDeformatter.

Bu sınıflar verimizin doğruluğunu ve güvenilirliğini sağlar.

static void Main(string[] args)
{
	var document = Encoding.UTF8.GetBytes("Top Secret Document");
	byte[] hashedDocument;

	using (var sha256 = SHA256.Create())
		hashedDocument = sha256.ComputeHash(document);

	AssignKey();

	var signature = SignData(hashedDocument);

	// True olursa kodumuz sorunsuz çalışmış demektir
	// Verify oldu = true
	var isVerified = VerifySignature(hashedDocument, signature);

	Console.Read();
}

private static RSAParameters _publicKey;
private static RSAParameters _privateKey;

private static void AssignKey()
{
	using (var rsa = new RSACryptoServiceProvider(2048))
	{
		rsa.PersistKeyInCsp = false;
		_publicKey = rsa.ExportParameters(false);
		_privateKey = rsa.ExportParameters(true);
	}
}

private static byte[] SignData(byte[] hash)
{
	using (var rsa = new RSACryptoServiceProvider(2048))
	{
		rsa.PersistKeyInCsp = false;
		rsa.ImportParameters(_privateKey);

		var rsaFormatter = new RSAPKCS1SignatureFormatter(rsa);
		rsaFormatter.SetHashAlgorithm("SHA256");

		return rsaFormatter.CreateSignature(hash);
	}
}

private static bool VerifySignature(byte[] hash, byte[] signature)
{
	using (var rsa = new RSACryptoServiceProvider(2048))
	{
		rsa.ImportParameters(_publicKey);

		var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
		rsaDeformatter.SetHashAlgorithm("SHA256");

		return rsaDeformatter.VerifySignature(hash, signature);
	}
}

Yukarıdaki örnekte verify işlemi sırasında hashedDocument değişkenindeki byte dizisi değerinden herhangi birisini değiştirmeniz sonucun false olmasına sebep olacaktır çünkü orijinal değerden farklı olacaktır.

NOT : Hibrid yöntemle kodunuzu genişletmeniz mümkün.

> SecureString

  • System.String kütüphanesi güvenli bir çözüm değil,
  • System.String kütüphanesi bazı sorunlar barındırmaktadır
    • Bellekte birden fazla kopya,
    • Şifreli değil,
    • Değiştirilebilir

Yukarıda belirtilen sorunlar bildiğimiz string veri tipinde tutulan hassas veriler için geçerli. System.String kullanımı yerine SecureString kullanımı tavsiye edilir.

  • SecureString bellekte şifreli tutulur (erişildiğinde şifresiz hale gelir),
  • GarbaceCollector bellekte gezinirken müdahale etmez, tek kopası bulunur,
  • IDisposable interface eklentisi var,
  • Pointer kullanımı mümkün (char array).

SecureString'in varlığı hassas bilgiyi string üzerinde tutmamanız için vardır. Hassas bilgi dışında kullanmamanız tavsiye edilir. Arka yapıda DPAPI kullanır.

Data Protection API (DPAPI)

  • DPAPI, şifreleme ile veri güvenliği sunar (şifre ve private key),
  • İşletim sistemi seviyesinde güvenlik sağlar yani başka kütüphanelere gereksinim duymaz,
  • Parola bazlı veri güvenliği sunan bir servistir. Güvenliğin sağlanması için parola gereklidir (giriş yapan kullanıcının parolası),
  • Crypt32.dll'in bir parçasıdır, tüm Windows işletim sistemlerinde bulunur,
  • DPAPI şifrelenmiş veriyi sizin için saklamaz, saklama işlemi için kendi depolama kodunuz olmalı,
  • DPAPI kullanıcının giriş bilgilerini kullanır,
  • Master Key adında güçlü bir anahtar (TripleDES ile) üretir. Bu anahtarı da üretirken kullanıcının parolasını kullanır. Bu anahtar da depolanmaz ve bir süre sonra kullanım ömrü dolar.
static void Main(string[] args)
{
	var str = ToSecureString(new[] { '1', '3', '5' });

	char[] charArray = CharacterData(str);

	// Baştaki orijinal verilere ulaşıyoruz
	string unsecureString = ConvertToString(str);

	Console.Read();
}

private static SecureString ToSecureString(char[] str)
{
	var secureString = new SecureString();

	Array.ForEach(str, secureString.AppendChar);

	return secureString;
}

private static char[] CharacterData(SecureString secureString)
{
	char[] bytes;
	var ptr = IntPtr.Zero;

	try
	{
		ptr = Marshal.SecureStringToBSTR(secureString);
		bytes = new char[secureString.Length];

		// Unmanaged bellekten char dizisine
		Marshal.Copy(ptr, bytes, 0, secureString.Length);
	}

	finally
	{
		if (ptr != IntPtr.Zero)
			// Unmanaged bellek temizleniyor
			Marshal.ZeroFreeBSTR(ptr);
	}

	return bytes;
}

// Hassas verinin tekrar string'e dönüştürülmesi önerilmez
// Bellekte birden fazla kopyası olması mümkün hale gelir
private static string ConvertToString(SecureString securePassowrd)
{
	var unmanagedString = IntPtr.Zero;

	try
	{
		// Unmanaged belleğe kopyalanıyor
		unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassowrd);

		return Marshal.PtrToStringUni(unmanagedString);
	}

	finally
	{
		Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
	}
}

GÜNCELLEME
.NET Framework 4.7 ile gelen ve bu konuyu ilgilendiren bazı değişiklikler var

  • Improved support of RSA decryption with hardware keys,
  • Opening a cryptographic key with CspParameters.ParentWindowHandle set to this.Handle will now correctly make any PIN or password prompt be modal to the current window,
  • Enabled ClickOnce signing scenarios where certificate is identified by a cryptographic provider and private key container names.

Yeni Windows 10 SDK Kullanıma Hazır

Windows 10

Microsoft'un Creators Update olarak adlandırdığı kod adı ise Redstone 2 olan son ve büyük Windows 10 güncellemesi hazır. Bu güncelleme ile beraber Windows 10'un versiyonu 1703 (15063.13) olarak güncellendi. Yeni güncellemenin gelmesi demek, Windows 10'a yeni özellikler, yeni build numarası, yeni emulatorlar demek. Dolayısıyla biz yazılım geliştiriciler için güzel haberler var. Haberin sonunda sizlere gerekli bilgileri ve araçları nerelerden edinebileceğinize dair bağlantı listesi vereceğim.

Bir önceki yazımda sene sonuna kadar çıkacak 3 büyük güncellemeden birisi olduğunu, lansmanı yapıldığında biz geliştiriciler için özellikle görsel anlamda yenilikler kattığını belirtmiştim. Bunun yanı sıra Bluetooth geliştirmeleri, Desktop Bridge iyileştirmeleri, yeni paylaşma deneyimi, Project Rome, uygulama güvenliği adına Windows Hello eklentisi gibi yenilikleri de var. Liste aslında Windows 10'un yeniliklerinden daha fazla ve heyecan verici. Windows 10'u çıkış tarihinden (11 Nisan) önce indirmeniz için Windows Upgrade Assistant uygulamasını kullanmanız gerekiyor. Bir kaç gün daha beklerseniz değişen hiçbir şey olmayacak.

Ayrıca .NET Framework 4.7 duyuruldu. (Ekstradan Developer Tools ekranları, dokümantasyon sisteminde de geliştirmeler yapıldı.)

NOT : Visual Studio 2017'ye yeni SDK'yı ve yeni emülatörleri yüklemenin en kolay yolu Visual Studio Installer kullanıp "Individual components" sekmesinden  Windows 10 SDK (10.0.15063.0) for UWP ve Windows 10 Mobile Emulator (Creators Update) seçeneklerini eklemek.

  1. Windows Blog yenilik listesi için buraya
    https://blogs.windows.com/buildingapps/2017/04/05/windows-10-creators-update-creators-update-sdk-released/#y1MUh2RvkLAsGxud.97
  2. Windows 10 versiyon 1703 - Mart 2017 yenilik listesi için buraya
    https://docs.microsoft.com/en-us/windows/uwp/whats-new/windows-10-version-1703
  3. Windows 10 version 1703 yeni API listesi için buraya
    https://docs.microsoft.com/en-us/windows/uwp/whats-new/windows-10-version-1703-api-diff
  4. Windows 10 SDK indirmek için buraya
    https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk
  5. .NET Framework 4.7 yenilikler listesi
    https://github.com/Microsoft/dotnet/blob/master/releases/net47/README.md