28 Ekim 2013 Pazartesi

C de Play Fair Şifrelemesi

Bu programda PLAY FAİR şifrelemesinin C kodunu yazacağız.

Kodun Kısa Açıklaması:


Kullanıcıdan anahtar metnini istiyoruz ve metnin uzunluğunu hesaplıyoruz. Bu programda öteleme işlemlerini kullanacağımız için her dizinin bitiş indisini tutuyoruz. Anahtarı aldıktan sonra içinde tekrar eden harfleri siliyoruz. Bu silme işlemini de bahsettiğimiz gibi sola bir kere öteleme yaparak hallediyoruz. Tekrarları sildikten sonra bu dizinin harflerini başta tanımladığımız alfabe dizisinden çıkartıyoruz. Tekrarları sildiğimiz dizinin elemanlarını alfabe dizisinin başına kopyalamamız gerekiyor. Bunun için de alfabe dizisini sağa doğru ötelememiz gerekiyor(tekrarsız kalan harf sayısı kadar). Alfabe dizisinin başına gerekli kopyalamaları yaptıktan sonra bu diziyi tabloya atıyoruz.

Kullanıcıdan şifrelenecek metni girmesini istiyoruz ve ikili olarak kontrole başlıyoruz. İkililerden aynı karakter olan varsa arasına yine öteleme işlemi yaparak ‘X’ karakterini yerleştiriyoruz. Tüm diziye bunu uyguladıktan sonra eğer en son eleman tek kalmışsa dizi sonuna da ‘Z’ karakterini ekliyoruz. Fakat bu son eleman da ‘Z’ ise programımızın sonsuz döngüye girmesini engellemek için ‘X’ karakterini ekliyoruz. Şifreleme işlemine geldiğinde ise her ikili karakterleri bir anda tabloda arıyoruz. Bulduğumuz karakterlerin adreslerini tablo adlı 2x2 lik matriste tutuyoruz. Örneğin HC ikilisini arıyoruz ve bulduğumuzda H karakterinin satır numarasını tutac[0][0] ’a H karakterinin sutun numarasını  tutac[0][1] ‘e ;  C karakterinin satır numarasını tutac[1][0] ’a C karakterinin sutun numarasını  tutac[1][1] ‘e  kaydediyoruz. Daha sonra bunların aynı satırda-sütunda olup olmadığına bu tutaç matrisini kullanarak bakıyoruz ve hemen şifrelenmiş şeklini şifrelenmiş string’i tutacak diziye atıyoruz. Bu işlemleri şifrelenecek string’in sonuna kadar yapıyoruz ve şifreyi ekrana yazdırıyoruz.

Kodun Ayrıntılı Açıklaması:


     Problemin çözüm kısmında öncelikle kullanıcıdan anahtar olacak metni büyük harflerle girmesini istiyoruz ve strlen fonksiyonunu kullanarak girilen dizinin son karakterinin indisini buluyoruz. Daha sonra ilk işimiz girilen bu anahtardaki tekrar eden harfleri çıkartmaktır. Bunu da bir while döngüsü kullanarak yapıyoruz. While döngüsünde aynı harflerin olup olmadığına bakıyoruz. Eğer aynı harfler varsa ikinci olarak bulunan harfi silmemiz gerekiyor. Bu işlemi de o harfin olduğu yere bir kere öteleyerek yapıyoruz. Burada ötelemeden sonra i değişkenini bir azaltmamızın sebebi sildiğimiz harfin üstüne aynı harf geldiği zaman tekrar silmesi gerektiğidir.

     Bahsettiğim başa dönme olayından dolayı bu işlemleri en başta for ile değil de while ile yaptık çünkü for döngüsündeki i değişkenine müdahale etmemiz gerekecekti ve for döngüsünde bu azaltma işlemini yapmak hiç sağlıklı değildir.

     Anahtar dizimizdeki tekrarlı harfleri çıkarttıktan sonra geriye kalan harfleri alfabe dizisinden çıkartmamız gerekiyor çünkü tablomuza alfabede kalan harfleri sırayla ekleyeceğiz.
