Uygulama 4 | Dosya Şifreleme / Şifre Çözme

Bu uygulamada dosya şifreleyen ve şifrelenmiş dosyayı çözen bir program yazacağız. Bunun için 'gpg' isimli bir araç kullanacağız. Açılımı 'GNU Privacy Guard - GnuPG' olan bu araç, popüler bir Linux şifreleme aracıdır.

İşe koyulmadan önce şu blogları okumanızı öneriyorum: Kriptografi Bölüm 1 ve Kriptografi Bölüm 2

Dediğim gibi, bu uygulamada 'gpg' kullanacağız ancak bunun nasıl kullanıldığını bilmiyorsak 'man gpg' diyerek bunun ne işe yaradığını, nasıl kullanıldığını görebiliriz.

Bunu kullanırken ihtiyacımız olan sadece iki şey var. Bunlardan biri '-c', biri de '-d' parametreleri. Buradaki '-c' parametresi, simetrik şifreleme yapmamıza olanak tanıyor ve bu şifrelemede, AES-128 kullanılıyor. Şifrelediğimiz bu dosyayı ise '-d' parametresi ile eski haline dönüştürebiliyoruz. Temel bilgileri aldığımıza göre işimize koyulabiliriz.

Yapmamız gereken ilk şey, kullanıcıya bir menü göstermek olmalıdır. Bu menü içerisinde şifreleme, şifre çözme ve çıkış seçenekleri bulunabilir. Bunun için de bir select döngüsü açabiliriz.

Gördüğünüz gibi klasik bir select döngüsü açtım. Bu noktada ilk önce ana dizine inmemiz lazım. Çünkü kullanıcıdan lokasyon ve dosya ismi isteyeceğiz. Bash'in bu lokasyona gidip o dosyayı bulabilmesi için ana dizinde olmalı ancak kullanıcı, o an için ana dizinde bulunmayabilir. O yüzden 'cd' diyorum.

'cd' dedikten sonra "seçilen şey 'Encryption' yani 'şifreleme' ise..." şeklinde bir if yapısı kurdum. Daha sonra kullanıcıya 'Encryption' seçeneğini seçtiğini belirten bir echo mesajı verdim.

Bunu yaptıktan hemen sonra kullanıcıdan önce dosyanın olduğu lokasyonu (location) ve şifrelenecek dosyanın adını (fileEncryption) aldık. Hemen sonrasında ise biraz önce aldığımız lokasyona 'cd $location' komutu ile gittik.

Şimdi, ikinci seçeneğimiz olan 'Decryption' kısmını yapalım. Aslında bunun için biraz önce yaptıklarımızın aynısını yapabiliriz; farklı bir şey yok zira.

Decryption kısmını da yaptıktan sonra 'Quit' kısmını da gerçekleştirdik. Eğer kullanıcı bu seçeneği seçerse ona teşekkür edip 'break' komutu ile döngüyü sonlandırıyoruz. Yukarıdaki görselde bilmediğiniz hiçbir şey yok, iyice inceledikten sonra devam etmenizi rica ediyorum.

select döngüsünü tamamladıktan sonra şimdi, Encryption ve Decryption için birer fonksiyon yazabiliriz. Çünkü eğer bunlara ait işlemleri de select içerisine yazarsak inanılmaz karışık bir yapı oluşur; bunu istemeyiz. Ondan önce önemli bir konuya değinmem lazım.

gpg ile bir dosya şifrelediğiniz zaman uzantısı '.gpg' olur. Örneğin 'deneme.txt' isimli dosyayı şifreleyince 'deneme.txt.gpg' olacaktır. Bu noktada bir siberci olarak bunu engellememiz lazım. Peki, neden?

Bir dosyayı şifrelediğinizi ve bu dosyayı birine yollayacağınızı varsayalım. Bu noktada araya giren kötü niyetli biri bu dosyayı çalabilir, elbette mümkündür. Böyle bir durumda bu dosyayı çalan kişi dosyayı açtığında şifrelenmiş bir şeyler görecektir yani dosyada ne yazdığını anlamayacaktır. Ancak uzantısına baktığında bunun 'gpg' ile şifrelendiğini anlayacak ve bunu, gpg algoritmasını kullanarak çok rahat bir şekilde çözecektir. Yukarıda söylediklerimi ispat etmeme izin verin.

