CQU密码学实验1

本文介绍了如何使用C++实现凯撒密码和矩阵换位法的加密解密功能,包括核心代码示例和加密解密流程,展示了两种不同的加密策略和其实现细节。
摘要由CSDN通过智能技术生成

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可能会简单一点点。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值