维吉尼亚密码解密c语言实现

维吉尼亚密码解密c语言实现

虽说用c语言写比较麻烦,但最后还是完成了!

在这里插入图片描述

/*
creator:bur@n
date:2020-10-13 
*/
 
#include <stdio.h>
#include <string.h>
#define K 2
#define matrix 5
//声明一些函数

//交互性函数 
void print_welcome();  
//读写文件并操作函数
void read_operate_pwd(char addr1[],char addr2[]);
//确定密钥函数,返回密钥
void make_key(char string[],int str_num); 





int main(){
	int flag;
	int i,j;
	char addr1[20]="pwd.txt",addr2[20]="result.txt";
	print_welcome();
	scanf("%d",&flag);
	//printf("输入打开的文件:\n");
	//scanf("%s",addr1);
	//printf("输入输出的文件:\n");
	//scanf("%s",addr2);
	switch(flag){
		//进行解密操作 
		case 1:read_operate_pwd(addr1,addr2);break;
		//退出 
		case 2:return 0;
	}
	return 0;
}

//交互性函数
void print_welcome(){
	int i,j;
	j=50;
	for(i=0;i<j;i++){
		printf("*");
	}
	printf("\n*");
	for(i=0;i<j-2;i++){
		printf(" ");
	}
	printf("*\n*");
	
	printf("      欢迎使用维吉尼亚加解密程序!              *");
	printf("\n*");
	for(i=0;i<j-2;i++){
		printf(" ");
	}
	printf("*\n");
	for(i=0;i<j;i++){
		printf("*");
	}
	printf("\n\n");	
	printf("请输入您选择的数字!\n\n");
	printf("1解密	2退出\n\n");

} 

//利用卡希斯基方法计算得到密钥的长度是5 
void read_operate_pwd(char addr1[],char addr2[]){
	int i,j,t;
	int size,str_num;
	int row;
	i=0;
	size=10000;
	row=100000;
	char str[size],ch;
	char temp[K]; 
	char string[row][K];
	FILE *in,*out;
	if((in=fopen(addr1,"r"))==NULL){
		printf("打开文件%s失败!\n",addr1);
		//exit(0);
	}
	if((out=fopen(addr2,"w"))==NULL){
		printf("打开文件%s失败\n",addr2);
		//exit(0);
	}
	//将字符串读入到数组里 
	ch=fgetc(in);
	while(!feof(in)){
		//将字符转换成小写字母存入数组中 
		if(ch>='a'&&ch<='z')
		str[i]=ch;
		else if(ch>='A'&&ch<='Z')
		str[i]=ch+27;
		ch=fgetc(in);
		i++;
	}
	//将字符装入二维数组中,我们这里设定的是长度为3的字符 
	str_num=i; 
	for(i=0;i<str_num-(K-1);i++){
		string[i][0]=str[i];
		string[i][1]=str[i+1];
		//string[i][2]=str[i+2];
		//string[i][3]=str[i+3];
	}
	//将信息写入文件中,手动计算密钥长度 
	for(i=0;i<str_num-(K-1);i++){
		for(j=i+1;j<str_num-(K-1)-i;j++){
				if((string[i][0]==string[j][0])&&(string[i][1]==string[j][1])){
				//将字符的首地址记录下来
				fprintf(out,"i的首地址为:%d\nj的首地址为:%d\n",i,j);
				fputs("字符为:",out);
				for(t=0;t<K;t++)
				fprintf(out,"%c",string[i][t]); 
				fputs("\n",out);
			}			
		}
	}
	//str_num=608;
	//将一个数组存入一个列为5的二维数组中
	printf("更改程序matrix的值来做下一步!\n");
	getchar(); 
	getchar();
	make_key(str,str_num);
	 
}


