C语言实现维吉尼亚密码的示例代码

 更新时间:2022年11月16日 15:23:59   作者:特立独行的小明  
维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。本文将用C语言实现维吉尼亚密码,需要的可以参考一下

前言    

作业要求:明文中的空格在密文中也有对应空格,明文中的大小写在密文中也有对应大小写。

一、维吉尼亚(Vigenère)密码原理及介绍

在一个凯撒密码中,字母表中的每一字母都会作一定的偏移,例如偏移量为3时,A就转换为了D、B转换为了E……而维吉尼亚密码则是由一些偏移量不同的恺撒密码组成。

在生成密码的时候,可以通过查表的方式(维吉尼亚密码表),通过密钥,来确定明文所对应的密文。

这一表格包括了26行字母表,每一行都由前一行向左偏移一位得到。

例如,假设明文为:

GOODSTUDY

密钥为:

HNUN

由于密钥比明文短,因此需要重复密钥,直至密钥和明文一样长。对于密钥来说,每个字母代表的偏移量为该字母在字母表中的位置

对于第一个字母G,对应密钥第一个字母H,那么由表格中的G行H列加密得到字母N,以此类推,可以得到:

明文:GOODSTUDY    密钥:HNUN    密文:NBIQZGOQF

二、加密/解密算法介绍

1.加密算法

主要思路:通过ASCII码来计算偏移量

附ASCII码对照表:

代码如下:

int Encryption(char* Plaintext, char* key) //加密算法
{
	int i = 0, j = strlen(key), k = strlen(Plaintext),m=0;
	char result[MAXSIZE] = {0};
	for (i = 0; i < k; i++)
	{
		if (Plaintext[i] != ' '&& Plaintext[i] >= 'a' && Plaintext[i] <= 'z')//明文是小写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 2 * 'a') % 26 + 'a';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 'A'-'a') % 26 + 'a';
			}
			m++;
		}
		else if (Plaintext[i] != ' ' && Plaintext[i] >= 'A' && Plaintext[i] <= 'Z')//明文是大写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 'a' - 'A') % 26 + 'A';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 'A' - 'A') % 26 + 'A';
			}
			m++;
		}
		else
			result[i] = ' ';
	}
	printf("加密后的密文为:%s\n",result);
	return 0;
}

思路介绍:由于要求<明文中的空格在密文中也有对应空格,明文中的大小写在密文中也有对应大小写>,所以需要判断输入的明文是否有空格符和密钥中字母的大小写。

key[m%j]是为了确保在明文/密文比密钥长时重复密钥。

2.解密算法

主要思路:加密算法的逆过程

代码如下(示例):

int Decrypt(char* Ciphertext, char* key)//解密算法
{
	int i = 0, j = strlen(key), k = strlen(Ciphertext),m=0; 
	char result[MAXSIZE] = { 0 };
	for (i = 0; i < k; i++)
	{
		if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'a' && Ciphertext[i] <= 'z')//明文是小写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'a') % 26 + 'a';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'a') % 26 + 'a';
			}
			m++;
		}
		else if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'A' && Ciphertext[i] <= 'Z')//明文是大写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'A') % 26 + 'A';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'A') % 26 + 'A';
			}
			m++;
		}
		else
			result[i] = ' ';
	}
	printf("解密后的明文为:%s\n", result);
	return 0;
}

三、完整代码展示

#include <stdio.h>
#include <string.h>
#define MAXSIZE 100
#define KEY 50
 
int Encryption(char* Plaintext, char* key) //加密算法
{
	int i = 0, j = strlen(key), k = strlen(Plaintext),m=0;
	char result[MAXSIZE] = {0};
	for (i = 0; i < k; i++)
	{
		if (Plaintext[i] != ' '&& Plaintext[i] >= 'a' && Plaintext[i] <= 'z')//明文是小写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 2 * 'a') % 26 + 'a';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 'A'-'a') % 26 + 'a';
			}
			m++;
		}
		else if (Plaintext[i] != ' ' && Plaintext[i] >= 'A' && Plaintext[i] <= 'Z')//明文是大写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 'a' - 'A') % 26 + 'A';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Plaintext[i] + key[m % j] - 'A' - 'A') % 26 + 'A';
			}
			m++;
		}
		else
			result[i] = ' ';
	}
	printf("加密后的密文为:%s\n",result);
	return 0;
}
 