Ben bu projeyi bitirmişim ve şimdi bir dosya şifreleyeceğim.

Gördüğünüz gibi isim, 'deneme.txt.gpg' olarak değişti. Ayrıca onu açtığımda saçma sapan şeylerin olduğunu görüyorsunuz. Şimdi, bu dosyayı normal uzantılı bir duruma sokalım.

Şifreli içeriği, 'secret.txt' şeklinde bir dosyaya aktardım ve ikisinin de aynı şeyi içerdiğini görüyorsunuz.

Şimdi bu 'secret.txt' dosyasını çözmeye çalışalım.

Kırmızı ok ile işaretlediğim kısımda, o şifrenin çözülmüş hâlini görüyorsunuz. Şimdi, aynı metni alacağım ve çok önceden Python ile yazdığım bir şifreleme aracına sokup bunu şifreleyeceğim. Bakalım, ne olacak?

Yukarıda gördüğünüz gibi aynı metni SHA512 ile şifreledim. Yani gpg algoritması söz konusu bile değil. Şimdi çıkan bu hash'i alıp secret.txt içerisine koyalım ve gpg ile bunu çözüp çözemeyeceğimizi görelim.

'system error' verdi ve bu hatanın üzerinde yazana bakın; 'no valid OpenPGP data found.' Yani diyor ki 'bir gpg verisi bulamadım, bu şifreyi çözemiyorum'.

Anlatabiliyorum, öyle değil mi? Eğer şifrelenmiş bir dosyanın hangi şifreleme algoritmasıyla şifrelendiğini bilmiyorsanız o şifreyi çözmeniz çok ama çok zor olur.

İşte bu yüzden biz, bu dosyanın uzantısını sileceğiz; daha doğrusu yeni bir dosya oluşturup şifrelenmiş içeriği buraya aktaracağız ve kişiye, normal gözüken bu dosyayı atacağız. Eğer dosya, yanlış bir kişinin eline geçerse en azından hangi şifreleme algoritmasının kullanıldığını anlamasını biraz zorlaştırabiliriz.

Şimdi, devam edelim. En son, Encryption ve Decryption fonksiyonlarını yazacağımızı söyledim. O yüzden ilk önce fileEncryption isimli bir fonksiyon açıyorum.

Bu fonksiyonu açtıktan sonra içine, biraz önce sözüne ettiğimiz 'gpg' komutunu ve '-c' parametresini veriyorum. Yorum satırından da anlayacağınız üzere bu, simetrik şifreleme yapmak içindi.

Hemen ardından kullanıcıyı echo ile uyarıyoruz: "Şifrelenmiş dosyanın uzantısını 'file.txt' gibi gizleyeceğiz." şeklinde bir uyarı verdim. Ardından kullanıcıdan, bu dosyanın isminin ne olmasını istediğini sordum. Bunu, "Bu yüzden, yeni gizli dosyanın ismini gir" şeklinde bir cümle kurarak yaptım.

Şimdi, "uzantısı .gpg olan dosya." tarzında bir komut vermemiz lazım. O yüzden extension="gpg" şeklinde bir komut verdim.

Bir uzantı değişkeni tanımladıktan sonra biraz önce kullanıcıdan aldığımız dosya ismiyle bir dosya oluşturuyoruz ${fileName}. Bunu, '$fileName' olarak da alabilirsiniz.

Bunları yaptıktan sonra "şifrelenmiş dosyanın içeriğini yeni yarattığımız dosyaya aktarmamız lazım". Bunun için 'cp' komutunu kullanabiliriz.

Bu komutu yazış şeklimi ilk defa gördüğünüz için komutun altında, yeşil yazıyla neler olduğunu kısaca anlatmaya çalıştım.

Burada, ${fileEncryption}, kullanıcıdan aldığımız, şifrelenecek dosyanın ismini (örneğin deneme.txt) ifade ediyor. ${extension} ise zaten 'gpg' idi. Aradaki nokta ise bunların birleşmesini ve ortaya 'deneme.txt.gpg' şeklinde bir sonuç çıkmasını sağlıyor. Bu kısım, kopyalanacak olan dosyayı kapsıyor.