//根据密钥长度判断密钥 
void make_key(char str[],int str_num){
	char str_group[matrix][300];
	char ch;
	int i,j,t,k;
	float max;
	int temp[matrix]={0},temp2[matrix];
	float voca[matrix][26]={0};
	int MI[matrix]={0};
	FILE *fp;
	float sum,temp1[26],sum1;
	float static_fre[26]={0.0856,0.0139,0.0297,0.0378,0.1304,0.0289,0.0199,0.0528,\
	0.0627,0.0013,0.0042,0.0339,0.0249,0.0707,0.0797,0.0199,0.0012,0.0677,0.0607,0.1045,\
	0.0249,0.0092,0.0149,0.0017,0.0199,0.0008};
	
	for(i=0;i<matrix;i++){
		for(j=0;j<str_num;j++){
			if(j%matrix==i){
			str_group[i][temp[i]]=str[j];
			temp[i]++;
		}
		}
		
	}
	
	//把各一维数组中的数字出现频度求出来
	for(i=0;i<matrix;i++){
		for(j=0;j<temp[i];j++){
			voca[i][str_group[i][j]-'a']++;
			}
		}
		
	for(i=0;i<matrix;i++){
		for(j=0;j<26;j++){
			voca[i][j]=voca[i][j]/temp[i];
			//printf("%f\n",voca[i][j]);
		}
		//printf("\n");
	}
	
	for(t=0;t<matrix;t++){
		
		for(i=0;i<26;i++){
		for(j=0,sum=0;j<26;j++){
			sum1=static_fre[j]*voca[t][(j+i)%26];
			sum=sum+sum1;
		}
		temp1[i]=sum;
		//printf("%f\n",sum);
	}
	max=temp1[0];	
	for(k=0;k<26;k++){
		if(temp1[k]>max){
			max=temp1[k];
			temp2[t]=k;
		}
	} 
	printf("密钥分别是:%c\n",temp2[t]+97);
	
	}
	//printf("\n");
	
	if((fp=fopen("mingwen.txt","w"))==NULL){
		printf("打开文件mingwen.txt失败\n");
	}
	
	for(i=0;i<str_num;i++){
		if((str[i]-temp2[i%matrix]-97)<0){
			fprintf(fp,"%c",(str[i]-temp2[i%matrix]+26));
			printf("%c",(str[i]-temp2[i%matrix]+26));
		}
		else{
			fprintf(fp,"%c",(str[i]-temp2[i%matrix]));
			printf("%c",(str[i]-temp2[i%matrix]));
		}
		
	}
	fclose(fp);
	
	
	
	} 

在这里插入图片描述

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
维吉尼亚密码是一种基于多表替换密码的加密算法,它使用一个关键字和明文进行加密和解密。下面是使用C语言实现维吉尼亚密码的基本步骤: 1. 定义关键字:选择一个关键字作为加密和解密的密钥。关键字可以是任意长度的字符串,通常由字母组成。 2. 明文转换:将明文转换为数字,可以使用ASCII码将每个字符映射为对应的数字。 3. 关键字扩展:将关键字扩展为与明文长度相同的字符串。可以使用循环来实现关键字的扩展。 4. 加密/解密:将明文字符与关键字字符进行对应位置的加密/解密操作。加密操作可以通过将明文字符与关键字字符相加并取模得到密文字符。解密操作可以通过将密文字符与关键字字符相减并取模得到明文字符。 5. 密文转换:将加密后的数字转换回对应的字符,可以使用ASCII码将数字映射为对应的字符。 下面是一个简单的C语言实现维吉尼亚密码的示例代码: ```c #include <stdio.h> #include <string.h> void vigenereEncrypt(char* plaintext, char* keyword) { int plaintextLen = strlen(plaintext); int keywordLen = strlen(keyword); char ciphertext[plaintextLen + 1]; for (int i = 0; i < plaintextLen; i++) { ciphertext[i] = ((plaintext[i] - 'a' + keyword[i % keywordLen] - 'a') % 26) + 'a'; } ciphertext[plaintextLen] = '\0'; printf("Ciphertext: %s\n", ciphertext); } void vigenereDecrypt(char* ciphertext, char* keyword) { int ciphertextLen = strlen(ciphertext); int keywordLen = strlen(keyword); char plaintext[ciphertextLen + 1]; for (int i = 0; i < ciphertextLen; i++) { plaintext[i] = ((ciphertext[i] - 'a' - keyword[i % keywordLen] + 'a' + 26) % 26) + 'a'; } plaintext[ciphertextLen] = '\0'; printf("Plaintext: %s\n", plaintext); } int main() { char plaintext[] = "hello"; char keyword[] = "key"; vigenereEncrypt(plaintext, keyword); vigenereDecrypt("uryyb", keyword); return 0; } ``` 这段代码实现维吉尼亚密码的加密和解密功能。在示例中,明文为"hello",关键字为"key",加密后的密文为"uryyb",解密后的明文为"hello"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值