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

來源於我的博客

1.編制密碼錶 

構造一個5*5的密碼錶,表格填充關鍵字(字母不重複),之後按字典序填充密碼錶中沒有的字母,需要注意的是5*5表格只能放25個字母,剩下一個字母需要選擇已經放入表的一個作爲替代,這裏習慣性將J省略,I/J共用。

以關鍵字爲PLAYFAIR EXAMPLE爲例


P L A Y F
I/J R E X M
B C D G H
K N O Q S
T U V W Z

得到如上密碼錶


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

P L A Y F
I/J R E X M
B C D G H
K N O Q S
T U V W Z
  • 不在一條線上

        取兩點爲頂點的矩形,矩形的另外兩點即爲密文

注意的是順序:橫座標保持不變,縱座標改爲pair的縱座標

T-Z  H-B I-R K-N 他們的橫座標均相同

TH=ZB


P L A Y F
I/J R E X M
B C D G H
K N O Q S
T U V W Z

  IN=RK



P L A Y F
I/J R E X M
B C D G H
K N O Q S
T U V W Z

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章