您的位置:首页 > 大数据 > 人工智能

[古典密码]:PlayFair cipher(Playfair密码)

2016-09-10 14:52 316 查看

来源于我的博客

1.编制密码表 

构造一个5*5的密码表,表格填充关键字(字母不重复),之后按字典序填充密码表中没有的字母,需要注意的是5*5表格只能放25个字母,剩下一个字母需要选择已经放入表的一个作为替代,这里习惯性将J省略,I/J共用。

以关键字为PLAYFAIR
EXAMPLE为例



PLAYF
I/JREXM
BCDGH
KNOQS
TUVWZ
得到如上密码表

2.整理明文

由于PalyFair成对字母加密的特性,要对明文进行分组处理:

两个不同的字母一组,如果字母相同需要添加冗余(指定一个字母)保持其不同;

最后如果有单个字母同样需要添加冗余使其成对。

以明文“Things are not always what they see”为例(指定W为替代字母)
整理后变成:“TH IN GS AR EN OT AL WA YS WH AT TH EY SE EW”

3.加密

根据成对字母在字母表中的相对位置进行替代

主要分两类:

在一条线上(行相同或列相同)

x相同,就取x+1位置的字母(mod 5,即最右边+1=最左边的):

y相同,就取y+1位置的字母(mod 5,即最下边+1=最上边的):
AL=YA
PLAYF
I/JREXM
BCDGH
KNOQS
TUVWZ
不在一条线上

        取两点为顶点的矩形,矩形的另外两点即为密文

注意的是顺序:横坐标保持不变,纵坐标改为pair的纵坐标
T-Z  H-B I-R K-N 他们的横坐标均相同
TH=ZB

PLAYF
I/JREXM
BCDGH
KNOQS
TUVWZ
  IN=RK

PLAYF
I/JREXM
BCDGH
KNOQS
TUVWZ
C++实现:

#include#include#includeusing namespace std;
//string keyWord = { "MoonCake" };
string keyWord = { "PLAYFAIR EXAMPLE" };
string alphabet = { "ABCDEFGHIKLMNOPQRSTUVWXYZ" };
char a[5][5] = { " " };
pair getPosi(char c) {
for (int i = 0;i < 5;i++) {
for (int j = 0;j < 5;j++) {
if (c == a[i][j]) return make_pair(i,j);
}
}
return make_pair(6, 6);//(5*5缺少一个字母)失败
}
string SplitWord_(string f) {
string g;
int count_g = 0;
int char_c = 0;
//作简单分割
for (int i = 0;i < f.size();) {
for (int j = 0;j < 2;j++) {
if ((int)(f[i])>64 && (int)(f[i]) < 91) {
//g[count_g++] = f[i];
string t_f;
t_f.resize(1);
t_f[0] = f[i];
g.append(t_f);
char_c++;
}
if (((int)(f[i]) > 96) && ((int)(f[i]) < 123)) {
//g[count_g++] = (char)((int)f[i] - 32);
string t_f;
t_f.resize(1);
t_f[0]= (char)((int)f[i] - 32);
g.append(t_f);
char_c++;
}
if (char_c == 2&&i!=f.size()&& i != f.size()-1) {
//g[count_g++] = ' ';
g.append(" ");
char_c = 0;
}
i++;
}
}
//cout << g << "e"<<endl;
return g;
}
bool is_dup(string g,int &posi) {
for (int i = 0;i < g.size()-1;i++) {
if (((int)(g[i]) > 64) && ((int)(g[i]) < 91)&& ((int)(g[i+1]) > 64) && ((int)(g[i+1]) < 91)) {
if (g[i] == g[i + 1]) {
posi = i;
posi++;
return true;
}
}
}
return false;
}
string SplitWord(string f, char replace) {
string g = SplitWord_(f);
//插值(replace)去除重复
int posi = 0;
string re;
re.resize(1);
re[0] = replace;
while (is_dup(g,posi)) {
g.insert(posi,re);
g = SplitWord_(g);
}
//判断结尾是否成对
if ((g[g.size() - 2]) < 64 || (g[g.size() - 2]) > 91) {
g.insert(g.size(), re);
}
//明文整理完成
return g;
}
void CreateMatrix() {
int row = 0;
int colom = 0;
for (int i = 0;i < keyWord.size();i++) {
if (keyWord[i] == ' ') continue;
if ((int)keyWord[i]>96 && (int)keyWord[i] < 123) {
keyWord[i] = (char)((int)keyWord[i] - 32);
}
bool noMatch = true;
for (int x = 0;x < 5;x++) {
for (int y = 0;y < 5;y++) {
if (a[x][y] == keyWord[i]) {
noMatch = false;
}
}
}
if (noMatch) {
a[row][colom] = keyWord[i];
if (++colom > 4) {
colom = colom % 5;
row++;
}

}
}
//		填充剩余字母
for (int i = 0;i < alphabet.size();i++) {
bool noMatch = true;
for (int x = 0;x < 5;x++) {
for (int y = 0;y < 5;y++) {
if (a[x][y] == alphabet[i]) {
noMatch = false;
}
}
}
if (noMatch) {
a[row][colom] = alphabet[i];
if (++colom > 4) {
colom = colom % 5;
row++;
}

}
if (row == 5) break;
}
//填充完成
}
void PrintMatrix() {
for (int i = 0;i < 5;i++) {
for (int j = 0;j < 5;j++) {
cout << a[i][j] << " ";
}
cout << endl;
}
}

