前言:
而今咱们对“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语言编写字母替换加密算法