古典密码之维吉尼亚密码Cpp源码
原理介绍
在上述加密方法中,密文字母和明文字母之间是一对一映射 ,其加密方法均无法掩盖明文数据的统计特性,通过统计计算密文字母的统计特性,比较容易找出明文和密文之间的对应关系,从而达到破解密文的目的。
以英文文章为例,不同的字母在文章中出现的频率是不同的,美国密码学家William Freidman在对大量英文文章进行统计后,得到不同英文字母的普遍使用频率,不同英文字母(不区分大小写)的使用频率见下表。字母 | 频率 | 字母 | 频率 | 字母 | 频率 |
A | 0.0856 | J | 0.0133 | S | 0.0607 |
B | 0.0139 | K | 0.0042 | T | 0.1045 |
C | 0.0279 | L | 0.0339 | U | 0.0249 |
D | 0.0378 | M | 0.0249 | V | 0.0092 |
E | 0.1304 | N | 0.0707 | W | 0.0149 |
F | 0.0289 | O | 0.0797 | X | 0.0017 |
G | 0.0199 | P | 0.0199 | Y | 0.0199 |
H | 0.0528 | Q | 0.0012 | Z | 0.0008 |
I | 0.0627 | R | 0.0677 |
|
|
以同样的方式还可以统计双字母和三字母的统计特性,例如:在双字母中TH、HE、ER和AN等是使用频率相对较高的双字母组合,而在三字母中则THE、ING、AND和HER等属于使用频率较高的三字母组合。利用双字母和三字母的统计特性,可以更有效地提高简单密码算法的准确性。
对单表代替密码进行改进,产生多表代替密码,多表代替密码隐藏了明文的统计特性,明文的结构信息被隐蔽了。
多表代替密码有两个共同的特征,其一是采用相关单表代换规则,其二是密钥决定代换的具体方法。
在这类密码算法中,比较典型的多表代替密码是维吉尼亚(Vigenere)密码和希尔(Hill)密码,希尔密码实际上也是多表代替密码的另一种变体。
维吉尼亚密码是多表代替密码中最简单的一种,它的代换规则和凯撒密码类似,每个代换表是明文字母移位到0到25次以后得到的代换单表,其代换表如下表所示。
|
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 |
c | 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 | 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 |
现设密钥为cipher,明文为seeyoulate,其加密结果如下:
- 密钥:ciphereiph
- 明文:seeyoulate
-
密文:UMTFSLNIIL
明文的第1个字母为s,密钥的第1个字母为c,密文则是第c行第s列对应的字母U,在明文中第二个字母和第三个字母都是e,但由于密钥不同,因此加密得到的密文也不同,这样,密文隐藏了明文的统计特性。由于密钥的长度为6,那么在第6个字母之后密钥循环使用,即第7个明文字母加密时使用的是密钥的第1个字母,以此类推。因此,与单表代替密码相比维吉尼亚密码具有更高的安全性。
Cpp源代码
完整的实现共包括三个相应的文件,vigenere.h、 vigenere.cpp和main.cpp,在vigenere.h中主要完成对类的声明,vigenere.cpp文件主要完成vigenere.h中声明函数的定义,main.cpp中主要是对象的调用。
vigenere.h的代码如下:
#ifndef VIGENERE_H #define VIGENERE_H #include<string> using namespace std; class Vigenere{ private: int cipherTable[26][26]; //数字编码表 string key; //密钥 string explicitly; //待处理的明文 string cipherText; //加密后的密文 string explicitlyText; //解密后的明文 public: Vigenere(); void init(); //初始化 cipherTable void setKey(string k); //设置加密密钥 void setExplicitly(string ex); //设置明文 void encryption(); //加密明文,获得密文 void decryption(); //将密文转换为明文 void outPutCipherText(); //将处理结果(加密的密文)输出 void outPutExplicitlyText(); //将处理结果(解密的明文)输出 int getPosition(int P,int n); //获取密文解密的位置 }; #endifvigenere.cpp的代码如下:
#include "vigenere.h" #include <iostream> Vigenere::Vigenere(){ init(); } void Vigenere::init(){ int i,j; for(int i=0; i<26; i++){ for(int j=0; j<26; j++){ cipherTable[i][j]=(i+j)%26; } } } void Vigenere::encryption(){ cipherText = explicitly; //初始化密文为明文 unsigned int i; int m,n; for(i=0; i<explicitly.length(); i++){ m=int(explicitly[i]-'a'); n=int(key[i%(key.length())]-'a'); cipherText[i]=char('A'+cipherTable[n][m]); } } void Vigenere::decryption(){ explicitlyText=cipherText; //初始化解密明文为密文 unsigned int i; int m,n; for(i=0;i<cipherText.length();i++){ n=int(key[i%(key.length())]-'a'); m=getPosition(i,n); explicitlyText[i]=char('a'+m); } } int Vigenere::getPosition(int p, int n){ int position; int i; for(i=0;i<26;i++){ if(char(cipherText[p])==char('A'+cipherTable[n][i])){ position=i; break; } } return position; } void Vigenere::setKey(string k){ key=k; } void Vigenere::setExplicitly(string ex){ explicitly=ex; } void Vigenere::outPutCipherText(){ cout<<cipherText<<endl; } void Vigenere::outPutExplicitlyText(){ cout<<explicitlyText<<endl; }main.cpp的代码如下:
#include <iostream> #include <string> #include "vigenere.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char** argv) { Vigenere *v = new Vigenere(); string key = "cipherciph"; string ex = "seeyoulate"; v->setKey(key); v->setExplicitly(ex); v->encryption(); cout<<"加密效果:"; v->outPutCipherText(); v->decryption(); cout<<"解密效果:"; v->outPutExplicitlyText(); return 0; }执行效果如下: