学习目标:
维吉尼亚密码是古典密码中非常具有代表的例子。本实验要求用高级语言编写和调试一个简单的维吉尼亚密码实现及解密程序,通过本实验可以加深理解维吉尼亚密码原理。
预备知识:
人们在单一恺撒密码的基础上扩展出多表密码,称为“维吉尼亚”密码。它是由16世纪法国亨利三世王朝的布莱瑟•维吉尼亚发明的。维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。维吉尼亚密码的密钥空间大小为26m,所以即使m的值很小,使用穷尽密钥搜索方法也需要很长的时间。例如,当m=5时,密钥空间大小超过1.1*107,这样的密钥量已经超出了使用手算进行穷尽搜索的能力范围。
维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。假如以上面第一行代表明文字母,左面第一列代表密钥字母,对如下明文加密:
TO BE OR NOT TO BE THAT IS THE QUESTION
当选定RELATIONS作为密钥时,加密过程是:明文一个字母为T,第一个密钥字母为R,因此可以找到在R行中代替T的为K,依此类推,得出对应关系如下:
密钥:RELAT IONSR ELATI ONSRE LATIO NSREL
明文:TOBEO RNOTT OBETH ATIST HEQUE STION
密文:KSMEH ZBBLK SMEMP OGAJX SEJCS FLZSY
历史上以维吉尼亚密表为基础又演变出很多种加密方法,其基本元素无非是密表与密钥,并一直沿用到二战以后的初级电子密码机上。
加密流程:
(1)编号。将A-Z以编号0-25编号;
(2)选取密钥。举例:wangyuhang;
(3)明文处理。去掉所有空格;举例:明文为we are discovered save yourself;处理后:wearediscoveredsaveyourself;
(4)密钥处理。将密钥重复排列;处理后:wangyuhangwangyuhangwangyuh;
(5)加密。举例:明文第一个字母W编码为22,密钥第一个字母为W编码为22;22+22=44,因为44>26,所以44-26=18;18对应字母为Q,故将W加密为Q;明文第二个字母E编码为4,密钥第二个字母为A编码为0;4+0=4,4对应字母为E,故将E加密为E;以此类推;
(6)输出密文。举例:senxadvyyoikneqywvrekueyals。
解密流程:
(1)编号。将A-Z以编号0-25编号;
(2)获取密钥。举例:wangyuhang;
(3)密文处理。去掉所有空格;处理后:senxadvyyoikneqywvrekueyals;
(4)密钥处理。将密钥重复排列;处理后:wangyuhangwangyuhangwangyuh;
(5)解密。举例:密文第一个字母Q编码为18,密钥第一个字母为W编码为22;18-22=-4,因为-4<0,所以-4+26=22;22对应字母为W,故将Q解密为W;密文第二个字母E编码为4,密钥第二个字母为A编码为0;4-0=4,4对应字母为E,故将E解密为E,以此类推;
(6)明文处理。根据相关语言释读,按照正确的语言格式整理明文;举例:we are discovered save yourself。
实验代码:
#include <iostream>
#include <cstring>
using namespace std;
#define MINCHAR 97
#define CHARSUM 26
char table[CHARSUM][CHARSUM];
bool Init();
bool Encode(char* key, char* source, char* dest);
bool Dncode(char* key, char* source, char* dest);
int main()
{if(!Init()){cout << "初始化错误!" << endl;return 1;}char key[256];char str1[256];char str2[256];int operation;while(1){do{cout << "请选择一个操作:1. 加密;2. 解密;-1. 退出\n";cin >> operation;}while(operation != -1 && operation != 1 && operation != 2);if(operation == -1)return 0;else if(operation == 1)//加密{cout << "请输入密钥:";cin >> key;cout << "请输入待加密字符串:";cin >> str1;Encode(key, str1, str2);cout << "加密后的字符串:" << str2 << endl;}else if(operation == 2)//解密{cout << "请输入密钥:";cin >> key;cout << "请输入待解密字符串:";cin >> str1;Dncode(key, str1, str2);cout << "解密后的字符串:" << str2 << endl;}cout << endl;}return 0;
}
// 初始化维吉尼亚方阵
bool Init()
{int i, j;for(i = 0; i < CHARSUM; i++){for(j = 0; j < CHARSUM; j++){table[i][j] = 65 + (i + j) % CHARSUM;}}return true;
}
// 加密
// key:密钥
// source:待加密的字符串
// dest:经过加密后的字符串
bool Encode(char* key, char* source, char* dest)
{char* tempSource = source;char* tempKey = key;char* tempDest = dest;do{*tempDest = table[(*tempKey) - MINCHAR][(*tempSource) - MINCHAR];tempDest++;if(!(*(++tempKey)))tempKey = key;}while(*tempSource++);dest[strlen(source)] = 0;return true;
}
// 解密
// key:密钥
// source:待解密的字符串
// dest:经过解密后的字符串
bool Dncode(char* key, char* source, char* dest)
{char* tempSource = source;char* tempKey = key;char* tempDest = dest;char offset;do{offset = (*tempSource) - (*tempKey);offset = offset >= 0 ? offset : offset + CHARSUM;*tempDest = MINCHAR + offset;tempDest++;if(!(*(++tempKey)))tempKey = key;}while(*++tempSource);dest[strlen(source)] = 0;return true;
}
实验结果:
思考:
1.维吉尼亚密码属于单表密码还是多表密码?
2.维吉尼亚密码中加密密钥和解密密钥相同吗?
答案:
1.多表密码。
2.相同。