Yan tarafa baktığımızda ${fileName}; kullanıcıdan, şifrelenmiş dosyanın hangi isimde görüneceğini aldığımız kısımdır. Burada, bu iki kısmı şu cümle ile özetleyebiliriz: "deneme.txt.gpg dosyasının içeriğini, $fileName dosyasına aktar".

Şimdi, bu fonksiyonumuz hazır olduğuna göre bunu, projenin başında tanımladığımız select döngüsüne ekleyebiliriz.

Şimdi de sıra, Decryption fonksiyonunu yazmakta. Bunun için 'fileDecryption' isimli bir fonksiyon açıyorum.

Burada, content=`gpg -d $fileDecryption` şeklinde bir tanımlama yapmışım; biraz önceki 'gpg -c $fileEncryption' gibi olmadı. Bunu bir değişkene atamışım. Bu noktada şifreli dosya çözüldükten sonra 'echo $content' şeklinde yazdırıyorum fakat bu çıktı, terminalde duracağı için kullanıcı terminali yanlışlıkla kapatırsa kaybolacak ve bu işlemi tekrar yapmak zorunda kalacaktır. Bunun için aklıma bir şey geldi.

Bu fonksiyonu böyle, olduğu gibi bırakalım ve içeriği başka yere taşıyan bir fonksiyon yazalım istiyorum. Yani terminaldeki yazıyı bir dosyaya aktarsın ve orada saklasın. Bu yüzden bu işlemi content isimli bir değişkene atadım; bu değişkeni kullanacağız.

Yukarıda dediklerimi yapmak için move_content isimli bir fonksiyon açıyorum.

Bu fonksiyon çağırıldığında ilk önce kullanıcıdan yeni bir dosya yaratmak ve içeriği oraya aktarmak için bir dosya ismi belirlemesini istiyoruz. Daha sonra yazdığı dosya isminin var olup olmadığını sorguluyoruz ve eğer dosya mevcutsa bunu bildiriyoruz. Kullanıcının, lazım olan bir dosyaya bu içeriği yazdırması hoş olmaz.

Bunun için eğer dosya mevcutsa kullanıcıya biraz soru sormamız ve onu biraz uyarmamız gerekiyor.

İlk önce kırmızı kutuya bakalım. "Bu işlem, dosyanın içindeki eski içeriği silecektir." şeklinde bir uyarı veriyoruz. Bir alt satırda ise read komutu ile; "Üzerine yazalım mı?" şeklinde bir soru yöneltip 'y' veya 'n' şeklinde cevap vermesini bekliyoruz.

Yeşil kutuya bakalım. Burada kullanıcı, az önceki soruya 'y' derse, 'echo > $newFile $content' komutuyla dosyanın üzerine yazıyoruz. Zaten echo'nun '>' komutunu biliyorsunuz; ne varsa siler. Sonra kullanıcıyı bilgilendiriyoruz. Buradaki $content ise, biraz önceki fonksiyonda tanımladığımız değişken oluyor; kullanacağımızı söylemiştim. Burada aslında Bash, terminaldeki çıktıyı, $newFile değişkeniyle oluşturulmuş dosyaya aktarıyor.

Mor kutuya geldiğimizde kullanıcının 'n' demesi ihtimalini değerlendirdiğimizi görüyorsunuz. Hemen sonrasında dosya zaten mevcut olduğu için başka bir dosya ismi girmesini istiyoruz. Kullanıcı, yeni ve farklı bir dosya ismi girdiğinde touch komutuyla o isimde bir dosya oluşturuyoruz. Son olarak biraz önce üzerine yazma işleminde verdiğimiz echo komutunu da veriyoruz. Burada, dosya yeni olduğu için içerisinde herhangi bir içerik de olmayacaktır. O yüzden veri kaybı tehlikesi de olmadığı için '>' ifadesiyle işlem yaptık.

Gerisi bildiğiniz şeyler.

Bu fonksiyonda son olarak, dosyanın var olmaması durumunu ele almamız lazım.

Eğer dosya yoksa, yine aynı işlemleri gerçekleştiriyoruz. Yeni bir dosya oluşturup terminaldeki içeriği, o dosyaya yazıyoruz.

