原理介绍
在上述加密方法中,密文字母和明文字母之间是一对一映射 ,其加密方法均无法掩盖明文数据的统计特性,通过统计计算密文字母的统计特性,比较容易找出明文和密文之间的对应关系,从而达到破解密文的目的。
以英文文章为例,不同的字母在文章中出现的频率是不同的,美国密码学家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); //获取密文解密的位置
};
#endif
vigenere.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;
}
执行效果如下:
京公网安备 11010502036488号