Fırat Esmer

ANLATILAN SENİN HİKAYENDİR - KARL MARX

Microsoft Cognitive Services - Text Analytics API

Microsoft'un Build 2016'da açıkladığı Microsoft Cognitive Services'ı duymamış olabilirsiniz, kısa bir özet geçeyim; Microsoft, yapay zeka (AI / Artifical Intelligence) yarışında diğer firmalarla kıyasıya mücadele ediyor ve bunu sektörde kullanıma hazır hale getirmek için geliştiricilere bir takım API'ler sunuyor. Bu API'ler Azure'da barınan, belli bir kullanıma kadar ücretsiz olup sonrasında kullanım başına hesap ödediğiniz servislerden fazlası değil.
 
Şu an için 5 kategori altında 30'a yakın servis var. Kategoriler:
  • Vision (Vizyon) : Yüz ifadelerinden duygulara, uygulamaların resim ve videolardan veri elde etmesi,
  • Speech (Konuşma) : Gürültü filtresi ile kullanıcıları tanımlama, konuşulanları analiz etme,
  • Language (Dil) : Metni işleyip, kullanıcıların neyi nasıl istediklerini öğrenmek,
  • Knowledge (Bilgi) : Web, akademik ya da kendi verilerinizden toplanan zengin bilgileri analiz edin,
  • Search (Arama) : Bing API'lerinin gücü ile milyarlarca web sayfasına, resimlere, videolara ve haberlere erişin.