void encrypt(){
//create 5*5 Matrix
CreateMatrix();

string f = { "Things are not always what they see" };
f = { "MY Name IS ATUL" };
//整理明文
string g=SplitWord(f, 'W');

PrintMatrix();
cout << g << endl;
//加密
for (int i = 0;i < g.size()-1;) {
if (getPosi(g[i]).first != getPosi(g[i + 1]).first&&getPosi(g[i]).second != getPosi(g[i + 1]).second) {//对角
char gi = g[i];
char giPlus = g[i + 1];
g[i] = a[getPosi(gi).first][getPosi(giPlus).second];
g[i + 1] = a[getPosi(giPlus).first][getPosi(gi).second];
}
if (getPosi(g[i]).first == getPosi(g[i + 1]).first&&getPosi(g[i]).second != getPosi(g[i + 1]).second) {//同x轴 换成对应位于y+1的字母,越界则为最上面
char gi = g[i];
char giPlus = g[i + 1];
int giy = getPosi(gi).second;
giy = (giy+1) % 5;

int giPlusy = getPosi(giPlus).second;
giPlusy = (giPlusy+1) % 5;
g[i] = a[getPosi(gi).first][giy];
g[i + 1] = a[getPosi(giPlus).first][giPlusy];
}
if (getPosi(g[i]).first != getPosi(g[i + 1]).first&&getPosi(g[i]).second == getPosi(g[i + 1]).second) {//同y轴 换成对应位于x+1的字母,越界则为最上面
char gi = g[i];
char giPlus = g[i + 1];
int gix = getPosi(gi).first;
gix = (gix+1) % 5;

int giPlusx = getPosi(giPlus).first;
giPlusx = (giPlusx+1) % 5;
g[i] = a[gix][getPosi(gi).second];
g[i + 1] = a[giPlusx][getPosi(giPlus).second];
}
i+=3;
}
cout << g << endl;
}
void decrypt() {
CreateMatrix();
string g = { "XF OL IX MK PV LR" };
cout << g << endl;
//解密
for (int i = 0;i < g.size() - 1;) {
if (getPosi(g[i]).first != getPosi(g[i + 1]).first&&getPosi(g[i]).second != getPosi(g[i + 1]).second) {//对角
char gi = g[i];
char giPlus = g[i + 1];
g[i] = a[getPosi(gi).first][getPosi(giPlus).second];
g[i + 1] = a[getPosi(giPlus).first][getPosi(gi).second];
}
if (getPosi(g[i]).first == getPosi(g[i + 1]).first&&getPosi(g[i]).second != getPosi(g[i + 1]).second) {//同x轴 换成对应位于y-1的字母,越界则为最上面
char gi = g[i];
char giPlus = g[i + 1];
int giy = getPosi(gi).second;
giy = (giy - 1)>=0?(giy - 1):4;

int giPlusy = getPosi(giPlus).second;
giPlusy = (giPlusy - 1)>=0? (giPlusy - 1):4;
g[i] = a[getPosi(gi).first][giy];
g[i + 1] = a[getPosi(giPlus).first][giPlusy];
}
if (getPosi(g[i]).first != getPosi(g[i + 1]).first&&getPosi(g[i]).second == getPosi(g[i + 1]).second) {//同y轴 换成对应位于x-1的字母,越界则为最上面
char gi = g[i];
char giPlus = g[i + 1];
int gix = getPosi(gi).first;
gix = (gix - 1)>=0 ? (gix - 1):4;

int giPlusx = getPosi(giPlus).first;
giPlusx = (giPlusx - 1)>=0? (giPlusx - 1):4;
g[i] = a[gix][getPosi(gi).second];
g[i + 1] = a[giPlusx][getPosi(giPlus).second];
}
i += 3;
}
cout << g << endl;
}
int main() {
encrypt();
cout << "加密完成,立即解密" << endl;
decrypt();
cout << "解密完成" << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: