Virginia加解密算法C语言实现

密码学实验: Virginia加解密算法C语言实现

1.实验步骤

  1. 用户输入密钥,对明文文件进行加密
  2. 使用唯密文攻击破解密钥
  3. 根据所得密钥进行解密

2.实验测试

1)明文文本

              

2)密钥:humin

3)密文

              

 4)程序运行结果

              

              

扫描二维码关注公众号,回复: 5353019 查看本文章

              

代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAX 10000 
#define LEN 50
/*Virginia加密算法*/ 
void encrypt()
{
	FILE *fin,*fout;
	char ch,cc;
	char filename1[LEN]="F:\\cryptology\\plaintext.txt";
	char filename2[LEN]="F:\\cryptology\\cipertext.txt";
	char key[MAX];
	int keylen,i=0;
	printf("请输入加密密钥:\n") ; 
	scanf("%s",key);
	keylen=strlen(key);
	fin=fopen(filename1,"r");
	if(fin==NULL)
	{
		printf("Fail to open the file1!\n");
	}
	fout=fopen(filename2,"w");
	if(fout==NULL)
	{
		printf("Fail to open the file2!\n");
	}
	printf("加密后的密文:\n");
	while((ch=fgetc(fin))!=EOF)
	{	
		cc=(ch+(key[i%keylen]-'a'))<='z'?(ch+(key[i%keylen]-'a')):(ch+(key[i%keylen]-'a'))-26;
		fprintf(fout,"%c",cc);
		i++;
		printf("%c",cc);	
	}
	printf("\n");
	fclose(fin);//关闭输入流 
	fclose(fout);
}

