1. 实现凯撒密码加密解密,核心代码如下:
加密函数以及解密函数:
解密函数相当于加密函数减去秘钥%26,代码如下:
调用加密和解密函数:
main函数如下:
其中选择信息:
如果不退出程序可以一直运行,如果用户选择退出,输入0或者任何其他的数字其实都可以退出程序。程序返回1。
#include <iostream>
#include <string>
using namespace std;
std::string caesar_encrypt(std::string text, int shift) {
std::string result = "";
for (char& c : text) {
if (isalpha(c)) {
char base = islower(c) ? 'a' : 'A';
result += static_cast<char>((c - base + shift) % 26 + base);
} else {
result += c;
}
}
return result;
}
std::string caesar_decrypt(std::string text, int shift) {
return caesar_encrypt(text, -shift);
}
void msg(){
cout << "--------------凯撒密码----------------" << endl;
cout << "--------------请输入数字---------------" << endl;
cout << "--------------1: 加密-----------------" << endl;
cout << "--------------2: 解密-----------------" << endl;
cout << "--------------0: 退出----------------" << endl;
}
void encrypted(){
string s;
int n;
cout << "请输入加密秘钥"<< endl;
cin >> n;
cout << "请输入要加密的字符串" << endl;
cin >> s;
std::cout << "Original text: " << s << std::endl;
std::string encrypted_text = caesar_encrypt(s, n);
std::cout << "Encrypted text: " << encrypted_text << std::endl;
cout << endl;
}
void decrypted(){
string s;
int n;
cout << "请输入秘钥"<< endl;
cin >> n;
cout << "请输入要解密的字符串" << endl;
cin >> s;
std::cout << "Original text: " << s << std::endl;
std::string decrypted_text = caesar_decrypt(s, n);
std::cout << "Decrypted text: " << decrypted_text << std::endl;
cout << endl;
}
int main() {
system("chcp 65001");
while(1){
int choice;
msg();
cin >> choice;
cin.ignore();
switch(choice){
case 1:encrypted();
break;
case 2:decrypted();
break;
default:
return 1;
}
}
return 0;
}
2. 实现矩阵换位法加密解密,核心代码如下:
输入输出与上一个程序相同,但是程序的加密解密为了清晰分开写。
加密函数核心源代码如下:
得到密钥矩阵:
得到每一行交换后的结果:
行列变换:
行列变换之后的最后一次交换:
解密函数源代码如下:
切割分组,完成第一次矩阵交换:
行列交换:
每一行交换即可解密成功:
以上就是加密解密函数。
还有重要的函数如下:
明文字符串切割,按照密钥的倍数:
密文字符串切割:
main函数,与上一个程序逻辑相同:
打印信息的工具类:
依然是工具函数,因为都要输入密钥,所以把加密解密输入密钥放到了一起:
以上就是全部的核心代码
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
//生成秘钥矩阵,一个矩阵反复用
int** createMatrix(string key) {
string key1 = key;
int n = key.length();
// 创建二维数组 arr,包含2行n列
int** arr = new int*[2];
for (int i = 0; i < 2; i++) {
arr[i] = new int[n];
}
// 初始化第一行为索引值
for (int i = 0; i < n; i++) {
arr[0][i] = i;
}
// 按照排序后的 key 的顺序初始化第二行
string sorted_key = key;
sort(sorted_key.begin(), sorted_key.end());
cout << "//排序后的秘钥:" << sorted_key << endl;
for (int i = 0; i < n; i++) {
arr[1][i] = sorted_key.find(key[i]);
}
return arr;
}
void msg(){
cout << "-------------矩阵换位法----------------" << endl;
cout << "--------------请输入数字---------------" << endl;
cout << "--------------1: 加密-----------------" << endl;
cout << "--------------2: 解密-----------------" << endl;
cout << "--------------0: 退出----------------" << endl;
}
//明文字符串切割
vector<string> splitString(std::string str, int chunkSize) {
std::vector<std::string> result;
std::string currentChunk = "";
for (char c : str) {
if (isalpha(c)) {//判断是字母
currentChunk += c;
if (currentChunk.length() == chunkSize) {
result.push_back(currentChunk);
currentChunk = "";
}
}
}
// 若最后一个chunk还有剩余字符,添加到result中
if (!currentChunk.empty()) {
result.push_back(currentChunk);
}
return result;
}
//密文字符串切割
std::vector<std::string> splitString_de(std::string str, int chunkSize) {
//切割成密文长度除以秘钥长度大小
std::vector<std::string> result;
std::string currentChunk = "";
string clean_str = "";
/*
* 如果是字母就加进来
*这个算法主要是换位置,不用考虑密文大小写
*/
for (char c : str) {
if (isalpha(c)) {
clean_str += c;
}
}
int num = clean_str.length();
chunkSize = num/chunkSize;
for (char c : str) {
if (isalpha(c)) {
currentChunk += c;
if (currentChunk.length() == chunkSize) {
result.push_back(currentChunk);
currentChunk = "";
}
}
}
// 若最后一个chunk还有剩余字符,添加到result中
if (!currentChunk.empty()) {
result.push_back(currentChunk);
}
return result;
}
//解密函数
void decrypted(string key,string text){
//获取秘钥矩阵,矩阵其实没什么区别,两行
//加密解密就看怎么用
int ** arr = createMatrix(key);
int row1 = 0;int row2 = 1;
int * arr1 = arr[row1];
int * arr2 = arr[row2];
int n = key.length();
//将输入的密文text拆开
vector<string> splittedStrings_de1 = splitString_de(text, n);
//大变换
vector<string> result_de1 = splittedStrings_de1;
for (const std::string& str : splittedStrings_de1) {
//交换得到最后一次大交换前
for(int i = 0;i < n; i++){
result_de1[arr2[i]] = splittedStrings_de1[arr1[i]];
}
}
//打印一下矩阵大变换环节结果 debug
for (string s:result_de1){
cout << s << " ";
}
cout << endl;
//大变换之后,完成一次行列转换
vector<string> result_de2;
// 输出每个字符串的第i个字符
string newString = "";
int temp = result_de1[0].length();
for (int i = 0; i < temp; i++) {
for (const string& s : result_de1) {
newString += s[i]; // 添加当前字符串的第i个字符
}
// cout << newString << endl; // 打印新字符串
result_de2.push_back(newString);
newString = ""; // 重置新字符串为空
}
//最后完成每一行的小变换
vector<string> result_final_de;
for (const std::string& str : result_de2) {
//设置一个变量,和秘钥的长度相等,所以初始化为秘钥即可
string str1 = key;
for(int i = 0;i < n; i++){
str1[arr2[i]] = str[arr1[i]];
}
result_final_de.push_back(str1);
}
//最后打印出来,验证解密是否成功
cout << "明文如下: " << endl;
for (const std::string& str : result_final_de) {
//设置一个变量,和秘钥的长度相等,所以初始化为秘钥即可
cout << str << endl;
}
}
void encrypted(string key,string text,bool flag){
int ** arr = createMatrix(key);
int row1 = 0;int row2 = 1;
int * arr1 = arr[row1];
int * arr2 = arr[row2];
//打印一下秘钥矩阵
// 打印二维数组
cout << "秘钥交换矩阵如下:" << endl;
for (int i = 0; i < 2; ++i) { // 遍历行
for (int j = 0; j < key.length(); ++j) { // 遍历列
cout << arr[i][j] << "\t";
}
cout << endl;
}
int n = key.length();
std::vector<std::string> splittedStrings = splitString(text, n);
int size_splittedStrings = splittedStrings.size();
// 打印切割后的子字符串数组
cout << "\n第一次切割后的明文" << endl;
for (const std::string& str : splittedStrings) {
std::cout << str << std::endl;
}
//交换每一行
vector<string> result1;
for (const std::string& str : splittedStrings) {
//设置一个变量,和秘钥的长度相等,所以初始化为秘钥即可
string str1 = key;
for(int i = 0;i < n; i++){
str1[arr1[i]] = str[arr2[i]];
}
result1.push_back(str1);
}
//打印
cout << "\n交换每一行明文之后:" << endl;
for (const std::string& str : result1) {
std::cout << str << std::endl;
}
//行列交换
vector<string> result2;
// 输出每个字符串的第i个字符
string newString = "";
for (int i = 0; i < n; i++) {
for (const string& s : result1) {
newString += s[i]; // 添加当前字符串的第i个字符
}
result2.push_back(newString);
newString = ""; // 重置新字符串为空
}
cout << "\n交换行和列之后:" << endl;
for (const std::string& str : result2) {
std::cout << str << std::endl;
}
//将新字符串再交换一次位置即可
vector<string> final_result_en = result2;
for (const std::string& str : result1) {
//设置一个变量,和秘钥的长度相等,所以初始化为秘钥即可
if(flag){
for(int i = 0;i < n; i++){
final_result_en[arr1[i]] = result2[arr2[i]];
}
} else{
for(int i = 0;i < n; i++){
final_result_en[arr2[i]] = result2[arr1[i]];
}
}
}
cout << "\n进行最后一次交换得到密文如下:" << endl;
for (string s:final_result_en){
cout << s << " ";
}
cout << endl;
}
void cry(int n){
string key;
string s;
cout << "请输入密钥:" << endl;
cin >> key ;
if(n == 1){
cout << "请输入要加密的字符串" << endl;
cin.ignore();
getline(cin,s);
std::cout << "Original text: " << s << std::endl;
encrypted(key,s, true);
} else if(n == 2){
cout << "请输入要解密的字符串" << endl;
cin.ignore();
getline(cin,s);
std::cout << "Original text: " << s << std::endl;
decrypted(key,s);
}
}
int main() {
system("chcp 65001");
while(1){
int choice;
msg();
cin >> choice;
cin.ignore();
switch(choice){
case 1://加密
cry(1);
break;
case 2://解密
cry(2);
break;
default://退出循环,代码返回1
return 1;
}
}
return 0;
}
3.实验结果
....省略一些截图
加密:
解密:
测试退出循环
第一个程序很简单,对于写程序而言,加密解密可以调用同一个函数传入不同参数即可。
第二个程序可能存在不足,时空复杂度可以再下降,为了展示完成过程,打印了中间结果。但是加密解密过程都是相似的,核心源代码主要是构造一个二维数组作为交换矩阵,然后加密是先分组,然后交换每一个小分组,然后行列变化,然后对大的做一次交换。
所以假设密钥字长度为n, 明文长度为len_m ,所以小分组有len_m/n =num_m(向上取整)个,需要交换num_m个小分组,然后转为列存储交换一次后输出。
所以一开始我没理解好规则将第二个程序加密解密写在一起了,后来我又分开做了实现。需要处理字符串数据,用到一些好的数据结构很重要,我觉得用python可能会简单一点点。