? ? 加密法的需求在军事上及政治上的显现极为旺盛,也迫使它快速地向前发展.传统的移位及替代法虽然使用方便,但可以采用统计的方式进行破解,安全性还有待加强.
? ? ? 所以后期就发展出一种新的加密方法,即维吉尼亚加密法.这种方法的出发点是,对于相同的字母或数字,加密后的密文可能不同,这就没法从统计的角度解密.
? ? ? 基本的加密方法,可以参考下图.
? ? ? 这张图中, 第一行代表原文的数字或字符,每一列代表加密采用第几套替代方案,每一横行的字符对应该列的字母加密后的密文 .是不是够复杂哈,如果采用这样的方式手工加密解密,写一封邮件估计要崩溃死了....
? ? ? 而且这套加密方法使用中还存在一些问题,就是需要把 整个加密图传给解密方 ,没有该图做指导,解密的人也是一脸懵逼....
? ? ? 比如加密"hello",加密结果就如下,加密后的密文为"FIDJS",两个字母"l"分别对应D和J,就没法用统计法找出破绽了.? ?
? ? ?
C++编程实现维吉尼亚密码加密解密
编程实现维吉尼亚密码加密解密
要求:用户可以输入密钥
#include
using namespace std;
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;
}
int operation;
while(1)
do
cin operation;
if(operation == -1)
return 0;
else if(operation == 1)//加密
cout "请输入密钥:";
cin key;
cout "请输入待加密字符串:";
cin str1;
cout "请输入待解密字符串:";
cout endl;
// 初始化维吉尼亚方阵
bool Init()
int i, j;
for(i = 0; i CHARSUM; i++)
for(j = 0; j CHARSUM; j++)
table[j] = MINCHAR + (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;
*tempDest = table[(*tempKey) - MINCHAR][(*tempSource) - MINCHAR];
tempDest++;
if(!(*(++tempKey)))
tempKey = key;
}while(*tempSource++);
dest[strlen(source)] = 0;
// 解密
// source:待解密的字符串
// dest:经过解密后的字符串
bool Dncode(char* key, char* source, char* dest)
char offset;
offset = (*tempSource) - (*tempKey);
offset = offset = 0 ? offset : offset + CHARSUM;
*tempDest = MINCHAR + offset;
}while(*++tempSource);
#include stdlib.h
#include stdio.h
#include string.h
#define N 10000
void function(char message[],char key[],int mode); //加解密函数
int choose;
char m[N],key[N];
scanf("%d",choose);
getchar();
if (choose == 1)
printf("输入明文:\n");
printf("输入密文:\n");
gets(m);
printf("输入密钥:\n");
gets(key);
function(m,key,choose);
else
printf("输入错误!\n");
void function(char message[],char key[],int mode) //加解密函数
int i, j = 0; //j控制key的轮回
int len_k = strlen(key); //密钥长度
char s[N];
for(i=0; message[i]!='\0'; i++)
s[i]=' ';
if (mode == 1)
j++;
printf("%c",s[i]);
printf("\n");
gets(l);//不加这句M就输入不了为什么?
是因为没有这句的话,按的回车键就输成m了.
连用两个输入语句时,需要考虑回车键,就像我代码里的getchar().
假如有这样一条指令:
RETURN TO ROME
用恺撒密码加密后就成为:
UHWXUA WR URPH
如果这份指令被敌方截获,也将不会泄密,因为字面上看不出任何意义.
明:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
密:T U V W X Y Z A B C D E F G H I J K L M N O P Q R S
在这个加密表下,明文与密文的对照关系就变成:
明文:THE FAULT, DEAR BRUTUS, LIES NOT IN OUR STARS BUT IN OURSELVES.
密文:MAX YTNEM, WXTK UKNMNL, EBXL GHM BG HNK LMTKL UNM BG HNKLXEOXL.
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
A A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
B B C D E F G H I J K L M N O P Q R S T U V W X Y Z A CC D E F G H I J K L M N O P Q R S T U V W X Y Z A B
D D E F G H I J K L M N O P Q R S T U V W X Y Z A B C E E F G H I J K L M N O P Q R S T U V W X Y Z A B C D F F G H I J K L M N O P Q R S T U V W X Y Z A B C D E G G H I J K L M N O P Q R S T U V W X Y Z A B C D E F H H I J K L M N O P Q R S T U V W X Y Z A B C D E F G I I J K L M N O P Q R S T U V W X Y Z A B C D E F G H J J K L M N O P Q R S T U V W X Y Z A B C D E F G H I K K L M N O P Q R S T U V W X Y Z A B C D E F G H I J L L M N O P Q R S T U V W X Y Z A B C D E F G H I J K M M N O P Q R S T U V W X Y Z A B C D E F G H I J K L N N O P Q R S T U V W X Y Z A B C D E F G H I J K L M O O P Q R S T U V W X Y Z A B C D E F G H I J K L M N P P Q R S T U V W X Y Z A B C D E F G H I J K L M N O Q Q R S T U V W X Y Z A B C D E F G H I J K L M N O P R R S T U V W X Y Z A B C D E F G H I J K L M N O P Q S S T U V W X Y Z A B C D E F G H I J K L M N O P Q R T T U V W X Y Z A B C D E F G H I J K L M N O P Q R S U U V W X Y Z A B C D E F G H I J K L M N O P Q R S T V V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
W W X Y Z A B C D E F G H I J K L M N O P Q R S T U V X X Y Z A B C D E F G H I J K L M N O P Q R S T U V W Y Y Z A B C D E F G H I J K L M N O P Q R S T U V W X Z Z A B C D E F G H I J K L M N O P Q R S T U V W X Y
维吉尼亚密码引入了"密钥"的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计.假如以上面第一行代表明文字母,左面第一列代表密钥字母,对如下明文加密:
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
历史上以维吉尼亚密表为基础又演变出很多种加密方法,其基本元素无非是密表与密钥,并一直沿用到二战以后的初级电子密码机上.
采用替代密码算法中的维吉尼亚密码方法,密文C="HEADVIGENERE",密钥K=KEY,求明文P
将密文HEADVIGENERE用密钥替换后为KEYKEYKEYKEY
替换前:HEADVIGENERE
替换后:KEYKEYKEYKEY
解密求明文:
按替换后的内容找到第一行的K所在位置向下寻找,找到H的位置,当前行最左侧第一列对应的就为明文X
加密求密文:
按明文找到第一列对应的H,在从第一行中找到对应的密钥K,两个位置相交的值就为密文.
答案:
HEA DVI GEN ERE
KEY? KEY KEY? KEY
XAC?TRK?WAP?UNG
姓名:? 莫益彰
原文:a b c
密文:d e f
由于出现了字母频度分析,凯撒密码变得很容易破解,所以呢人们在单一恺撒密码的基础上扩展出多表密码,称为"维吉尼亚"密码.
【嵌牛鼻子】密码学,计算机安全.
【嵌牛正文】
维吉尼亚密码的加密
维吉尼亚密码由凯撒密码扩展而来,引入了密钥的概念.即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计.假如以上面第一行代表明文字母,左面第一列代表密钥字母,对如下明文加密:
密钥:RE LA ?TI ?ONS ?RE LA TION ? SR ELA TIONSREL
明文:TO BE OR NOT TO BE THAT ?IS ?THE QUESTION
密文:KS ME HZ ?BBL ?KS ME MPOG AJ XSE JCSFLZSY
图解加密过程:
在维吉尼亚(Vigenère)的密码中,发件人和收件人必须使用同一个关键词(或者同一文字章节),这个关键词或文字章节中的字母告诉他们怎么样才能前后改变字母的位置来获得该段信息中的每个字母的正确对应位置.
维吉尼亚密码的破解
维吉尼亚密码分解后实则就是多个凯撒密码,只要知道密钥的长度,我们就可以将其分解.
如密文为:ABCDEFGHIJKLMN
组1:A D G J N
分解后每组就是一个凯撒密码,即组内的位移量是一致的,对每一组即可用频度分析法来解密.
所以破解维吉尼亚密码的关键就是确定密钥的长度.
确定密钥长度
确定密钥长度主要有两种方法,Kasiski 测试法相对简单很多,但Friedman 测试法的效果明显优于Kasiski 测试法.
Kasiski 测试法
在英文中,一些常见的单词如the有几率被密钥的相同部分加密,即原文中的the可能在密文中呈现为相同的三个字母.
在这种情况下,相同片段的间距就是密文长度的倍数.
所以我们可以通过在密文中找到相同的片段,计算出这些相同片段之间的间距,而密钥长度理论上就是这些间距的公约数.
然后我们需要知道重合指数(IC, index of coincidence)的概念.
重合指数表示两个随机选出的字母是相同的的概率,即随机选出两个A的概率+随机选出两个B的概率+随机选出两个C的概率+......+随机选出两个Z的概率.
对英语而言,根据上述的频率表,我们可以计算出英语文本的重合指数为
利用重合指数推测密钥长度的原理在于,对于一个由凯撒密码加密的序列,由于所有字母的位移程度相同,所以密文的重合指数应等于原文语言的重合指数.
举例来说,对密文ABCDEABCDEABCDEABC
首先测试密钥长度=1,对密文ABCDEABCDEABCDEABC统计每个字符出现的次数:
组1:A C E B D A C E B
在知道了密钥长度n以后,就可将密文分解为n组,每一组都是一个凯撒密码,然后对每一组用字母频度分析进行解密,和在一起就能成功解密凯撒密码.
上文已经说到,自然语言的字母频度是一定的.字母频度分析就是将密文的字母频度和自然语言的自然频度排序对比,从而找出可能的原文.