龙空技术网

PlayFair加密方法原理及C+ +实现

AugustTheo 87

前言:

而今咱们对“c语言编写字母替换加密算法”大约比较看重,各位老铁们都想要学习一些“c语言编写字母替换加密算法”的相关文章。那么小编同时在网络上网罗了一些对于“c语言编写字母替换加密算法””的相关文章,希望兄弟们能喜欢,大家快快来了解一下吧!

普莱费尔密码(英文:Playfair cipher 或 Playfair square)是一种使用一个关键词方格来加密字符对的加密法,1854年由一位名叫查尔斯·惠斯通(Charles Wheatstone)的英国人发明。

加密步骤(我们采用英语作为语言)1 选择一个(不包括z的)口令,然后去除其中重复的字母作为密钥

我选择口令为augusttheodor,则密钥为augstheodr。

2 按照口令和字母表编制5*5密码表

由于我们使用的是英语,采用去掉Z的规则时字母表共有25个,刚好不需要删减字母。事先约定密码表以行优先(也就是前n行放密钥),按照密钥-字母表中除了密钥之外的字母的顺序排列成5*5矩阵。

对于这个矩阵,第一列是最后一列的右列,第一行是最后一行的下行,也就是它是循环的。

3 整理明文

我们约定插入字母为X(也可以为Q)

我们按照以下步骤对明文进行整理:

1.我们规定从头数起每两个字母为一个字母对。

2.在两两重复的字母对中的每个字母,插入一个插入字母构成两个字母对。

3.对插入之后的明文计数,如果明文的字母数为奇数,就在其末尾添加一个插入字母。

4 加密

对于字母对<x,y>在密码表中的位置:

1.x与y在同一行,我们用x与y在密码表中右侧的字母替代。

2.x与y在同一列,我们用x与y在密码表中下方的字母替代。

3.x与y既不在同一列也不在同一行,我们以其为对角线构造一个矩形,然后选择此矩形上另两个顶点对应的字母替代。至于替代顺序需要事先约定,我们这里规定同行替代。

解密步骤1 按照手上的密钥构造密码表2 解密

对密码对<a,b>,如果:

1.ab在同一行:则明文对cd分别在其左侧

2.ab在同一列:则明文对cd分别在其上侧

3.ab的其他情况:则明文为以其为对角线构造的矩形的另两个顶点

# 解密算法

相比于加密,解密的步骤其实并不困难,也就是最后的加密算法中最后的加密操作倒过来执行而已。

PlayFair算法的优点与缺点优点

-破译工具简单

-采用双字母加密,相较于替换单字母的加密方式更为安全(请参照福尔摩斯中跳舞小人案)

缺点

-转换的密文不够精确,构建矩阵的时候需要取舍字母

-有很多需要提前约定的部分

示例1 明文摘自Natural第一节:

Will you hold the line

When every one of them is giving up or giving in, tell me

In this house of mine

Nothing ever comes without a consequence or cost, tell me

Will the stars align?

Will heaven step in? Will it save us from our sin? Will it?

2 我们将明文全部小写然后去除非字母的所有符号,得到:

willyouholdthelinewheneveryoneofthemisgivinguporgivingintellmeinthishouseofminenothingevercomeswithoutaconsequenceorcosttellmewillthestarsalignwillheavenstepinwillitsaveusfromoursinwillit

# 可以使用ruby的downcase(全部小写)与gsub(正则表达式)完成这个步骤,代码如下:

a='''

你的未经处理的明文

'''

p a.downcase.gsub(/[^a-z]/,'')

口令为:

augusttheodor

则构造的密码表为:

[ A, U, G, S, T,

H, E, O, D, R,

B, C, F, I, J,

K, L, M, N, P,

Q, V, W,X, Y,]

3 则明文构成的字母对为:

wi lx lx yo uh ol dt he li ne wh en ev er yo ne of th em is gi vi ng up or gi vi ng in te lx lx me in th is ho us eo fm in en ot hi ng ev er co me sw it ho ut ac on se qu en ce or co st te lx lx me wi lx lx th es ta rs al ig nw il lh ea ve ns te pi nw il li ts av eu sf ro mo ur si nw il li tx