int Decrypt(char* Ciphertext, char* key)//解密算法
{
	int i = 0, j = strlen(key), k = strlen(Ciphertext),m=0; 
	char result[MAXSIZE] = { 0 };
	for (i = 0; i < k; i++)
	{
		if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'a' && Ciphertext[i] <= 'z')//明文是小写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'a') % 26 + 'a';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'a') % 26 + 'a';
			}
			m++;
		}
		else if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'A' && Ciphertext[i] <= 'Z')//明文是大写字母
		{
			if (key[m % j] >= 'a' && key[m % j] <= 'z')//密钥为小写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'A') % 26 + 'A';
			}
			else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密钥为大写字母
			{
				result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'A') % 26 + 'A';
			}
			m++;
		}
		else
			result[i] = ' ';
	}
	printf("解密后的明文为:%s\n", result);
	return 0;
}
int main()
{
	int n;
	char Plaintext[MAXSIZE] = {0};
	char Ciphertext[MAXSIZE] = {0};
	char key[KEY] = {0};
	while (1)
	{
		printf("===============\n");
		printf("   1.加密\n");
		printf("   2.解密\n");
		printf("   0.退出\n");
		printf("===============\n");
		printf("请输入要执行的操作:");
		scanf_s("%d",&n);
		getchar();
		switch (n)
		{
		case 1:
			printf("请输入明文:");
			scanf_s("%[^\n]", Plaintext, MAXSIZE);
			getchar();
			printf("请输入密钥:");
			scanf_s("%[^\n]", key, KEY);
			Encryption(Plaintext, key);
			break;
		case 2:
			printf("请输入密文:");
			scanf_s("%[^\n]", Ciphertext, MAXSIZE);
			getchar();
			printf("请输入密钥:");
			scanf_s("%[^\n]", key, KEY);
			Decrypt(Ciphertext, key);
			break;
		case 0:
			exit(0);
			break;
		}
	}
	return 0;
}

做了一个菜单方便选择加密解密。

总结

主要是ASCII码的运用,对照维吉尼亚密码表算出每个字母的偏移量,对逻辑要求可能比较高,需要,计算偏移量以及循环密钥较为繁琐。

到此这篇关于C语言实现维吉尼亚密码的示例代码的文章就介绍到这了,更多相关C语言维吉尼亚密码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c++深入浅出讲解堆排序和堆

    c++深入浅出讲解堆排序和堆

    在c++里有很多排序方法,比如相对简单的冒泡排序、选择排序、插入排序,还有 STL里的sort函数  手写快排  归并排序等,还有就是堆排序,这次主要说堆排序和堆
    2022-03-03
  • 详解C++中的双冒号 ::

    详解C++中的双冒号 ::

    这篇文章主要介绍了C++中的双冒号 ::,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-09-09
  • C/C++ Qt MdiArea 多窗体组件应用教程

    C/C++ Qt MdiArea 多窗体组件应用教程

    MDI窗体控件类似于画布,该控件只具备展示窗体的功能,无法实现生成窗体,所以我们需要在项目中手动增加自定义的Dialog对话框,并对该对话框进行一定的定制,这篇文章主要介绍了C/C++ Qt MdiArea 多窗体组件应用,需要的朋友可以参考下
    2021-12-12
  • opencv3/C++图像边缘提取方式

    opencv3/C++图像边缘提取方式

    今天小编就为大家分享一篇opencv3/C++图像边缘提取方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • C语言转义字符实例详解

    C语言转义字符实例详解

    这里主要介绍了C语言的转义字符的知识,并附有示例代码,以便理解,希望对学习 C语言的同学有所帮助
    2016-07-07
  • C语言之qsort函数详解

    C语言之qsort函数详解

    这篇文章主要介绍了C语言中qsort函数的用法实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下
    2021-08-08
  • C++类型转换的深入总结

    C++类型转换的深入总结

    这篇文章主要给大家介绍了关于C++类型转换的深入总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • C语言详解float类型在内存中的存储方式

    C语言详解float类型在内存中的存储方式

    在c语言中float函数是单精度的。它在内存中以二进制的形式存储。分为符号位,阶码与尾数三部分,下面我们详细来了解一下
    2022-04-04
  • 详解如何在code block创建一个C语言的项目

    详解如何在code block创建一个C语言的项目

    这篇文章主要介绍了详解如何在code block创建一个C语言的项目,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • C语言实现单词助手功能

    C语言实现单词助手功能

    这篇文章主要为大家详细介绍了C语言实现单词小助手,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10

最新评论