Tabloya ekleyeceğimiz harfleri alfabe dizisinden alacağız. Bu yüzden sırayla, önce tekrar eden harfleri çıkarttığımız dizideki harfleri alfabe dizisine almalıyız. Bunu da yapmak için öncelikle alfabeden sildiğimiz harf kadar sağa öteleme yapmalıyız ki alfabe dizisinin başına tekrarsız harfleri ekleyebilelim.

     Öteleme işlemini yaptıktan sonra anahtar dizisinde kalan harfleri sırayla alfabe dizisine atıyoruz. Artık alfabe dizisini tabloya atarak şifre metinini kullanıcıdan istiyoruz.

     Bu bölümde öncelikle girilen string’i ikili parçalara ayırıp aynı harf ikililerinin olup olmadığına bakıyoruz. Eğer böyle ikililer varsa o ikililerin arasına ‘X’ karakterini yerleştiriyoruz.  Bu işlemi dizinin sonuna kadar yapıyoruz. Bu işlemleri tamamladıktan sonra eğer en sonda tek karakter kaldıysa onu  ikili yapmak için string’in sonuna ‘Z’ ekliyoruz ve dizinin uzunluğunu bir arttırıyoruz. Eğer son eleman da ‘Z’ ise dizinin sonuna sonsuz döngüyü engellemek için ‘X’ karakterini ekleriz.  Dizilerde son elemanı tutmaktaki amaç öteleme yaptığımız zaman kalan elemanların da diziye dâhil olduğu fakat kullanılmadığından dolayı dizinin asıl son elemanını bulabilmemiz. Görsel amaçlı olarak kullanıcıya burada bir de şifrelenecek string’in son halini gösteriyoruz.

     En son olarak geriye string’i şifrelemek kalıyor. İ değişkenini 0’dan dizi uzunluğuna kadar ikişer olarak arttırıyoruz. Bunu yapmamızdaki amaç her ikilileri bir adımda bulacağımız için teker teker gitmeye gerek kalmamasıdır. Tutaç adlı 2x2 lik matrisimiz bize bulunan harflerin tablodaki indislerini gösterecektir.

Örneğin:

2
4
1
3




     Yukarıdaki tablo bulunan birinci harfin satır sayısının 2 Sütun sayısının 4 olduğunu, ikinci harfin de satır sayısının 1 sütun sayısının 3 olduğunu gösteriyor.

     Programın devamında24’e kadar giden bir t değişkeni tanımladık. Bu bize bulunduğumuz satır ve sütunu verecek. Eğer burada for döngüsü kullansaydık her eleman için 25 elemanı da kontrol etmek zorunda kalacaktık. Örneğin t=13 durumunda satır sayısını 13/5 den 2, sütun sayısını da 13 (mod5 )‘ten 3 olarak bulacağız. Şifrelenecek iki harfin de Satır ve sütun numaralarını bulduktan sonra aynı satır-sütunda olduğuna ya da olmadığına bakıyoruz. Eğer aynı satırdalarsa yanlarındaki, aynı sütundalarsa altlarındaki, ikisi de değilse köşelerindeki elemanları alıyoruz. Bunu tüm stringi dolaşarak yapıyoruz ve bulduğumuz her şifreli harfleri şifre için tanımladığımız diziye atıyoruz. En son da şifrelenmiş string’i ekrana yazdırıyoruz ve programımızı bitiriyoruz. 

Programın Kaynak Kodu:







#include <stdio.h>
#include <stdlib.h>