/*唯密文破解密钥*/ 
void getKey(char filename1[],char key[])
{
	FILE *fin,*fout;	
	char sub[100]="";
	char try[100]="";
	int alphabat[26]={0};//用于统计字母出现的频率
	double assese[100]={0}; //统计每个字串的IC'值 
	int Count=1;//密钥长度 
	int i,j;
	double avg=0; 
	double p[30]={0.0805,0.0162,0.0320,0.0365,0.1231,0.0228,0.0161,0.0514,0.0718,0.0010,
				  0.0520,0.0403,0.0225,0.0719,0.0794,0.0229,0.0020,0.0603,0.0659,0.0959,
				  0.0310,0.0093,0.0203,0.0020,0.0188,0.0009};//字母出现的统计频率
				  
	int keyIndex[MAX];//密钥的位置
	// step1:估算Virginia多表代换加密的秘钥长度
	while((int)(fabs(avg-0.065)*1000)>1)
	{
		char ch;	
		Count++;
		avg=0.0;				
		//将密文分成Count个子串,然后计算其IC’的平均值
		memset(assese,0,sizeof(assese));
		printf("分成%d个子串\n",Count);
		for(i=0;i<Count;i++) 
		{
			fin=fopen(filename1,"r");
			if(fin==NULL)
			{
				printf("Fail to open the cipertextfile!\n");
				exit(0);
			}else{
				sprintf(sub,"F:\\cryptology\\sub%d.txt",i+1);//创建Count个文本文件 
				fout=fopen(sub,"w");
				if(fout== NULL )  
				{
					printf("Fail to open subFile.");
					break ;	
				}else
				{
					int len=0;
					memset(alphabat,0,sizeof(alphabat));//初始化字母出现的频率 
					for(j=0;j<i;j++)//第i个字串的开始点
					{
						if((ch=fgetc(fin))!=EOF) continue;
					}					
					while((ch=fgetc(fin))!=EOF)
					{
						fprintf(fout,"%c",ch); 
						alphabat[ch-'a']++;
						len++;
						printf("%c",ch);
						for(j=0;j<Count-1;j++)//同一个字串内的字母相距 Count-1 
						{
							if((ch=fgetc(fin))!=EOF)
							{
								continue;
							} 
						}
					}
					printf("\n");	
					//计算IC'
					for(j=0;j<26;j++)
					{
						if(alphabat[j]>1)
						{
							assese[i+1]+=((double)alphabat[j]/len)*((double)(alphabat[j]-1)/(len-1));
						}
						
					}
					avg+=assese[i+1];
				}
				fclose(fout);
				fclose(fin);//关闭输入流 
			}
		}
		avg=avg/Count;//求IC'的平均值 
		if((int)(fabs(avg-0.065)*1000)<=1)//IC'的平均值接近于0.065 
		{
			printf("第%d次的IC'=%f\n",Count,avg);
			break;
		}
		printf("第%d次的IC'=%f\n",Count,avg);
	}
	//step2:再计算秘钥中的每个字符
	for(i=0;i<Count;i++)
	{
		double index[27]={0.0};//字串每一次移位的拟重合指数 
		int fre[26]={0};
		double max=0.0;
		sprintf(sub,"F:\\cryptology\\sub%d.txt",i+1);//打开字串文件 
		sprintf(try,"F:\\cryptology\\try%d.txt",i+1);
		for(j=0;j<26;j++)
		{
			char ch,cc;
			int k;
			int n=0;//字串的长度 
			memset(fre,0,sizeof(fre));
			fin=fopen(sub,"r");
			fout=fopen(try,"w");
			while((ch=fgetc(fin))!=EOF)
			{	
				cc=(ch-j)>='a'?(ch-j):(ch-j)+26;//左移j位 
				fprintf(fout,"%c",cc);
				fre[cc-'a']++;//统计移位后每个 字母出现的频率 
				n++;  
			}
			//计算拟重合指数
			for(k=0;k<26;k++)
			{
				index[j-1]+=(p[k]*fre[k])/n;
			}
		}
		//求最大的拟重合指数
		max=index[0];
		for(j=1;j<26;j++)
		{	
			if(index[j]>max)
			{
				max=index[j];
				keyIndex[i]=j;//保存当前字串的密钥 
			}
		} 
		fclose(fin);
		fclose(fout);		
	} 
	printf("所求密钥为:\n");
	for(i=0;i<Count;i++)//输出密钥 
	{
		printf("%c",keyIndex[i]+'a'+1);
		key[i]= keyIndex[i]+'a'+1;//保存密钥 
	}
	printf("\n");
}
/*Virginia已知密钥解密算法*/  
void decrypt()
{
	FILE *fin,*fout;
	char ch,cc;
	char key[MAX];
	char filename1[LEN]="F:\\cryptology\\cipertext.txt";
	char filename2[LEN]="F:\\cryptology\\decryptiontext.txt";
	int keylen,i=0;
	getKey(filename1,key);
	keylen=strlen(key);
	fin=fopen(filename1,"r");
	fout=fopen(filename2,"w");
	if(fout==NULL)
	{
		printf("fail\n");
	}
	printf("解密得到的明文:\n"); 
	while((ch=fgetc(fin))!=EOF)
	{	
		cc=(ch-(key[i%keylen]-'a'))>='a'?(ch-(key[i%keylen]-'a')):(ch-(key[i%keylen]-'a'))+26;
		fprintf(fout,"%c",cc);
		i++;
		printf("%c",cc);		
	}
	printf("\n");
	fclose(fin);//关闭输入流 
	fclose(fout);
}
int main()
{
	int choice;
	while(1)
	{
		printf("----------------------------------------\n");
		printf("\t\t1.加密\n");
		printf("\t\t2.解密\n");
		printf("\t\t3.退出\n");
		printf("----------------------------------------\n");
		printf("请输入你的选择:\n") ;
		scanf("%d",&choice);
		switch(choice)
		{
			case 1:
				encrypt();
				break;
			case 2:
				decrypt();
				break;
			case 3:
				exit(0);
				break;
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_36793356/article/details/84563089
今日推荐