破解凯撒密码


首先来看以下恺撒密码。

离散数学的一道作业题。

凯撒密码作为一种最为古老的对称加密体制,在古罗马的时候都已经很流行,他的基本思想是:通过把字母移动一定的位数来实现加密和解密。例如,如果密匙是把明文字母的位数向后移动三位,那么明文字母B就变成了密文的E,依次类推,X将变成A,Y变成B,Z变成C,由此可见,位数就是凯撒密码加密和解密的密钥。

题目如下:

It is known that the following crypted paragraph is encryted using a slighted enhanced Caesar encryption method of the form f(p)=(ap+b)mod29.

jgc!.chr, dhdw,nbn bn kdncy oh uxc jdru uxdul bh dh, qbfch nugcurx oj mgbuuch wdhq.dqcl rcgudbh wcuucgn dhy roakbhdubohn oj wcuucgn orr.g mbuxfdg,bhq jgc!.chrbcns aogcofcgl uxcgc bn d rxdgdrubnubr ybnugbk.uboh oj wcuucgn uxdu bn go.qxw, uxc ndac jog dwaonu dww ndavwcn oj uxdu wdhq.dqcs

What is also known is the two most frequently used letters in the paragraph are t and e.The reference alphabet is an array of length 29 "abcdefghijklmnopqrstuvwxyz,.!", indicating that space is not handled during encryption (space remains space). Try to de-cypher the message and give the plaintext.


简单理解就是解密一段文字,加密方式为f(p)=(ap+b)mod29的凯撒加密方式,算是恺撒密码的加强版。字母表为"abcdefghijklmnopqrstuvwxyz,.!",且根据统计,t和e为英语中出现最多的字母。

破解的一般思路就是通过字母的频率求得对应的密钥,然后反解密文。求解过程如下。



统计字母出现

void analyze(char *c)
{
	int a[26]={0};
	int i=0,j;
	while(c[i]!='\0')
	{
		if(c[i]!='.'||c[i]!='!'||c[i]!=',')
		a[c[i]-'a']++;
		printf("%d\t",i++);
	}
	for(j=0;j<26;j++)
	{
		
		printf("%c:%d\n",j+'a',a[j]);
	}
	
}

在main中调用。

int main()
{
	char ch1[10000];
	char hash[29];
	
	printf("Input paragragh:\n");
	gets(ch1);
	analyze(ch1);
	return 1;
}

得到结果:


可治u和c为出现频率最高的两个字母。

在字母表中的顺序:

t-19 u-20 e-4 c-2

可以列出下面的式子:

(19a+b)mod29=20

(4a+b)mod29=2

但是还不能求得a和b的值,需要用一段程序枚举求得。

#include
void getA()
{
	int a,b;
	for(a=0;a<20;a++)
	{
		b=20-(19*a)%29;
		if((4*a+b)%29==2)
		printf("%d,%d\n",a,b);
	}
}
int main()
{
	getA();
	return 1;
}



得到a=7,b=3.


由于f(p)是满足双射关系的,即两两对应,可以将明暗文对应关系放在Hash表中。

char alphabet[]="abcdefghijklmnopqrstuvwxyz,.!";
void createHash(char *c,int a,int b,int d)
{
	int i;
	char encode[29];
	for(i=0;i<29;i++)
	{
		encode[i]=alphabet[(a*i+b)%d];
		printf("%c",encode[i]);
	}
	for(i=0;i<29;i++)
	{
		c[encode[i]-'a']=alphabet[i];
	}
}

这样就可以通过密文直接hash到明文了。

解密函数就最简单了。

void decypher(char *c,char *hashmap,int a,int b,int d)
{
	int i=0;
	int char_pos;//record the caractor's position
	while(c[i]!='\0')
	{
	    char_pos=c[i]-'a';
	    //printf("char_pos:%d\n",char_pos);
		if(c[i]!=' ')
		{
			printf("%c",hashmap[char_pos]);
		}
		else
		{
			printf(" ");
		}
		i++;
	}
}


完整的程序如下:

#include
void analyze(char *c);
void decypher(char *c,char *hashmap,int a,int b,int d);
void createHash(char *c,int a,int b,int d);
char alphabet[]="abcdefghijklmnopqrstuvwxyz,.!";
int main()
{
	char ch1[10000];
	char hash[29];
	
	printf("Input paragragh:\n");
	gets(ch1);
	analyze(ch1);
	printf("\nAfter decyphered:\n");
	createHash(hash,7,3,29);
	decypher(ch1,hash,7,3,29);
	
	printf("\n%s\n",ch1);
	return 1;
}
void analyze(char *c)
{
	int a[26]={0};
	int i=0,j;
	while(c[i]!='\0')
	{
		if(c[i]!='.'||c[i]!='!'||c[i]!=',')
		a[c[i]-'a']++;
		printf("%d\t",i++);
	}
	for(j=0;j<26;j++)
	{
		
		printf("%c:%d\n",j+'a',a[j]);
	}
	
}
void decypher(char *c,char *hashmap,int a,int b,int d)
{
	int i=0;
	int char_pos;//record the caractor's position
	while(c[i]!='\0')
	{
	    char_pos=c[i]-'a';
	    //printf("char_pos:%d\n",char_pos);
		if(c[i]!=' ')
		{
			printf("%c",hashmap[char_pos]);
		}
		else
		{
			printf(" ");
		}
		i++;
	}
}
void createHash(char *c,int a,int b,int d)
{
	int i;
	char encode[29];
	for(i=0;i<29;i++)
	{
		encode[i]=alphabet[(a*i+b)%d];
		printf("%c",encode[i]);
	}
	for(i=0;i<29;i++)
	{
		c[encode[i]-'a']=alphabet[i];
	}

	printf("\n%s\n",alphabet);
}

最终运行结果:


解密结果:

frequency analysis is based on the fact that, in any given stretch of written language, certain letters and combinations of letters occur withvarying frequencies. moreover, there is a charactistic distribution of letters that is roughly the same for almost all samples of that language.


你可能感兴趣的:(C&C++)