int main() {
	char tablo[5][5];
	char anahtar[25];//GİRİLECEK ANAHTAR İÇİN KULLANILACAK DİZİ
	char sifrelenmis_dizi[25];//ŞİFRELENEN HARFLERİN YAZILACAĞI DİZİ
	int tutac[2][2];//TABLODA ARANIP-BULUNAN 2 HARFİN ADRESLERİNİN TUTULACAĞI DİZİ
	char alfabe[25]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','X','V','W','Y','Z'};
	char sifrelenecek_dizi[30];//ŞİFRELENMEK İÇİN GİRİLEN DİZİ
	int i,j,k,t,indis;
	int anahtar_dizi_sonu;//ANAHTAR DİZİSİNİN SON İNDİSİNİ TUTAN DEĞİŞKEN
	int alfabe_sonu=24;
	int sifrelenecek_dizi_uzunlugu;
	int sifre_onay=0;
	
	printf("Lutfen anahtar metnini buyuk harflerle giriniz !!\n");
	scanf("%s",&anahtar);
	anahtar_dizi_sonu=strlen(anahtar)-1;
	i=1;
	while(i<=anahtar_dizi_sonu){
		j=0;
				while(anahtar[j]!=anahtar[i] && j<i){
					j++;
				}
				if(j!=i){
						for(k=i;k<anahtar_dizi_sonu;k++){
							anahtar[k]=anahtar[k+1];
						}
						anahtar_dizi_sonu--;
						i--; 
				}
		i++;
	}//AYNI HARFLER BULUNUP DİZİDEN ÇIKARTILIYOR
	for(i=0;i<=anahtar_dizi_sonu;i++){
		j=0;
			while(anahtar[i]!=alfabe[j] ){
				j++;
			}
				for(k=j;k<alfabe_sonu;k++){
					alfabe[k]=alfabe[k+1];
				}
					alfabe_sonu--;
	}//GİRDİĞİMİZ ANAHTARDAKİ HARFLER ALFABEDEN ÇIKARTILIYOR	
	for(i=alfabe_sonu;i>=0;i--)
	{
		alfabe[i+anahtar_dizi_sonu+1]=alfabe[i];
	}//SİLİNEN HARFLER KADAR ALFABE DİZİSİNİ SAĞA ÖTELİYORUZ VE ANAHTARDAKİ HARFLERE YER AÇIYORUZ
	
	for(i=0;i<=anahtar_dizi_sonu;i++){
		alfabe[i]=anahtar[i];
	}//ALFABE DİZİSİNDE AÇTIGIMIZ YERLERE TEKRARSIZ ANAHTAR HARFLERİMİZİ YERLEŞTİRİYORUZ
	printf("\nGirdiginiz anahtarin tekrarsiz harfli formati asagidaki gibidir:\n\n");
	for(i=0;i<=anahtar_dizi_sonu;i++){
		printf("%c",anahtar[i]);
	}
	strcpy(tablo,alfabe);//ALFABE DİZİMİZİ TABLOYA YERLEŞTİRİYORUZ
	printf("\n\nAnahtar yerlestirilmis tablo asagidaki gibidir!!\n\n");
	for(i=0;i<5;i++)
	{
		for(j=0;j<5;j++){
			printf("%c ",tablo[i][j]);
		}
			printf("\n");
	}
	
	
		printf("\nLutfen sifrelenecek metni giriniz!!\n");
		scanf("%s",&sifrelenecek_dizi);
		sifrelenecek_dizi_uzunlugu=strlen(sifrelenecek_dizi);
		indis=0;
		while(indis<sifrelenecek_dizi_uzunlugu){
				if(sifrelenecek_dizi[indis]==sifrelenecek_dizi[indis+1]){
					for(j=strlen(sifrelenecek_dizi)-1;j>indis;j--){
						sifrelenecek_dizi[j+1]=sifrelenecek_dizi[j];
					}
							sifrelenecek_dizi_uzunlugu++;
							sifrelenecek_dizi[indis+1]='X';
		  		}
				else{
					indis=indis+2;
	        	}
		}//AYNI HARF OLAN İKİLİLER VARSA ARAYA 'X' YERLEŞTİRİYORUZ
		
		
			if(sifrelenecek_dizi_uzunlugu%2==1){
				if(sifrelenecek_dizi[sifrelenecek_dizi_uzunlugu-1]=='Z'){
					sifrelenecek_dizi[sifrelenecek_dizi_uzunlugu]='X';
					sifrelenecek_dizi_uzunlugu++;	
				}//EN SON HARF 'Z' İSE SONUNA 'X' EKLİYORUZ
				else{
					sifrelenecek_dizi[sifrelenecek_dizi_uzunlugu]='Z';
					sifrelenecek_dizi_uzunlugu++;	
				}//EN SON HARF TEK KALMIŞSA SONUNA 'Z' EKLİYORUZ
						
			}
		
    
		printf("\nGirdiginiz metnin sifrelenmeye uygun son hali :\n\n");
		for(i=0;i<sifrelenecek_dizi_uzunlugu;i++){
				if(i%2==0&&i!=0){
						printf("-");
				}
				printf("%c",sifrelenecek_dizi[i]);
		}
		printf("\n\n ***ACIKLAMALAR***\n");
		
		for(i=0;i<sifrelenecek_dizi_uzunlugu;i=i+2){
				for(k=i;k<i+2;k++){
					t=0;
						while(sifrelenecek_dizi[k]!=tablo[t/5][t%5]){
								t++;
				   		}
			    		tutac[k%2][0]=t/5;
			    		tutac[k%2][1]=t%5;
				}
			if(tutac[0][0]==tutac[1][0]){
				sifrelenmis_dizi[i]=tablo[tutac[0][0]][(tutac[0][1]+1)%5];
				sifrelenmis_dizi[i+1]=tablo[tutac[1][0]][(tutac[1][1]+1)%5];
	printf("\n%c ve %c ayni satirdadirlar!!\n",tablo[tutac[0][0]][tutac[0][1]],tablo[tutac[1][0]][tutac[1][1]]);
			}//AYNI SATIRDALARSA
			else{
				if(tutac[0][1]==tutac[1][1]){
				
				sifrelenmis_dizi[i]=tablo[(tutac[0][0]+1)%5][tutac[0][1]];
				sifrelenmis_dizi[i+1]=tablo[(tutac[1][0]+1)%5][tutac[1][1]];
       printf("\n%c ve %c ayni sutundadirlar!!\n",tablo[tutac[0][0]][tutac[0][1]],tablo[tutac[1][0]][tutac[1][1]]);
				}//AYNI SUTUNDALARSA
				else{
					sifrelenmis_dizi[i]=tablo[tutac[0][0]][tutac[1][1]];
					sifrelenmis_dizi[i+1]=tablo[tutac[1][0]][tutac[0][1]];
printf("\n%c ve %c ayni satir-sutunda degildirler!!\n",tablo[tutac[0][0]][tutac[0][1]],tablo[tutac[1][0]][tutac[1][1]]);
				}//AYNI SATIR VEYA SUTUNDA DEĞİLLERSE
			}
		}
		printf("\n\nMetnin sifrelenmis hali asagidaki gibidir:\n");
		for(i=0;i<strlen(sifrelenmis_dizi);i++){
				if(i%2==0&&i!=0){
						printf("-");
				}
				printf("%c",sifrelenmis_dizi[i]);
		}	
	return 0;
}

 

Programın Ekran Çıktıları:

























Hiç yorum yok:

Yorum Gönder