4 通过加密,获得的密文为:

xfnvnvwrgeemraeomjldgodlcuohwrldfmaeolndsfxcmstldhsfxcmsnxaonvnvlonxaendedgtodmwnxdldadbmscuohfdlogxjsedgaubdmtoagdllcdhfdtaaonvnvloxfnvnvaeotaudtukfspxjmkehuucxdaonjpxjmmjatugcegihdwftednpxjmmjsy

加密算法的C++实现

其实可以算是C语言的实现了,除了io之外并没有用到什么C++特有的部分。

当然,如果想用Python写只会更简单,使用C++的原因只是惯例和顺带温习一下指针。

1 算法文件构成

-_playfair.h:头文件,包括各种用于加密的函数

-_playfair.cpp:实现_playfiar.h文件中声明的文件

-PLAYFAIR.cpp:主文件,main函数的文件

2 _playfair.h

#pragma once

const int MAXH = 22256; //输入最大文字数

const int MAXC = 1024; //输入的明文对最大数量

const char STOPC = 'x'; //插入字母

char* getCipher(char* a); //根据口令获取密钥

int countCipher(char* a); //返回密钥长度

char** getRect(int count,char* a); //返回密码矩阵

void getPairs(char in[], char p[][2]); //获得明文对

int wh_location(char p, char** rect); //返回一个十位为行个位为列的描述字母位置的数字

int is_situation(int p1, int p2); //判断两个字母在密码表中的情况

void getCiphertext(char** rect, char p[][2], char*ciphertext); //获取密文

int cipherCicle(int c); //判断循环

3 _playfair.cpp

#include "_playfair.h"

#include<stdlib.h>

#include<iostream>

using namespace std;

char* getCipher(char* a)

{

char _s[27]; //存放出现过的字母的临时数组

int _m = 0; //游标

int _n = 0; //同上

bool flag = false; //相同字母是否出现的bool

static char re[27] ; //返回的字符串//口令转换后的长度必然不大于26 //请注意,这是一个静态变量,因为要保证返回的指针的正确性

for (int i = 0; i < 27; i++) {

_s[i] = ' ';

re[i] = ' ';

} //赋值

for (int i = 0; a[i]!='\0'; i++) {

for (int m = 0; m < 26; m++) {

if (_s[m] == a[i]) { //出现过这个字母

flag = true;

break;

}

}

if (flag == false) {

re[_m] = a[i]; //输出字母

_m++;

_s[_n] = a[i]; //记录出现

_n++;

}

flag = false;

}

re[_m] = '\0'; //记录结束

return re;

}

int countCipher(char* a) {

int count = 0;

for (int i = 0; a[i] != '\0'; i++) {

count++;

}

return count;

}

char** getRect(int count, char* a) { //列先行后

static char **rect;

rect = (char**)malloc(sizeof(char*) * 5); //是五个指向字符数组的指针

for (int i = 0; i < 5; i++) {

rect[i] = (char*)malloc(sizeof(char) * 5); //是五个成员的字符数组

}

char alfabeto[] = "abcdefghijklmnopgrstuvwxy"; //字母表 //我们采用去掉z的方式构建,所以口令与密码矩阵里都没有z

for (int i = 0; i < count; i++) {

int l = i % 5;

int h = i / 5;

rect[h][l] = a[i]; //赋值

}

for (int m = 0; m < count; m++) { //去除出现过的字母

for (int i = 0; i < 26; i++) {

if (alfabeto[i] == a[m]) {

alfabeto[i] = ' ';

break;

}

}

}

for (int i = count; i < 25; i++) {

int l = i % 5;

int h = i / 5;

for (int m = 0; m < 26; m++) { //遍历到第一个非空字母

if (alfabeto[m] != ' ') {

rect[h][l] = alfabeto[m];

alfabeto[m] = ' ';

break;

}

}

}

return rect;

}

