old_blog 维吉利亚加密与破译

  记得TP在上学期的程序设计周里做过一个实验,就是维吉尼亚密码加密的算法,当然,这是相当简单的。(不过TP不给力啊,我帮他完成了大部分)。
  只需要将原文字text每个字符加上固定的密钥值就行,不过为了标准化,我们的原文小写无空格,密文大写,密钥大写。原文字可以文件读入。
//代码:大河时代。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
void toL(char* m)
{
	int i;
	for(i=0;i<strlen(m);i++)
		if(m[i]>='a'&&m[i]<='z') m[i]-=32;
}
void tol(char* m)
{
	int i;
	for(i=0;i<strlen(m);i++)
		if(m[i]>='A'&&m[i]<='Z') m[i]+=32;
}
void sol(char *m,char *keyw)
{
	int i,lm,lk;
	char ch,yon;
	char c[500];
	FILE *vv;
	lm=strlen(m);
	lk=strlen(keyw);
	printf("the message is the following:(the key is %s)\n\n",keyw);
	for(i=0;i<lm;i++)
	{
		ch=m[i]+(keyw[i%lk]-65)-97;
		if(ch>25) ch-=26;
		ch+=97;
		ch-=32;
		printf("%c",ch);
		c[i]=ch;
	}
	c[lm]='\0';
	printf("\n\n\nexport the message?(y/n)");
	scanf("%c",&yon);	
	if(yon=='y'||yon=='Y') 
	{
		getchar();
		vv=fopen("message.txt","w+");
		fprintf(vv,"%s\n",c);
		printf("export success!the file name is message.txt\n");
		fclose(vv);
	}
		
	
}
void main()
{
	char m[500];
	char keyw[50];
	int choose;
	FILE *v;
	printf("1.input the text by keyboard\n2.load text by file\nplease choose:");
	scanf("%d",&choose);
	while(choose!=1&&choose!=2)
	{
		printf("enter ERROR!\n");
		scanf("%d",&choose);
	}
	getchar();
	if(choose==1) gets(m);
	if(choose==2)
	{
		printf("the file name must be text.txt,please ensure it!\n");
		getch();
		v=fopen("text.txt","r+");
		if(v==0) {printf("load ERROR!\n");getch();exit(0);}
		fscanf(v,"%s",m);
		fclose(v);
	}
	tol(m);
	system("cls");
	printf("the message is :\n%s\n\nplease enter the key:",m);
	scanf("%s",keyw);
	getchar();
	toL(keyw);
	system("cls");
	sol(m,keyw);
	getch();
}
  但是,这远远是不够的,对于一个信息安全的学生来讲,研究密码破译有着相当重要的意义。在未知密钥的情况下对于维吉尼亚加密的破解,已经有了很明确的方案。这里运用Kasiski测试法和重合指数法(ic)寻找密钥长度,再用重合指数法拟合每一位的密钥字符,最后解密。
  当然,维吉尼亚的密码破译是有前提的。第一:原文必须有意义,不能是随便输入的字符。第二,原文必须有一定的长度,一般200字母即可。密文可以文件录入,如果Kasiski测试法不能找到较为准确的密钥长度,会提示破译失败。具体使用可以看程序本身。
