目录
前言
一、维吉尼亚(Vigenère)密码原理及介绍
二、加密/解密算法介绍
1.加密算法
2.解密算法
三、完整代码展示
总结
前言
本文介绍了维吉尼亚密码的原理,以及用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码的运用,对照维吉尼亚密码表算出每个字母的偏移量,对逻辑要求可能比较高,需要,计算偏移量以及循环密钥较为繁琐。新手第一次写文章,如果代码有什么不足的、没有考虑到的地方,文章有哪些可以补充的,欢迎大佬指正。