void getPairs(char in[], char p[][2]) {

int keys = 0; //字母对计数

for (int m = 0; in[m] != ' '; m=m+2) { //步长为2

if (in[m] == in[m + 1]) { //如果出现重复字母对

p[keys][0] = in[m];

p[keys][1] = STOPC;

p[keys + 1][0] = in[m];

p[keys + 1][1] = STOPC;

keys = keys + 2;

}

else {

p[keys][0] = in[m];

if (in[m + 1] == '\0') { //奇数末尾的处理

p[keys][1] = STOPC;

}

else {

p[keys][1] = in[m + 1];

}

keys++;

}

}

return;

}

int wh_location(char p, char**rect) {

for (int i = 0; i < 5; i++) {

for (int m = 0; m < 5; m++) {

if (p == rect[i][m]) {

return i * 10 + m;

}

}

}

return -1; //Z的情况我没看到有资料写怎么处理

}

int is_situation(int p1, int p2) {

if (abs(p1 - p2) < 10) { //在同一行

return -1;

}

else if (abs(p1 - p2) % 10 == 0) { //在同一列

return 1;

}

else {

return 0;

}

}

int cipherCicle(int c) {

if (c >= 5) {

return c - 5;

}

else if (c < 0) {

return c + 5;

}

return c;

}

void getCiphertext(char** rect, char p[][2], char* ciphertext) {

int loc1, loc2;

int m = 0; //游标

for (int i = 0; p[i][0] != ' '; i++) {

loc1 = wh_location(p[i][0],rect);

loc2 = wh_location(p[i][1], rect);

switch (is_situation(loc1, loc2)) {

case 1:

ciphertext[m] = rect[cipherCicle(loc1 / 10 + 1)][loc1 % 10];

ciphertext[m + 1] = rect[cipherCicle(loc2 / 10 + 1)][loc2 % 10];

break;

case -1:

ciphertext[m] = rect[loc1 / 10][cipherCicle(loc1 % 10 + 1)];

ciphertext[m + 1] = rect[loc2 / 10][cipherCicle(loc2 % 10 + 1)];

break;

case 0: //同行取代也就是,保留行数,交换列数

ciphertext[m] = rect[loc1 / 10][loc2 % 10];

ciphertext[m + 1] = rect[loc2 / 10][loc1 % 10];

break;

}

m = m + 2;

}

}

4 PLAYFAIR.cpp

#include"_playfair.h"

#include<iostream>

using namespace std;

int main() {

char passkey[256];

char plaintext[MAXH]; //可以更改

char ciphertext[MAXH*2]; //加密算法生成的密文不会膨胀

char p[MAXC][2]; //明文对

for (int i = 0; i < MAXC; i++) {

p[i][0] = ' ';

p[i][1] = ' ';

}

for (int i = 0; i < MAXH; i++) {

plaintext[i] = ' ';

ciphertext[i] = ' ';

} //赋初值

cout << "请输入口令(不包括z):";

cin >> passkey;

cout << "正在生成密钥。。。" << endl;

char* cipher = getCipher(passkey);

for (int i = 0; cipher[i] != ' '; i++) {

cout << cipher[i];

}//显示密钥

cout << endl;

int count = countCipher(cipher); //获取密钥长度

cout << "正在获取密码矩阵。。。" << endl;

char** rect = getRect(count, cipher); //获取矩阵

for (int i = 0; i < 5; i++) {

for (int m = 0; m < 5; m++) {

cout << rect[i][m] << ' ';

}

cout << endl;

}//显示矩阵

cout << "请输入明文(不包括z):" << endl;

cin >> plaintext; //获取明文

cout << "正在获取明文对。。。" << endl;

getPairs(plaintext, p); //获取明文对

for (int i = 0; p[i][0] != ' '; i++) {

cout << p[i][0] << p[i][1] << ' ';

}//显示明文对

cout << endl;

cout << "正在获取密文。。。" << endl;

getCiphertext(rect, p, ciphertext); //获取密文

for (int i = 0; ciphertext[i] != ' '; i++) {

cout << ciphertext[i];

} //显示密文

}

标签: #c语言编写字母替换加密算法