Bir kaç servis örneği vereyim:
  • Face API (Yüz API'si) : Fotoğraflardaki yüzleri algılayın, tanımlayın, çözümleyin, düzenleyin ve etiketleyin,
  • Computer Vision API (Görüntü İşleme API'si) : Görüntülerden eyleme dönüştürülebilir bilgiler çıkarın,
  • Text Analytics API (Metin Analizi API'si) : Duyguları ve konuları kolayca değerlendirerek kullanıcıların ne istediğini anlayın,
  • Emotion API (Duygu Tanıma API'si) : Duygu tanıma ile kullanıcı deneyimlerini kişiselleştirin.
Soru : Neden servise ihtiyacımız var?
AI veya Machine Learning konusunda tek başımıza pek de efektif işler çıkaramamamız sebep gösterilebilir. Servisi bize sunan Microsoft'un hem AI hem de Machine Learning konusunda araştırmalar yaptığı, halihazırda bir çok müşterisi ve test etmek için de milyonlarca verisi mevcut. Dolayısıyla bize altın tepside sunulan bu fırsatın kullanılması bizim yararımıza olacaktır.
 

Soru : Neden Azure?

Çünkü, bugün (özellikle Microsoft) her şeyin buluta taşınması gibi bir çılgınlık söz konusu. Aslında bunun bize sağladığı faydalar da var. İlki, her yerden erişilebilir ve stabil olması. İkincisi ise kullandığın kadar öde söz konusu olduğu için kullanımı da epey kolay.
 
Soru : API ne işe yarayacak?
Sosyal medyada bir ürün/hesap hakkında veya mağazada bulunan uygulamanız hakkında yapılan yorumların ne duygular içerdiğini, insanların nasıl tepkiler verdiğini ölçebilirsiniz. Aslında, size herhangi bir konuda API veren her platformda bu API'yı kullanabilirsiniz. Buna GitHub'da yapılan yorumlardan, veri tabanında bulunan herhangi bir alana karşı kullanmak da mümkün.
 
Makalemizde Text Analytics / Metin Analiz API servisini kullanacağız. (Tüm servisler ve kategorileri görmek için buraya bakabilirsiniz.)

Text Analytics API / Metin Analiz API'si

Servis 3 ayrı bölümden oluşmakta. Bunlar:

  • Sentiment analysis (Duygu analizi) : API, 0 ile 1 arasında bir sayısal puan döndürür. Puanın 1’e yakın olması yaklaşımın olumlu olduğunu, 0’a yakın olması ise olumsuz olduğunu gösterir.
    Örnek : Bilmiyorum ifadesi 0.5, Seni seviyorum ifadesi ise 0.98... puan döndürüyor.

  • Key phrase extraxtion (Anahtar tümcecik ayıklama) : API, giriş metnindeki başlıca konuşma noktalarını gösteren bir dize listesi döndürür.
    Örnek : Anahtar tümcecik ayırma işlemi Türkçe dil desteği yok. ("Supplied language is not supported. Pass in one of: de,en,es,fi,fr,it,ja,pl,pt-BR,pt-PT,sv.") fakat İngilizce örnek vermek gerekirse I had a wonderful experience! The rooms were wonderful and the staff was helpful (Harika bir deneyimdi! Odalar harika ve personel yardımcıydı) ifadesinin anahtar tümceleri wonderful (harika), experience (deneyim), staff (personel), rooms (odalar).

  • Language Detection (Dil algılama) : API, algılanan dile ek olarak 0 ile 1 arasında bir sayısal puan döndürür. Puanın 1’e yakın olması, tanımlanan dilin %100 olasılıkla doğru olduğunu gösterir. 120 dil desteği mevcut.
    Örnek : Merhaba, benim adım Fırat ifadesi için Türkçe ve 1.0 puan değer dönüyor.

Metin Analiz API'sini deneyebileceğiniz bir sayfa mevcut, bakmak isterseniz buraya tıklayın.

Şimdi, servisi 3 ayrı bölümde inceleyelim. Çünkü üçünün de farklı request/response json verileri mevcut.

ÖNEMLİ NOTLAR

  • Senaryo : Basit bir console uygulaması ile belirli ifadeleri analiz edip, bilgi edinebileceğimiz bir uygulama yapacağız,
  • Visual Studio 2017 kullanacağım / .NET Framework 4.7 (uygulama indirme linkini sonda paylaşacağım),
  • Servisi kullanabilmek için (sizi şimdilik Azure Portal'e sokmayacağım) API anahtarını ve Azure sunucu bilgisini buradan alabilirsiniz,
  • Yüklemeniz gereken NuGet Package'ın adı "Microsoft.Azure.CognitiveServices.Language" (DİKKAT : Include Prelease kutusunu seçin)

Microsoft Azure Cognitive Services Language

Servisi kullanmadan önce ayar yapmamız gerekiyor. Ayarlarda dikkat edilmesi gereken 2 husus var.

  1. Azure Region (Bölge) bilgisinin API'yi aldığınız region ile bir olması,
  2. Subscription Key (API anahtarı) size verilen ile birebir olmalı.
            ITextAnalyticsAPI client = new TextAnalyticsAPI();
            client.AzureRegion = AzureRegions.Westcentralus;
            client.SubscriptionKey = "SİZİN KEY'İNİZ";

Text Analytics API

Sentiment Analysis / Duygu Analizi

Duygu analizi kısmında yapmamız gereken tek şey API'nin istemiş olduğu parametreleri sağlamak.
Parametreler

  • Dil : Duygu analizinin yapılacağı dil (TR = Türkçe verdik),
  • Id : Sıradan bir Id, takip edebilmeniz için,
  • Text : Analiz edilecek ifade
            #region Duygu Analizi
            SentimentBatchResult sentimentResults = client.Sentiment(
                new MultiLanguageBatchInput(
                    new List<MultiLanguageInput>()
                    {
                        new MultiLanguageInput("tr", "0", "Çok güzeldi, çok beğendim."),
                        new MultiLanguageInput("tr", "1", "Kesinlikle gitmeyeceğim."),
                        new MultiLanguageInput("tr", "2", "Nasıl olacak bilemiyorum?"),
                        new MultiLanguageInput("tr", "3", "Hiç beğenmedim, çok kötüydü."),
                    }));

            foreach (var document in sentimentResults.Documents)
                Console.WriteLine("Doküman Id: {0}, Duygu Skoru: {1:0.00}", document.Id, document.Score);
            #endregion
Ve sonuç aşağıdaki gibi
Text Analytics API Sentiment Results

Key Phrase Extraction / Anahtar Tümcecik Ayıklama

Anahtar kelimeleri ifademizden ayırabilmek için verilmesi gereken parametreler duygu analizi ile aynı parametreler. Dil, Id ve ifade.

Anahtar kelime ayırma Türkçe dil desteği bulunmadığı için İngilizce ifadeler kullanacağım. Bunlar
Last night I had too much to drink = Dün gece içmek için çok fazla şeyim oldu
I've got a bike. You can ride it if you like = Bir bisikletim var. İstersen sürebilirsin
You reached for the secret too soon = Sırra çok erken ulaştın
No dark sarcasm in the classroom = Sınıfta alaya yer yok

            KeyPhraseBatchResult keyPhraseResults = client.KeyPhrases(
                new MultiLanguageBatchInput(
                    new List<MultiLanguageInput>()
                    {
                          new MultiLanguageInput("en", "1", "Last night I had too much to drink."),
                          new MultiLanguageInput("en", "2", "I've got a bike. You can ride it if you like."),
                          new MultiLanguageInput("en", "3", "You reached for the secret too soon."),
                          new MultiLanguageInput("en", "4", "No dark sarcasm in the classroom.")
                    }));


            foreach (var document in keyPhraseResults.Documents)
            {
                Console.WriteLine("Doküman Id: {0} ", document.Id);

                Console.WriteLine("Anahtar kelimeler:");

                foreach (string keyphrase in document.KeyPhrases)
                    Console.WriteLine(keyphrase);

                Console.Write(Environment.NewLine);
            }

Sonuç aşağıdaki çıktı

Text Analytics API Key Phrase Results

Language Detection / Dil Algılama

Dil algılamayı en başta yapsam daha sağlıklı olurdu, çünkü verilen ifadenin önce dilini öğrenip ondan sonra Duygu ve Tümcecik Ayırma analizi yapmak en doğru yol fakat tümcecik ayırma analizinde TR dil desteği olmadığı için ayrı ayrı yapma fikri daha ağır bastı.
Dil algılama servisinin bizlerden istediği iki parametre var: Id ve ifade (text).
            LanguageBatchResult languageResult = client.DetectLanguage(
                    new BatchInput(
                        new List<Input>()
                        {
                          new Input("1", "This is a document written in English."),
                          new Input("2", "Este es un document escrito en Español."),
                          new Input("3", "Bu doküman Türkçe yazılmıştır.")
                        }));

            // Printing language results.
            foreach (var document in languageResult.Documents)
                Console.WriteLine("Doküman Id: {0} , Dil: {1}, Yakınlık {2:0.00}", 
                    document.Id, document.DetectedLanguages[0].Name, document.DetectedLanguages[0].Score);
Text Analytics API Language Detection Results
 
Dil algılama işlemini tamamladık, metin analiz servisini tamamen kullandık. Hepsi bu kadar. Siz de Microsoft'un API kullanımı için hazırladığı örnek kod sayfasına (C#) göz atmak isterseniz buraya, servis dokümanını incelemek isteseniz ise buraya tıklayın.
 Projeyi indirmek için tıklayınız : TextAnalyticsAPIDemo.7z (2,50 mb)

Bitcoin ve Decentralized Yapıya Giriş (Biraz da Blockchain)

Bu makalede adından sürekli söz ettiren Bitcoin ve Bitcoin'in kullandığı merkezi olmayan (dağıtık) teknolojik altyapıyı inceleyeceğiz. Borsa ve politik konularda yorum yapmayacağım, işin teknik kısmı ile ilgileneceğiz.

Bitcoin (BTC)

Bitcoin Nedir?

Kendi tabirleriyle : Bitcoin açık kaynaklıdır; tasarımı halka açıktır, kimse Bitcoin'e sahip değildir ve onu kontrol edemez, herkes katılabilir.

Bitcoin, merkezi olmayan, insanların dünyanın herhangi bir noktasından diğer bir noktasına anonim bilgilerle transfer veya alışveriş yapabildiği dijital para birimidir. Ulusal para birimlerinin aksine Bitcoin'in merkezi yoktur. Yani, paranın basıldığı bir darphane veya yetkili bir merci (ne devlet ne banka ne de şirket) yok. Bunun yerine dağıtık bir sisteme sahiptir. Bu sistemde Bitcoin yazılımı (node) kullanılır. Bu yazılım, diğer yazılımlarda yapılan işlemleri (para transferi) ve blokları (sonra değineceğim) onaylar. Kısacası herkesin çalıştığı bir komün düşünün. Sisteme dahil olanlara bookkeeper (finans işlemlerini kayıt eden / muhasebeci) denir. Daha sonra miner / madenci diyeceğiz.

Muhasebeciler (bookkeepers) en temel seviyede defter (defter-i kebir, büyük defter) tutarlar. Bu defter yapılan işlemlerin kayıtlarını tutar. Bitcoin'in hangi hesaptan hangi hesaba ne kadar yollandığının kaydı tutulur. Yapılan her işlemin kaydı herkese açıktır. Az önce saydığım 3 kriteri (kimden, kime, ne kadar) herkes görebilir, bunun için sisteme dahil olmanıza bile gerek yok.

Bitcoin'in değerini belirleyen şey arz-talep dengesidir ve diğer adından bahsetmeyeceğim parametrelerdir. Üretilecek Bitcoin sayısı bellidir 21 milyon BTC. Dolayısıyla bir dönem kıtlık yaşanacak. Çünkü kıtlığı aşmak için Bitcoin üretecek bir merkez bulunmayacak. Bunun yanı sıra kullanımı kolay, hızlı, ucuz ve güvenlidir. Güvenliğin aşılabilmesi için ya sizin hesabınıza (cüzdan) girmeleri gerekir ya da muhasebeciler defterde kayıtları manipüle etmeli. Manipüle etmek de kolay değil çünkü dağıtık bir ağ olduğu ve yapılan işlemlerin tümü şeffaftır ve herkesin onayına açıktır. Böylece işlemin validasyonu (oy verme) da yine diğer katılımcılar tarafından sağlanacaktır (Muhasebecinin defterini tüm geçmişiyle birlikte indirmek mümkün).

Bitcoin Güvenliği

Bitcoin'in bize kazandırdığı kavramların başında cryptocurrency (dijital para birimi) gelmekte. Aslında bu ismi güvenliği sağlamak adına arka planda gerçekleştirdiği algoritmalardan alır.

Bir hesaptan diğer hesaba para aktarma işlemi esnasında bu transfer işlemi kriptografik dijital imza ile imzalanır. Böylece muhasebeciler bu transfer işlemini onaylamak için ellerinde kanıt bulundurmuş olurlar. Kriptografik dijital imzayı bir kağıda atılan ıslak imza gibi düşünebilirsiniz. Her işlem için farklı imzalar yaratılacağı için kullanılmış bir imzayı tekrar kullanamazlar veya imzanın herhangi bir noktasında değişiklik yapamazlar. Sebebi ise kullanılan anahtarlar ve bu anahtarların validasyonu gerçekleştirecek diğer kullanıcılarda bulunması.

NOT : Kriptografi ile ilgili bilginiz yok ve merak ediyorsanız daha önce yazdığım yazıya göz atabilirsiniz. Bitcoin SHA256 algoritmasını kullanıyor.

Her bir Bitcoin hesabı veya adresi aslında public key tabanlıdır. Transfer işleminde kullanılan dijital imzalama işlemi ise private key tabanlıdır. Geri kalan işlem ise muhasebecilerin validasyon işlemini gerçekleştirmesidir.

Neden Merkeziyetçi Değil?

Merkeziyetçilik örneği -konu bağımsız- tepeden aşağı inmeciliktir. Bu da sorunları beraberinde getirir. Gücün tek bir elde toplanması, sizin elinizde tuttuğunuz paranın (ne olursa olsun) değerinin bu güç tarafından istenilen zamanda değiştirilebilir olduğu anlamına gelir. Örneğin; ABD'nin merkez bankası FED'in alacağı kararlar doğrultusunda cebinizdeki doların değeri değişmektedir. İnternet, özünde özgürlüğü barındırır. Merkeziyetçi olmayan sisteme bir örnek daha vermek gerekirse Torrent. Torrent dünyası P2P (peer-to-peer) kişiden-kişiye dediğimiz sistemle çalışır. Dosyalar, o dosyayı download/upload eden kişilerden sağlanır. Dolayısıyla bir kişinin dudaklarından çıkacak lafın gücü, bu dünyada yer edinemez. Bitcoin de P2P sistemle çalışır. Bitcoin'in de gücü aslında buradan gelmektedir. Asıl inovasyon burada yatmakta.

Merkeziyetçiliğin Dezavantajları

  • Kötüye kullanım,
  • Saldırılara açık,
  • Sansür uygulanabilir.

Merkezi Olmayan Sistemin Avantajları

  • Şeffaf ve kayıt tutulabilir,
  • Hızlı ve kolay (e-posta atmak kadar),
  • Daha az maliyetli,
  • Sınır tanımaz.

Muhasebeciler

Bookkeepers dediğimiz kişilerin bu ağda edindikleri bir görev var. Bu kişiler belli ücretler veya ödüller karşılığında yapılan finansal işlemlerin doğruluğunu onaylar. Peki, muhasebecileri hile yapmasına engel olan (mesela kendi hesabına para ekleme) şey nedir? Bunun için önce Bitcoin'in piyasaya sürülmesi ile ilgili bir kaç bilgi vereyim. Tüm para; 21 milyon BTC üretilecek demiştik. Üretilene kadar her geçen sürede yeni paranın üretilmesi süreci git gide yavaşlamakta. Bunun sebebi ise BTC üretmek için gerekli algoritmaların her üretim sonrasında git gide zorlaşması. Daha fazla zaman ve makine gücü gerekiyor. Son para 2140 yılında kadar üretilecek. Şimdi gelelim asıl soruya, muhasebecinin buna engel olmasına sebep olan şey nedir veya iki farklı muhasebeciden iki farklı sonuç (defter) gelirse ne olacak?

Merkeziyetçi sistemde -örnek olarak PayPal'i ele alalım- yapılan finansal işlemler belli bir sıraya göre işleme konur fakat dağıtık sistemde farklı zamanlarda farklı muhasebecilerin önüne düşer.

Hesabımda 5 BTC olduğunu düşünün. Bunu önce Eren'e, onaylanmadan da Sevda'ya gönderdiğimi düşünün (bkz. double spend). Farklı muhasebecilerin önüne farklı sıra ile düşeceği için parayı aslında kimin tutması gerektiğini bilemeyecekler ve burada bir sorun oluşacak.

Bitcoin dünyasının bu soruna yaklaşımı için fikir birliğine varması gerekiyor. Çözüm; finans işleminin doğru olup olmadığının oylanması yani validasyon. Fakat kimliksiz bir dünyada bir muhasebecinin birden fazla oy vermesi nasıl engellenecek? Bunun çözümü, muhasebecilerin çok özel bir matematik problemini (algoritma) çözmesinde yatıyor. Bu yönteme proof-of-work denir. Bunun tabi bir bedeli var. Güç ve zaman.

"...bir işlemci bir oy (...one cpu one vote)" - Orjinal Bitcoin whitepaper (sayfa 3)

Her yeni oylama için geçen süre 10 dakikadır. Böylece tüm muhasebeciler senkron kalırlar. İşlem gruplarına block (blok) ve birbirine bağlı olan bu blokların oluşturduğu zincire de blockchain (blok zinciri) / Distributed Ledger Technology (DLT) denir. Blockchain teknolojisi ise başlı başına bir devrim. Şimdiden bir çok üniversite, startup, firma bu teknoloji üzerinde çalışmalara başladı. Şimdi blockchain içerisindeki her bloğun nasıl onaylandığına bakalım.

Blockchain içerisinde bulunan her bir block, bir önceki block'un cevabını probleme girdi olarak alır. Böylece bloklar güvenli hale gelmeden önce oy ve işlem sürecinden geçerler. Problem dediğimiz şey kriptografi dünyasından, diğer bir tabirle kırılması gereken bir problem, algoritma. Algoritma üzerinde harcanan/harcanacak olan iş yükü bellidir ve kanıtlanabilir. Sonuç olarak bir merkeze bağlı olmadan, kimliğinizi gizli tutarak oylama işlemi yapabilirsiniz. Bu da Bitcoin dünyasının sunduğu (güven ihtiyacının azaltılması) güzelliklerden sadece bir tanesi.

Güven ihtiyacının azaltılması sözünü biraz açmak istiyorum. Bir hesaptan başka bir hesaba transfer yapılırken işlemi yapacak olan kişi sadece hesap sahibi olabilir. Arada banka veya başka bir şahıs yok (borsa üzerinden yapmıyorsanız). Bir diğer konu da yüksek tutarlı işlemlerin gerçekleşmesi için gereken süre uzayabiliyor. Son olarak, sistemde yapılmak istenen değişikliğin çoğunluk tarafından kabul edilmesi de diğer bir dezavantaj. Çünkü bunu zorla kabul ettirebilecek herhangi bir merci yok. Örnek vermek gerekirse Bitcoin'in 1 Ağustos tarihinde ikiye bölünme ihtimali var(dı). Bunun için oylama katılımı yapılmakta.

NOT : Zero Confirmation Transactions kavramı onay süreci olmadan hızlıca transfer yapılmasıdır. Alışveriş yaptığınız yerde bekleme lüksünüz yoksa (market gibi) bunu kullanabilirsiniz fakat dolandırıcılığa açık bir yöntem. Bunun da önüne geçmek için bazı ödeme biçimleri mevcut fakat konuya girmeyeceğim.

Cüzdan

Cüzdan, sahip olduğunuz parayı tutan, para transfer işlemlerinizi yaparken kullanılan ve önceki işlemlerinizi listeleyen bir uygulamadan fazlası değil. Herhangi bir firmanın cüzdanını kullanabilirsiniz, yeter ki uyumlu olsun. Ethereum (başka bir coin) cüzdanı üzerinde Bitcoin tutamazsınız. Ayrıca cüzdanınızda yaşayacağınız sorunların coin ile alakası olmadığını da belirtmek isterim. Örnek transfer işlemleri veya cüzdan örnekleri için buraya tıklayabilirsiniz. Cüzdanınız web, mobil veya masaüstü tabanlı uygulamalar olabilir. Uygulamanızda QR kod okuyucu var ise ödemelerinizi daha kolay yapabilirsiniz hatta yeni yeni yerleştirilmeye başlanan Bitcoin ATM'lerini kullanabilirsiniz. Eğer cüzdanınızın şifresini unutursanız (private key'e ulaşamadığınız durum) asla tekrar paranıza kavuşamazsınız, bunu unutmayın.

Örnek bir cüzdan adresi => 1CatFTRHtMNngkdLEeobF76b57LETtpyVx

Cold Storage Cüzdan

Yüksek miktarda para barındıran hesapların cold storage denen yani internete hiç çıkmamış hesaplarda tutulması öneriliyor. Bu adreste üretilen Bitcoin cüzdanı client-side yani internete hiç dokunmamış oluyor. Böylece private-key çalınma korkunuzu da aşmış oluyorsunuz. Hatta site size sayfayı HTML olarak indirip bilgisayarınızda çalıştırmanızı öneriyor.

Donanım Tabanlı Cüzdan

Private-key'inizi internetten korumak adına başka bir yöntem ise donanım tabanlı cüzdanlar. USB ile bilgisayarınıza bağladıktan sonra uyumlu cüzdanlarla çalışan, transfer işlemleri sırasında her türlü hırsızlığı koruyan bu yöntem daha da güvenlik korkusu olanların ilacı. Hatta virüslü bir bilgisayarda bile güvenle kullanabilirsiniz. Bkz. Trezor

Yedekleme

Kısa ve öz; private-key'e erişimi olmayan (cüzdanı yaratan kişi/şirket) cüzdan tiplerinde sakın ama sakın yedeklemeyi unutmayın.

Mining (Madencilik)

İşte geldik en can alıcı noktaya. Çoğu kişinin Bitcoin'in nasıl çalıştığı, neler yaptığıyla ilgilenmeyip bir an önce madencilikten para kırmayı umduğu kısım. Öncelikle şunu söyleyeyim, diğer coin'ler için değil ama Bitcoin için çok geç. 2013 yılında olsaydık bir şeyler yapabilirdiniz ama şu an çok geç. Mining hiç efektif değil çünkü üretilecek Bitcoin'lerin çoğu üretildi ve çözülmesi gereken algoritma şu an o kadar zor noktadaki tüketilen elektrik ve makine gücü karşılığında üretilen Bitcoin'in miktarı zarar etmenize sebep oluyor (tabi Bitcoin'in değeri uçuk noktalara gelmezse, fakat gelecek gibi görünüyor). Bitcoin Mining Calculator tarzı sitelerde harcanan elektrik ve zamana göre üretilen coin ve kar oranlarını belirleyen siteler var. Neyse, konuya dönelim.

Bitcoin'i ATM, borsa, web veya direkt olarak diğer insanlardan almanın dışında bir yol daha var; mining, diğer adıyla madencilik.

Muhasebeci (Bookkeper) = Madenci (Miner)

Yazıda bunca zaman bookkeeper olarak bahsettiğim muhasebeciler aslında birer madenci. Peki neden böyle isimlendirdik? Tek sebebi daha anlaşılabilir olması için ve isminin hakkını vermesi. Muhasebecinin oylama sürecinde yaptıkları iş kadar ödül aldığı sistemden fazlası değil madencilik. Böylece dünyanın dört bir tarafına yeni Bitcoin dağıtılmış olur. Madenciliğin ekran kartı işlemcisi veya işlemcinin kullanılmasıyla yeni para üretimi olduğu gibi bir yanlış algı var fakat asıl işleri tuttukları defterin sürdürülebilirliğini sağlamak. Defterlerin sürdürülebilirliğini sağlamaktan kastım transfer işlemlenin doğrulanmasında harcadıkları emek. Emeğin karşıtı yeni para.

Soru : Madenciler transfer işlemlerindeki oylama süreci sonucu para ile ödüllendiriliyorsa para üretimi 2140 yılında bittiğinde nasıl para kazanılacak?
Her 4 senede bir para üretiminin (ödül) yarı yarıya azalacağına dair kural var. Son BTC üretiminin (2140) sonrasında ise madencilik olmayacak. Çünkü piyasaya yeni para çıkmayacak. Madenciler para transferlerini kontrol edip oylama işlemlerini yapmaya devam edecekler defterlerini senktron tutacaklar fakat para kazanamayacaklar (tabi madencilerin alacağı fikir birliği ile değişiklik olmazsa). İşlem ücreti hariç. Oylama (validasyon) işlemlerinin hızlı olması için küçük miktarlarda ödül koyabilirsiniz bunu da belirteyim.

Bu dönemde bilgisayarınızın CPU veya GPU'sunu kullanarak BTC madencilik yapmak gerçekten de hiç karlı bir işlem değil. Madencilik yapacaksanız diğer coin'lere (altcoin) bakmanızı öneririm. Markette bulunan coinlerin listesini buradan görebilirsiniz. (değeri, market hacmi vs.)

Bitcoin Yazılım Evreni

Bitcoin ilk çıktığı zaman tüm işlemleri yapan tek bir uygulama vardı. Sadece cüzdan istiyorsanız yine de tüm defteri indirmeniz gerekiyordu. Bu da gereksiz işlem ve hacim kaybına sebep oluyordu. Örneğin; defter kaydını tutmak istemiyorsunuz. Bunun için de mantıklı bir sebebiniz var; neden yapılan tüm işlemlerin kaydını tutasınız ki? Temmuz 2017'ye kadar yapılan işlemlerin defter boyutu 65 GB ve uygulamanızın depolama şekline göre 100 GB'a kadar çıkabiliyor (hatta geçebiliyor). Defteri diğer node'larla (noktalarla) paylaşmanın bedeli ise her ay yüzlerce GB'lık veri transferine sebep oluyor.

Bitcoin Core tüm defter kaydını tutan,resmi bir uygulama ve Bitcoin.org'dan indirilebilir.

Şimdi ise Bitcoin'in açık kaynak olması nedeniyle bir çok uygulama var ve ihtiyacınıza göre uygulamaları edinebiliyorsunuz. Örneğin; sadece cüzdana sahip olmak, madencilik yapmak istemiyorsanız bunun için tek bir uygulama var. Ayrıca Bitcoin kütüphaneleri Python, Java, Ruby, Go ve daha fazla popüler programlama dilini desteklemekte.

Bir diğer Bitcoin uygulaması ise BitPay imzalı bitcore uygulaması. Uygulama Javascript tabanlı, açık kaynak koda sahip.

Dijital İmzalar

Dijital imzalar public ve private key'lerin kullanılması ile oluşturulan bir sürecin çıktısıdır. Bir cüzdandan başka bir cüzdana para transferi yapılırken ortaya çıkan sürece bakalım.

Yukarıdaki dijital imza süreci; mesaj public key kullanılarak elde ediliyor ve orjinal mesaj ile eşleşiyorsa bu transfer işlemini yapan kişinin private key'i kullanılarak yapıldığını kanıtlar. Eşleşme doğruysa bu mesajın değiştirilmediğini de kanıtlamış olur. Sağlamasını şöyle yapabiliriz; imza mesajın bir parçası olduğu için ve biz yine aynı mesaja ulaştıysak, mesaj değiştirilmemiş demektir.

Dijital imzanın nasıl yaratıldığı konusunu da gördükten sonra şimdi bir işlem (transaction) yapıldığı zaman nasıl süreçlerden geçtiğine bakalım.

Bitcoin adresi : dijital imza algoritması kullanılarak oluşturulmuş bir public key.

Senaryo : Tayfun, Sevda'ya para yollamak istediğinde parayı yollayacağı adres Sevda'nın public key'i oluyor. Bu işlem sırasında bu public key'in Sevda'ya ait olduğu da üretilen imza ile tescilleniyor. Bitcoin adresi bir havuz gibi düşünebilirsiniz. İsteyen herkes bu adrese istediği miktarda para yollamakta serbest. Fakat sadece private key'e sahip kişi bu havuzun anahtarına sahip. Bu da parayı sadece Sevda'nın çekebileceği anlamına geliyor.

Soru : Private key random karakterlerden oluşuyorsa, aynı key'e sahip olmamız mümkün değil mi?
Cevap : Kağıt üzerinde mümkün fakat cüzdan oluşturmak için 1048 ihtimal mevcut.

Bitcoin İşlemleri (Transaction)

Adres ve işlem hakkında bilgi sahibi olduğumuza göre şimdi işlemlerin defterlerde nasıl kayıt edildiğine bakalım.

Defterde işlem esnasında gönderilen para miktarı görünür fakat bakiye (balance) gözükmez. O halde başka bir soru işareti doğuyor : Parayı gönderen kişinin hesabındaki para miktarını nasıl bilip işlemi onaylayacağız? Eren, Sevda'ya 5 BTC yollamak isterse hesabındaki BTC miktarını görmeden bu transaction'ı nasıl onaylarız? Şöyle : Eren'in hesabında 5 BTC olduğuna göre, birisi veya birileri Eren'e 5 BTC yollamış olmalı. Bu transactionlarda bulunup işleme katılıyor ve böylece işlem onaylanıyor. Çok fazla işlem olduğu zaman performansa yansıyacak fakat sorun indexlerle hallediliyor.

Unspent Output Kavramı

Harcanmamış çıktı, henüz başka bir transaction'ın girdisi olmayan çıktıdır. Unspent Transaction Outputs "utxo's" olarak adlandırılır. Farklı bir veri tabanında tutulur ve sık sık, kontrol amaçlı kullanılır.

Aşağıda bir örnekle açıklayayım, bunun işlemlerin hızlı gerçekleştiği (küçük blok zinciri) bir sistemde olduğunu varsayıyorum.

İlk blok : A adresinde mine edilmiş 10 BTC var. (A = 10)
İkinci blok : A adresinde mine edilmiş 10 BTC var, A adresinden B adresine 3 BTC gönderiliyor, para üstü adreste kalıyor (A = 10, B = 3, C = 7)
Üçüncü blok : A adresinde 10 BTC var, B adresinden D adresine 3 BTC gönderiliyor (A = 10 + 10, C = 7, D = 3)

Üç blok sonrası toplamda 4 tane harcanmamış çıktı (unspent output) bulunuyor

  1. A'da iki tane 10 BTC değerinde unspent output bulunuyor,
  2. C'de 7 BTC değerinde tek unspent output bulunuyor,
  3. D'de 3 BTC değerinde tek unspent output bulunuyor.

İki tane de harcanmış çıktı (spent output) mevcut

  1. İlk blokta 10 BTC üretildi, 2. blokta harcandı,
  2. 2. blokta 3 BTC çıktı üretildi ve 3. blokta harcandı.

Harcanmamış çıktılar birleşmez. A adresindeki iki harcanmamış çıkı birbirinden ayrıdır ve transaction'da kullanılana kadar ayrı kalacaklar.

NOT : Para üstünü almak da bir transaction oluyor. Dolayısıyla para üstü de paranın sahibinin adresine geri gönderiliyor. Bunun sebebi bir kerede tüm parayı harcama kuralı.

İşlem Zinciri Güvenliği

Her ne kadar cüzdan sahibinin kimliği bilinmese de yapılan işlemlerle cüzdana ulaşmak mümkün. Her para birimi değil fakat Bitcoin'de mümkün.
Bitcoin Transaction

Yukarı resim bir transaction'a ait. scriptSig denen kısım ise adres sahibi tarafından girdiler için oluşturduğu bir dijital imza. Bu imza izni içerisinde barındırıyor. Ayrıca gönderen kişinin cüzdan kimliğini de barındırıyor. Bu yüzden Bitcoin için anonim değil pseudonymous (takma isim) ifadesi kullanılır.

Soru : Bunun bizim için ne gibi sakıncası olabilir?
Cevap : Örneğin; Microsoft Bitcoin kabul ediyor olsun ve alışveriş yaparak kendinize bir ürün aldınız. Yaptığınız transaction'ı diğer transaction'larla bağlayabilir ve nelere para harcadığınızı görebilir. Bir nevi "shopping behavior" analizi elde edilebilir.

Fikir Birliği Hakkında

"Dijital" kelimesi sanki çok kolay bir şekilde çoğaltılabilirmiş anlamına geliyor. Aslında doğru, bir siteden .mp3 indirdiğinizi düşünün. Orjinali + (1) sizin indirdiğinizle beraber sayısı artmış olacak. Peki Bitcoin dünyasında bu işler nasıl yürüyor? Cüzdanınızda 10 BTC olduğunu düşünün, bunun tümünü harcadığınızı ve asıl defter yerine henüz güncellenmemiş defterle bir dükkana gidip alışveriş yapmaya çalıştığınızı düşünün. Bu durumda sahip olduğunuz + sahip olduğunuzu iddia ettiğiniz kadar paranız olacak. Daha da kötüsü, bir grup miner'ın düzenbazlık yaparak alışverişlerde hile yapmaya çalıştığını düşünün. Mümkün mü? Hayır. Güven sistemi çoğunluğa dayalı olduğu için transaction'ın valid olup olmaması belli olmayan sıralarla diğer miner'ların önüne sunulacak. O yüzden, para yaratma, nasıl validasyon edileceği, yazılım güncellemeleri vb. gibi sorular tüm minerlara yöneltilen, fikir birliğine varılan bir sistemi oluşturuyor.

Blockchain ile İşlemleri Kilitleme

Mining işleminin şifrelenmiş bir problemin çözümünden başka bir şey olmadığını söylemiştik. Altında yatan çözüm ise verilmiş bir çıktı için girdiyi bulmak, diğer bir şekilde söylemek gerekirse değer kısmında bulunan yere sürekli sayılar vererek deneme işlemi yapmak.

SHA256(X) < t ........... t / 256 = Başarı İhtimali ......... t ne kadar küçük ise işlem o kadar zor.

SHA256(ÖNCEKİ BLOCK HASH, TRANSACTIONS, değer)  < t ?
SHA256(ÖNCEKİ BLOCK HASH, TRANSACTIONS, 0)        < t ?
SHA256(ÖNCEKİ BLOCK HASH, TRANSACTIONS, 1)        < t ?

Açıklanan istatistiklere göre 2016 Ocak ayı itibariyle madenciler saniyede 1 kentilyon deneme yapıyormuş.

Bitcoin Network

Yapılan her transaction sonrasında bu transaction network'e dağıtılır fakat dağıtıldığı an gerçek kabul edilmez. Önce "onaylanmamış işlem havuzu" denen havuza düşer. Madenciler bu havuzdan transaction'ları alarak yeni bir blok adayı yaratırlar. Her madenci cevabı bulan ilk kişi olmak için yarışır ve çözüme ulaşan ilk kişi cevabı ağ ile paylaşır.  Bir kişinin cevabı bulması yeterlidir. Çünkü bir blockchain'de block bir önceki block'un hash değerini üzerinde tutar. Burada anlaşılması gereken bir konu var. Farklı transaction'lar farklı miner'ların önüne farklı zamanlarda düştükleri için bir block'un input'una verdikleri değer (çözülmüş bir block'un output'u) farklı block'tan gelmiş olabilir.

Bitcoin Fork

İki madencinin aynı anda block'u çözüp aynı sonuca ulaşması blockchain'de fork (çatallaşma bkz. yukarıdaki resim) meydana getirir. Bu sorun, hangi branch üzerinde işleme devam edileceği oylaması ile sonuçlanır. Genel kural, en uzun blockchain'in işleme alınmasıdır fakat daha fazla ve daha hızlı bilgisayarların ağa katılımı sonucu zorluk derecesi artar ve en uzun blockchain değil, çözümü en zorlu ve en ağır iş yükü olan blockchain seçilir (oluşturulur).

Çatallaşmaya ve kararsızlığa engel olmak adına kısa süreli kabul işlemleri yerine ortalama bir süre vardır bu süre 10 dakikadır.

Blockchain Onay Süreci

6 onay 6 blok geri demek ve yüksek tutarlı ödemeler için önerilen onay sayı budur.

Ortadan kaldırılan kısa branch'ler yok olmaz. Onaylanmamış işlem havuzuna geri dönerler.

Bitcoin Yaratma

Bitcoin yaratma sürecinin başında problemini çözdüğünüz bloktan blok ödülü almak yer alıyor. Bunun dışında blokta bulunan transaction'lara konan ödül (fee)'yi de alırlar. Transaction'a onaylanması adına ufak bir ödül koymak burada önem kazanıyor. Madenciler ödülü olmayan veya az olan transaction'ları (onaylanmamış işlem havuzu) görmezden gelebilir veya önemini azaltabilir.

Block'a çözüm bulmak ve blok ödülünü almak zor bir iş. Bitcoin dünyasında bunun karşılığı sizin ürettiğiniz hash yüzdesi ile ağdaki diğer insanların ürettiği hash yüzdesiyle orantılı. Bu sebeple insanlar "mining pools" denen madencilik havuzlarında beraber güç kullanarak çözüm bulmaya çalışırlar. Ödül az fakat istikrarlı. Dezavantaj => mining pool'lar özünde merkeziyetçidir. Çünkü havuz operatörleri bulunuyor. Şu an halihazırda çalışan poolların listesi (bazıları ağdaki tüm hash gücünün %10'una sahip) ve kullanım oranları için tıklayınız.

Merkeziyetçlik ve Baskı

Bitcoin'in merkeziyetçi yapıda olmaması sizi merkeziyetçi bir yapıdan kurtarmaya yetmiyor. Bu da ne demek?

Merkeziyetçi Madencilik

Bloktan ödül kazanmanın zor olduğunu söylemiştik. Ne kadar zor diye sorarsanız piyangoyu kazanmak kadar zor diyenler olacaktır. O yüzden insanların çoğu "madencilik havuzu" denen yönteme yöneliyorlar. Maden havuzları kendi sunucularını barındıran merkezi yapılardan fazlası değil. Blockchain'in nasıl oluşturulacağına karar veren, kesinti yapan ve operatörlere sahip bir sistem. Dolayısıyla sizi bazı dezavantajlar bekliyor. Operatörler sizin için işlem seçen, branch'e ve hangi yazılım versiyonunun kullanılacağına karar veren yetkililerdir. Yani kişilere güç tanınıyor, aracı ile çalışmış oluyorsunuz.

Merkeziyetçi Yazılım

Bitcoin'in kodu her ne kadar açık kaynak kod da olsa sonuçta belirli geliştiriciler ve bu geliştiricilerin ürettikleri yazılımlar var. Bu yazılımların dışına çıkıldığında (başka uygulamalar) sorunlar da beraberinde geliyor. Öncelikle şunu soralım. İnsanlar neden başka yazılımlara geçiş yapıyor? Bitcoin, block başına 1 MB veri tutabiliyor. Bu da işlem hacmi büyük bir kripto-para için sorun çünkü işlemler aksayabiliyor. Bazı programlar bundan fazlasını sunabiliyor fakat bu da transaction'ların ve block'ların reddedilmesine sebep olabiliyor çünkü yazılım orjinal değil, farklı versiyon. Bu sorun göz önüne alındığında herkes (sorunsuzca mine etmek istiyorlarsa) tek bir yazılım, orjinal yazılımı kullanmak zorunda kalıyor.

Hard Fork vs. Soft Fork

Fork (çatallaşma, ayrışma) işlemini github'daki fork gibi düşünebilirsiniz. Sizi, master branch'ten ayıran başka bir yol.

Mesela Bitcoin'in 1 MB'lık block size'ı ileride sorunlara sebebiyet verebilir. Bu sebeple madenciler arasında bir tartışma gerçekleşir. Kimileri bunun sabit kalması gerektiğini savunurken kimileri de kuralların değişmesi gerektiğini savunuyor. Bunun sebepleri başında fikirbirliğine varılamaması yatıyor. Peki bu ayrışmalar nasıl oluyor?

Hard Fork
Yazılım / kural değişir; eski yazılımın desteği olmaz.

Hard Fork
Senaryo : Blok boyutunun 2MB'a çıkarıldığını ve çoğunluğun yeni yazılımı kullandığını düşünün . Eski node'lar 1MB'tan fazla olan blokları onaylamayacak ve görmezden gelecektir. Madencilerin çoğu yeni yazılımı kullanıyor olsa da eski yazılımı kullanan azınlık kendi branch'inde devam edecektir. Eski yazılımı kullanan servisler veya cüzdanlar da bundan etkilenecektir.

Soft Fork
Yazılım / kural değişir; eski yazılımın, yapılan her transaction ve blockları destekleyeceği ayrışma biçimi.

Soft Fork

Senaryo : Blok boyutunun 2MB olduğunu ve çoğunluğun yeni yazılımı kullandığını düşünün. Eski yazılım, yeni bloğu tanımaz fakat geçerli sayar. Yeni bloklar yaratıldıkça eski yazılım farkında olmadan blok zincirini inşa etmeye çalışır fakat blok zincirine boyutu büyük bloklar gelir. Daha sonra blok zincirine yeni bloklar gelmez çünkü çoğunluğun hash gücü daha fazladır. Soft fork'un avantajı yeni yazılım tanınmasa da blok zincirine eklenir. Fakat şöyle bir karışıklık meydana gelir: eski yazılımı kullanmaya devam eden madencilerin oluşturdukları bloklar israf olacak çünkü kabul edilmeyecekler.

Bitcoin'den Fazlası

Altcoin

Bitcoin, cryptocurrency dünyasının ilk ürünü fakat şu an 800'den fazla dijital para var. Bu kadar dijital para türetmek yerine neden Bitcoin'e katkı sağlanmadı veya neden tek bir dijital para birimi yok diyorsanız altcoin dünyasına hoşgeldiniz.

Bitcoin, dünyanın dört bir yanında madencilere sahip, market hacmi ve işlem sayısı büyük bir ağ. Ağ ne kadar büyükse güncelleme işlemleri de bir o kadar zor oluyor. Dolayısıyla yeni fikirleri böylesine büyük bir ağda hayata geçirmek hem riskli hem de zor olduğu için katkı yerine yeni dijital para birimleri üretiliyor. Türetilen bu yeni dijital paralara altcoin deniyor. Altcoin'lerin bu kadar çok olmasının başka bir sebebi ise güzel fikirlerin, yanında kendi coin'i ile gelip geliştiricilere para kazandırması.

Soru : Yeni para nasıl dağıtılıyor?
Cevap : Bitcoin yavaşça para üretir ve rastgele katılımcılara madencilik yoluyla para dağıtır. Bazı dijital paralar ise ufak miktarda tedarik ile veya crowdsale / Initial Public Offering (İlk Halka Arz / IPO) ile dağıtıma başlıyor. IPO'nun yerini Initial Coin Offering (ICO) ifadesi almış durumda.

Proof-of-Work

Yazımda bir kere de olsa bahsettiğim proof-of-work mekanizmasını biraz açmak istiyorum. Anonim olarak dünyanın dört bir yanından transaction'ların oylanması mekanizması proof-of-work'e örnektir. Bunun yapılma sebebi ise defterin doğruluğunu sağlamak. Doğruluk, çoğulculuk ile elde ediliyor.

Bizans Generalleri Sorunu : Bir şehri 5 farklı yerden 5 generalle kuşatan Bizans ordularını hayal edin. Hep beraber hareket ederlerse -ister saldırı olsun ister geri çekilme- başarılı olma ihtimalleri yükselecek çünkü güçlerini birleştirmiş olacaklar. Fakat kimisi saldırıp kimisi geri çekilmeye çalışırsa muhtemelen yenileceklerdir. Bu generallerin birbirlerine bir ulak gönderip hangi kararı alacaklarını bildirdikleri sistem, proof-of-work sistemine güzel bir örnek. Çoğunluk ne karar alırsa o doğru kabul edilir ve işlenir.

Soru : Proof-of-work mekanizması sonucunda üretilen çözümler kullanışlı olabilir mi?
Cevap : Bir kaç altcoin var ki arkada mine etmeniz için çözdüğünüz algoritmalar, gerçek hayatta karşımıza çıkan sorunlara cevap olabiliyor. Mesela Primecoin (XPM), çözdüğünüz her algoritma ile asal sayıları bulmayı hedefliyor. FoldingCoin (FLDC) (mine medicine, not hashes) sağlık sektörüyle ilgili sorunlara çözüm bulmayı hedefliyor. Gridcoin (GRC) ise makinelerin gücünü bilimsel araştırmalarda kullanıyor.

Proof-of-Stake

Proof-of-Stake, Bitcoin'indeki transaction sırasına göre işlem gücüyle çözüm bulmak yerine, kaç adet paranız olduğuna bakan oylama sistemidir. Paranız çoksa, işlerin ters gitme ihtimaline karşı daha fazla risk altında olduğunuz için parası çok olanın ağda etkin olduğu bir oylama sistemi.

Bitcoin Proof-of-Work

HASH(önceki blok bilgisi, transactions, değer) < x

Peercoin (PPC) Proof-of-Stake

HASH(önceki blok bilgisi, simdiki_zaman, coin_id) < bakiye * x

Yukarıdaki algoritmada (Peercoin = başka bir altcoin) değişen tek şey zaman parametresi. Bu algoritmayı bir saniyede birden fazla kez çalıştırmaya gerek yok.

Avantajları

  • Daha az enerji tüketimi,
  • Maden havuzu ve özel donanıma ihtiyaç olmadığı için daha az merkeziyetçi,
  • Daha güvenli.

Proof-of-Stake tabanlı oylama sisteminde fork işlemlerinde blok üretmek için hiçbir yük olmayacağından kolayca branch'ler uzayıp gidebilir. Bu da tabi ileride sorunlara sebep olabilir fakat bu sorunlar  için de çözüm mevcut. Fork konusunu zaten anlattığım için pek fazla derine inmeden geçiyorum bu konuyu.

Zero Knowledge Proofs

Zero knowledge proof, transaction protokolünde paranın tutarını ve katılımcılarını (kimden ve kime) gizleyen, buna rağmen bir kişinin iki kişiye onaylanmadan aynı parayı yollamasına engel olan yöntemdir.

Soru : Hiçbir bilgi yoksa, bir kişinin aynı tutarı birden fazla kişiye yollaması nasıl engellenecek?
Cevap : Algoritma çözüldükten sonra çözümün sadece bir kısmı ki bu kısımdaki değerler de şifrelenip kontrol ediliyor.

Bu yöntemi kullanan halihazırda dijital paralar var. Bunlardan bir tanesi (şu an en popüleri) Zcash (ZEC).

Stabilite Sorunu

Dijital paralar henüz gerçek değerine ulaşamadığı için marketlerde veya diğer alışveriş lokasyonlarında fiyatın ürününü göstermekte sorunlar ortaya çıkıyor. Dolayısıyla dijital paraların dolar değerinden cinsinden, yani direkt olarak kağıt para cinsinden değerleri tutuluyor.

Smart Contracts denen kavram ise (bkz. Ethereum) para transferi yapan programların, önceden programlanmış belli kurallara göre işlem yapması. Durum burada daha da kötü. Örneğin evinizin kirasını BTC cinsinden ödüyor olun. Bugünün değeriyle 2 BTC ödeyecekken bu değer bir dahaki ay 1 BTC olabilir.

Bir dijital para, ne kadar çok kullanılırsa o kadar değeri gerçeğe yaklaşır. Şu an için dalgalanmalar mevcuttur ve normaldir. Bu duruma çözüm üretmeye çalışan başka dijital para birimleri mevcut.

Digix (DGD) : Direkt olarak Singapur'da bir kasada duran altınla eşleşmiş olan bu coin, token (para) başına 1 gram altın değer taşıyor. Gerçekten altına sahip olduğunuzu da size gönderdikleri fotoğraftan anlayabilirsiniz. Hatta Singapur'a gidip dijital paranız karşılığında değeri kadar altın alabilirsiniz. Şu an için tek kasanın olması risk barındırıyor olabilir ama işler ileride değişebilir. Not : Ethereum tabanlıdır.

Tether (USDT) : Digix'in aksine altın ile değil bildiğimiz Amerikan Doları ile ilişkili. Hesapların kayıtları tutuluyor ve hesap Honk Kong'da. Tether firmasına vereceğiniz dolar karşılığında token elde ediyorsunuz. Bunu da Bitcoin ağında tekrar Amerikan Doları'na çevirebiliyorsunuz.

Konu ile alakalı diğer dijital para birimlerinden bazıları : NuBits (USNBT), bitUSD (BITUSD)

Konuyu burada bitiriyorum. İnanın bu yeni teknolojinin detayları çok fazla ve teknik konular çok derin. Maksat bir ön bilginiz olması. Ethereum'dan da ayrı bir makalede bahsetmek istiyorum. O yüzden pek detaya inmedim.

Bitcoin ile ilgili temel sorulara (kim yaptı, yasal mı, nasıl satın alır veya alışveriş yaparım) cevap bulmak isterseniz bu sayfayı inceleyebilirsiniz => https://bitcoin.org/tr/sss

Dijital parayı destekleyin, ben öyle yapıyorum. Para transferlerinde aracı firmalara mesela legal mafya olan bankalara para vermemek, merkeziyetçi, sansürcü ve baskıcı ortamlardan özgürlükçü VE HAFTASONU BİLE FARKLI ADRESLERE IŞIK HIZINDA PARA TRANSFERİ YAPABİLECEĞİMİZ ortamlara evrilmenin önü açıldı, kimse engel olamaz.

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.