目录
一、前言
作者:钱塘江上潮信来,今日方知我是我
原创内容转载需说明
二、原理
加密:
移位类似凯撒加密;替换采用用了map映射思想,数组下标对应要加密字符的ascii码,数组的值是下标相应的替换字符;置换:col设置一行最多有几列,做成二维表,然后两列两列相交换,剩下的单列不交换,使用列存储的方式转化成一维数组。
解密:
与加密反着来,再反转解密顺序。
三、代码
#include <iostream>//C++标准输入输出函数和常用函数文件
#include <string>//存储字符串操作函数文件
#include <vector>//存储数据类型模版容器函数文件
//声明流输入输出、字符串和vector容器操作等功能
using std::cin;
using std::cout;
using std::string;
using std::vector;
//移位操作函数(-key可以还原字符串)
/* 默认操作可见字符,若想设置默认所有ASCII表内字符则分别设置为0, 127, 128 */
string Shift(string str, short key, short begin = 32, short end = 126, short base = 95);
//替换操作函数
/* 默认操作可见字符,若想设置默认所有ASCII表内字符则分别设置为0, 127 */
string ToMapping(string str, short begin = 32, short end = 126);
//替换成原来的操作函数
/* 默认操作可见字符,若想设置默认所有ASCII表内字符则分别设置为0, 127 */
string ReMapping(string str, short begin = 32, short end = 126);
string Map;//替换表,储存ASCII表内替换内容
string InitMap();//初始化Map表
/*ASCII表可显示字符有: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ */
string map0_9 = "7853214690";//0到9替换表
string mapA_Z = "poiuytrewqlkjhgfdsamnbvcxz";//A到Z替换表
string mapa_z = "MNBVCXZLKJHGFDSAPOIUYTREWQ";//a到z替换表
//其他符号的替换:
string map32_47 = "+-)!#$(\" /\'*.,&%";
string map58_64 = "<@;?:=>";
string map91_96 = "`^_][\\";
string map123_126 = "~}{|";
/* 不可显示符号的替换: { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,127 };*/
string map0_31 = { 20,21,22,23,24,25,16,127,18,19,10,31,30,29,28,27,26,12,13,14,15,11,8,9,6,7,4,5,2,3,0,1 };
char map127 = 17;
//置换操作
string Permutation(string str, unsigned short cols, bool &b);
//反置换操作
string RePermutation(string str, unsigned short cols, bool &b);
//加密函数
string Encrypted(string str, short key, unsigned short col, bool &b);
//解密函数
string Decrypt(string str, short key, unsigned short col, bool &b);
int main() {
/* {
//对照表,ascii可显示字符串,32:126。测试数据用到,加密解密未用到。
string Initial_Array;
for (size_t i = 0; i < 95; i++) {
Initial_Array += char(i + 32);
}
cout << Initial_Array << '\n';
cout << Initial_Array.length();
}*/
string str;//储存加密解密字符串
short key = 5;//向左移5位。负数向右移。
short col = 5;//置换表设置成5列。
bool b = true;//字符串长度大于等于置换表列数(5)。
Map = InitMap();//初始化替换表。
cout << "请输入要加密的字符串:\n";
cin >> str;
//进行一次加密
string str1 = Encrypted(str, key, col, b);
if (!b) {cout << "加密失败";return -1;}//如果输入字符串小于置换表列长(5)
cout << "加密后的字符串为:\n" << str1 << '\n';//输出结果
//进行一次解密
str = Decrypt(str1, key, col, b);
cout << "解密后的字符串为:\n" << str << '\n';//输出结果
return 0;
}
//移位函数
string Shift(string str, short key, short begin, short end, short base) {
string s;
short t = 0;
for (short i = 0; i < str.length(); i++) {
t = str[i];
if (t >= begin && t <= end) {
t += key;
if (t > end) s += char(t - base);
else if (t < begin) s += char(t + base);
else s += char(t);
}
else s += char(t);
}
return s;
}
//映射替换
string ToMapping(string str, short begin, short end) {
string s;
for (char& c : str)
for (short i = begin; i <= end; i++)
if (c == i) {
s += Map[i];
break;
}
return s;
}
//替换回来
string ReMapping(string str, short begin, short end) {
string s;
for (char& c : str)
for (short i = begin; i <= end; i++)
if (c == Map[i]) {
s += char(i);
break;
}
return s;
}
string InitMap() {//初始化替换表
string s;
s = map0_31;
s += map32_47;
s += map0_9;
s += map58_64;
s += mapA_Z;
s += map91_96;
s += mapa_z;
s += map123_126;
s += map127;
return s;
}
//置换函数
string Permutation(string str, unsigned short cols, bool &b) {
unsigned short len = unsigned short(str.length());
if (len < cols) {
cout << "置换失败:字符串总长度小于所设置的列长("<< cols <<")\n";
b = false;
return str;
}
unsigned short rows = unsigned short(len / cols);
if (rows * cols != len)rows += 1;
// 使用vector来创建二维数组
vector<string> t1(rows, string(cols, '\0'));
vector<string> t2(rows, string(cols, '\0'));
//分割数组
unsigned short row = 0;
unsigned short col = 0;
for (unsigned short i = 0; i < len; i++) {
col = i % cols;
if (i != 0 && col == 0)row += 1;
t1[row][col] = str[i];
t2[row][col] = str[i];
col++;
}
if (cols > 1) {//第一列和第二列换,第三列和第四列换,第五列和第六列换……
for (unsigned short i = 0; i < cols; i+=2) {
for (unsigned short j = 0; j < rows; j++) {
if (t1[j][i + 1] == '\0')break;//单行不换
t1[j][i] = t2[j][i + 1];
t1[j][i+1] = t2[j][i];
}
}
}
// 列录入:将二维数组转换为一维字符串
string s;
for (unsigned short i = 0; i < cols; i++) {
for (unsigned short j = 0; j < rows; j++) {
s += t1[j][i];
}
}
return s;
}
//置换回来
string RePermutation(string str, unsigned short cols, bool &b) {
unsigned short len = unsigned short(str.length());
if (len < cols) {
cout << "置换失败:字符串总长度小于所设置的列长(" << cols << ")\n";
b = false;
return str;
}
unsigned short rows = unsigned short(len / cols);
if (rows * cols != len)rows += 1;
// 使用vector来创建二维数组
vector<string> t1(rows, string(cols, '\0'));
vector<string> t2(rows, string(cols, '\0'));
//逆列录入,将一维数组转换为二维字符串
unsigned short x = 0;
for (unsigned short i = 0; i < cols; i++) {
for (unsigned short j = 0; j < rows; j++) {
t1[j][i] = str[x];
t2[j][i] = str[x];
x++;
}
}
/*for (unsigned short i = 0; i < rows; i++) {
for (unsigned short j = 0; j < cols; j++) {
cout << t1[i][j];
}
cout << '\n';
}
cout << '\n';*/
if (cols > 1) {//第一列和第二列换,第三列和第四列换,第五列和第六列换……
for (unsigned short i = 0; i < cols; i += 2) {
for (unsigned short j = 0; j < rows; j++) {
if (t1[j][i + 1] == '\0')break;//单行不换
t1[j][i] = t2[j][i + 1];
t1[j][i + 1] = t2[j][i];
}
}
}
// 将二维数组转换为一维字符串
string s;
for (const auto& row : t1) {
s += row;
}
return s;
}
//一次三操作加密
string Encrypted(string str, short key, unsigned short col, bool &b) {
//ASCII表所有字符移位。32,126,95是可见字符移位
string str1 = Shift(str, key, 0, 127, 128);
//进行替换
string str2 = ToMapping(str1);
//进行置换
str = Permutation(str2, col, b);
return str;
}
//一次三操作解密
string Decrypt(string str, short key, unsigned short col, bool &b) {
//进行反置换
string str1 = RePermutation(str, col, b);
//进行反替换
string str2 = ReMapping(str1);
//反移位。
str = Shift(str2, -key, 0, 127, 128);
return str;
}