//代码:大河时代。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int sort(int* a,int* b,int* c,int x)
{
	int count=0,i,j,flag=1;
	int min,temp;
	for(i=0;i<x;i++)
	{
		for(j=0;j<count;j++)
			if(b[j]==a[i]) {flag=0;break;}
		if(flag) b[count++]=a[i];
		else flag=1;
	}

		for(i=0;i<count;i++)
	{	c[i]=0;
		for(j=0;j<x;j++)
			if(a[j]==b[i]) c[i]++;
	}
	for(i=0;i<count-1;i++)
	{
		min=i+1;
		for(j=i+1;j<count;j++)
			if(c[j]<c[min]) min=j;
		if(c[i]>c[min])
		{
			temp=b[i];b[i]=b[min];b[min]=temp;
			temp=c[i];c[i]=c[min];c[min]=temp;
		}
	}
	return count;
}
double ic(char *p)
{
	int i,j,l;
	double a[27]={0.0};
	double s=0.0;
	l=strlen(p);
	for(j=1;j<=26;j++)
		for(i=0;i<l;i++)
			if(p[i]==65+j-1) a[j]++;
	for(i=1;i<=26;i++)
	{
		a[i]=(a[i]*(a[i]-1))/(l*(l-1));
		if(a[i]>1e-8) s+=a[i];
	}
	return s;

}
int doulet(char m[],char a[][2],int b[],int c[][10],int d[][10],int e[][80],     int f[380])
{             //文本  //连续字母  //出现个数 //位置     //相对位置   //位置的因子 //因子个数
	char p,q,x;
	int i,j,k,l=strlen(m),count=0,t,max,min,temp,s;
	for(i=0;i<l-1;i++)
	{
		p=m[i];q=m[i+1];
		x=0;
		for(j=0;j<l-1;j++)
			if(m[j]==p&&m[j+1]==q) x++;
		if(x>1) {a[count][0]=p;a[count][1]=q;b[count]=x;count++;}
	}
	for(i=0;i<count-1;i++)
		for(j=i+1;j<count;j++)
			if(a[i][0]==a[j][0]&&a[i][1]==a[j][1])
			{
				for(k=j;k<count-1;k++)
				{	a[k][0]=a[k+1][0];
					a[k][1]=a[k+1][1];
					b[k]=b[k+1];
				}
				count--;
			}
	for(i=0;i<count-1;i++)
	{
		max=i+1;
		for(j=i+1;j<count;j++)
			if(b[j]>b[max]) max=j;
		if(b[i]<b[max])
		{
			temp=b[i];b[i]=b[max];b[max]=temp;
			temp=a[i][0];a[i][0]=a[max][0];a[max][0]=temp;
			temp=a[i][1];a[i][1]=a[max][1];a[max][1]=temp;
		}
	}
	for(i=0;i<count;i++)
	{	
		t=0;
		for(j=0;j<l;j++)
			if(m[j]==a[i][0]&&m[j+1]==a[i][1])
			{c[i][t++]=j;}
	}
	for(i=0;i<count;i++)
		for(j=0;j<b[i]-1;j++)
			d[i][j]=c[i][j+1]-c[i][j];


    for(i=0;i<count;i++)
	{
		t=0;
		for(j=0;j<b[i]-1;j++)
		{
			for(k=1;k<=(d[i][j]<50?d[i][j]:50);k++)
				if(d[i][j]%k==0) e[i][t++]=k;
		}
		f[i]=t;
	}
	for(s=0;s<count;s++)
	{
		for(i=0;i<f[s]-1;i++)
			for(j=i+1;j<f[s];j++)
				if(e[s][i]==e[s][j])
				{
					for(k=j;k<f[s]-1;k++)
						e[s][k]=e[s][k+1];
					f[s]--;
				}
		for(i=0;i<f[s]-1;i++)
		{
			min=i+1;
			for(j=i+1;j<f[s];j++)
				if(e[s][j]<e[s][min]) min=j;
			if(e[s][i]>e[s][min])
			{
				temp=e[s][i];e[s][i]=e[s][min];e[s][min]=temp;
			}
		}
	}
	if(count>20) count=20;
	return count;
}
void qksort(int* zh,int zhn)
{	
	int i,min,j,temp;
	for(i=0;i<zhn-1;i++)
			{
				min=i+1;
				for(j=i+1;j<zhn;j++)
					if(zh[j]<zh[min]) min=j;
				if(zh[i]>zh[min])
				{
					temp=zh[i];zh[i]=zh[min];zh[min]=temp;
				}
			}
}
int zhengl(int* a,int *b,int *c,int n)
{
	int x=1,i,j,max,temp;
	for(i=0;i<n;i++)
		a[i]=c[i];
	for(i=1;i<n;)
	{	
		if(a[i]==a[i-1])
		{
			for(j=i;j<n-1;j++)
				a[j]=a[j+1];
			n--;
			x++;
		}
		else {b[i-1]=x;i++;x=1;}
	}
	b[n-1]=x;
	for(i=0;i<n-1;i++)
		{
			max=i+1;
			for(j=i+1;j<n;j++)
				if(b[j]>b[max]) max=j;
			if(b[i]<b[max])
			{
				temp=b[i];b[i]=b[max];b[max]=temp;
				temp=a[i];a[i]=a[max];a[max]=temp;
				
			}
		}
	n=n>18?18:n;
	return n;

}
double cic(char* m,int n)
{
	int i,j,k;
	int p[50]={0};
	char ch[50][500];
	double xic[50],s=0.0;
	for(i=0;i<strlen(m);i++)
	{
		ch[i%n][p[i%n]]=m[i];
		p[i%n]++;
	}
	for(i=0;i<n;i++)
	{
		ch[i][p[i]]='\0';
		p[i]++;
	}
	for(i=0;i<n;i++)
		xic[i]=ic(ch[i]);
	for(i=0;i<n;i++)
		s+=xic[i];
	return s/n;
}
void cal(char* m,int key,char *keyw)
{
	double plet[27]={0.082,0.015,0.028,0.043,0.127,0.022,0.02,0.061,0.07,0.002,0.008,0.04,0.024,0.067,0.075,0.019,0.001,0.06,0.063,0.091,0.028,0.01,0.023,0.001,0.02,0.001};
	int i,j,k,l,letmax[50];
	double pml[27]={0.0},ic[27]={0.0},icmax[50];
	int p[50]={0};
	char ch[50][500];
	char change[500];
	for(i=0;i<strlen(m);i++)
	{
		ch[i%key][p[i%key]]=m[i];
		p[i%key]++;
	}
	for(i=0;i<key;i++)
	{
		ch[i][p[i]]='\0';
	}
	printf("\n");
	
	for(i=0;i<key;i++)		//行
	{
		for(j=0;j<26;j++)	//加j
		{	
			for(k=0;k<26;k++) pml[k]=0;
			ic[j]=0.0;
			for(k=0;k<p[i];k++)		//列
			{	
				change[k]=ch[i][k]-j;
				if(change[k]<65) change[k]+=26;
			}
			for(k=0;k<p[i];k++)
				pml[change[k]-65]++;
			for(k=0;k<26;k++)
				ic[j]+=(pml[k]/p[i])*plet[k];
		}
		letmax[i]=0;icmax[i]=ic[0];
		for(j=0;j<26;j++)
			if(fabs(icmax[i]-0.065)>fabs(ic[j]-0.065)) 
			{
				icmax[i]=ic[j];
				letmax[i]=j;
			}
		printf("%d\t%c\t%f   %.2f%%\n",letmax[i],letmax[i]+'A',icmax[i],fabs(icmax[i]-0.065)*100);
	}
	for(i=0;i<key;i++)
		keyw[i]=letmax[i]+65;
	keyw[key]=0;
}
void sol(char *m,char *keyw)
{
	int i,lm,lk;
	char ch,yon;
	char c[500];
	FILE *vv;
	lm=strlen(m);
	lk=strlen(keyw);
	printf("the text is the following:(the key is %s)\n\n",keyw);
	for(i=0;i<lm;i++)
	{
		ch=m[i]-(keyw[i%lk]-65);
		if(ch<65) ch+=26;
		ch+=32;
		printf("%c",ch);
		c[i]=ch;
	}
	c[lm]='\0';
	printf("\n\n\nexport the text?(y/n)");
	scanf("%c",&yon);	
	if(yon=='y'||yon=='Y') 
	{
		getchar();
		vv=fopen("text.txt","w+");
		fprintf(vv,"%s\n",c);
		printf("export success!the file name is text.txt\n");
		fclose(vv);
	}
		
	
}
void toL(char* m)
{
	int i;
	for(i=0;i<strlen(m);i++)
		if(m[i]>='a'&&m[i]<='z') m[i]-=32;
}
void main()
{
	char m[500];
	int i,n,j,num[380];
	char dl[380][2];
	int c[380][10],d[380][10],e[380][80],f[380];
	int zh[1000],zhn=0;
	int yz[1000],yzs[1000],gs;
	double xic[20],xdic[20];
	int key=0;
	char keyw[50],yon;
	int choose;
	FILE *v;
	printf("1.input the message by keyboard\n2.load message by file\nplease choose:");
	scanf("%d",&choose);
	while(choose!=1&&choose!=2)
	{
		printf("enter ERROR!\n");
		scanf("%d",&choose);
	}
	getchar();
	if(choose==1) gets(m);
	if(choose==2)
	{
		printf("the file name must be message.txt,please ensure it!\n");
		getch();
		v=fopen("message.txt","r+");
		if(v==0) {printf("load ERROR!\n");getch();exit(0);}
		fscanf(v,"%s",m);
		fclose(v);
	}
	
	toL(m);
	system("cls");
	printf("the message is :\n%s\n\nthe first step is to search the num of key,continue?(y/n)",m);
	scanf("%c",&yon);
	if(yon=='y'||yon=='Y') {getchar();system("cls");} else exit(0);
	n=doulet(m,dl,num,c,d,e,f);
	for(i=0;i<n;i++){
		printf("%c%c  %d  ",dl[i][0],dl[i][1],num[i]);
		for(j=0;j<num[i]-1;j++) printf("%d,",d[i][j]);
		if(num[i]>3) printf("\t"); else if(num[i]>1) printf("\t\t"); else printf("\t\t\t");
		for(j=0;j<f[i];j++) printf("%d,",e[i][j]);
		printf("\n");}
	for(i=0;i<n;i++)
		for(j=0;j<f[i];j++)
			zh[zhn++]=e[i][j];
	qksort(zh,zhn);
	printf("\nproper nums of key:\n");
	gs=zhengl(yz,yzs,zh,zhn);
	for(i=0;i<gs;i++)
		printf("%-3d ",yz[i]);
	printf("\n");
	printf("\n");
	for(i=0;i<gs;i++)
	{
		xic[i]=cic(m,yz[i]);
		xdic[i]=fabs(xic[i]-0.065)*100;
	}
	for(j=0;j<gs;j++)
		if(xdic[j]<1.0) {key=yz[j];break;}
	if(key==0) printf("no key nums are available!please check the message!\n");
	else{
	for(i=0;i<gs;i++)
	{
		if(xdic[i]<1.0)
		{
			printf("%-5d%-5d  %lf\t%.2lf%%\n",yz[i],yzs[i],xic[i],xdic[i]);
			if(yz[i]<key) key=yz[i];
		}
	}
	printf("key num %d is recomended,continue the second step?(y/n)",key);
	scanf("%c",&yon);
	if(yon=='y'||yon=='Y') 
		{getchar();system("cls");} 
	else 
		{printf("enter the num of key:");scanf("%d",&key);getchar();system("cls");}
	cal(m,key,keyw);
	printf("%s\n",keyw);
	printf("key %s is recomended,continue?",keyw);
	scanf("%c",&yon);
	if(yon=='y'||yon=='Y') 
		{getchar();system("cls");} 
	else 
		{printf("enter the key:");scanf("%s",&keyw);getchar();system("cls");}
	toL(keyw);
	sol(m,keyw);
	}
	getch();
}
  下面可以给出一个密文,大家用程序测试一下就知道可以破译的了。将密文保存至程序目录,命名message.txt即可。
BZGTNPMMCGZFPUWJCUIGRWXPFNLHZCKOAPGLKYJNRAQFIUYRAVGNPANUMDQOAHMWTGJDXGOMPJPTKAAVZIUIWKVTUCWBWNFWDFUMPJWPMQGPTNWXTSDPLPMWJAXUHHXWPFXXGVAPFNTXVFKOYIRBOQJHCBVWVFYCGQFGUSUBDWVIYATJGTBNDKGHCTMTWIUEFJITVUGJHHIMUVJICUWYQWYGGUWPUUCWIFGWUANILKPHDKOSPJTTWJQOJHXLBJAPZHVQWPDYPGLLGDBCHTGIZCCMEGVIIJLIFFBHSMEGUJHRXBOQUBDNASPEUCWNGWSNWXTSDPLPMWJAIUHUMWPSYCTUWFBMIAMKVBNTDMQNBVDKILQSSDYVWVXIGDQFIBHSLEAVDBXGOLGDBCHTGIZVNFQFKTNGRWXUDCTGKWCOXIXKZPPFDZG


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值