Şimdi, fileDecryption fonksiyonumuza geri dönelim.

Bu fonksiyon, şifreli dosyayı çözme işini yapıyordu. Burada, "çıktıyı yeni bir dosyaya taşımak ister misin?" şeklinde bir soru sorduk ve ondan 'y' veya 'n' şeklinde cevap beklemeye başladık. Bu noktada kullanıcı eğer, 'y' derse biraz önce yarattığımız ve taşıma işlemlerini gerçekleştiren fonksiyonu çağırıyoruz (move_content).

Sonrası, bildiğiniz şeyler. Şimdi, bu kodu artık deneyelim. Kodun kesintisiz halini en aşağıda göreceksiniz.

Programı çalıştırdıktan sonra '1' seçeneğini yani 'Encryption' seçeneğini seçtim. Daha sonra benden lokasyon ve dosya ismi istedi. Bunları girdikten hemen sonra karşıma şöyle küçük bir kutucuk geldi. Burada ilk kısma parolamı, ikinci kısma da parolamı tekrar yazmam lazım. Bu noktada güçlü olmayan bir parola girerseniz sizi uyaracaktır:

Yeşil kutu içerisinde size, parolanızın güçlü/güvenli olmadığını ve parolanızın 8 karakterden uzun olması gerektiğini söylüyor. Aşağıda, kırmızı kutu içerisindeki seçeneklerden biri "Yeni parola gir - Enter new passphrase" iken diğeri, "Ne olursa olsun bunu kullan - Take this one anyway" şeklindedir, dilediğinizi seçebilirsiniz. Bu uyarı, parola kısmına '1234' yazdığım için geldi ancak ben sağdaki butona tıklayarak devam ediyorum.

Parola meselesini halledince sol üst köşede gördüğünüz gibi 'deneme.txt.gpg' şeklinde bir dosyamız belirdi. Bu dosya, şifreli bir dosyadır yani içini açsanız bile ne anlatmak istediğini anlamayacaksınızdır.

Dosya belirdikten hemen sonra, uyarımız da belirdi ve bizden yeni bir dosya ismi girmemizi istedi. Ben buraya 'secret.txt' yazacağım.

Bu işlemden sonra, sol tarafta 'secret.txt' isimli bir dosya belirdi ve içini açınca saçma sapan şeylerin olduğunu gördük; dosyamızın içeriği şifrelendi.

Şimdi bu şifreyi çözeceğiz ancak biraz düşünelim. Bunu yolladığınız kişi bu dosyanın şifresini çözebilmek için bu yazılımı kullanmalı. Dolayısıyla Decrypt ederken ona dosyanın açılması için bir parola da sorulmalı, değil mi? Dosyayı oluştururken bize parola sormasının sebebi buydu ve parolamız '1234' idi.

NOT: Bu arada secret.txt dosyası gibi deneme.txt.gpg dosyasını da bu yazılıma sokabilirsiniz. Ne de olsa ikisi de gpg algoritmasıyla şifrelendi sadece uzantıları farklı; aynı sonuçları verecektir.

İşte, Decrypt ederken bize parolayı soruyor. Buraya, onu oluştururken hangi parolayı girdiyseniz onu girmeniz lazım.

Parolayı girdikten sonra bize çıktıyı veriyor ve soruyor: "Bu içeriği yeni bir dosyaya aktarmak istiyor musun?". Buna, 'y' cevabını vereceğim.

'y' dedikten hemen sonra bana, yeni dosyanın ismini soruyor. Ben de buraya 'plaintext.txt' diyorum ve sol tarafta böyle bir dosya açılıyor. İçine bakalım.

Gördüğünüz gibi içerik, terminaldeki ile aynı.

Son olarak üçüncü seçenek olan "Quit" işlevini de kullanalım, yazık.

Çıkışımızı sağladı.

Evet, uygulamamız bu kadardı. Eğer bu kodu ödeviniz için veya GitHub hesabınıza koymak için alacaksanız lütfen kaynak bildirin. Bununla beraber anlamadığınız bir nokta olduysa lütfen iletişime geçin. Sevgiler.

Kodlar


Yayınlanma Tarihi: 2022-09-22 18:57:12

Son Düzenleme Tarihi: 2022-09-25 12:50:51