信息安全之仿射密码加密和解密

时间:2021-12-18 05:40:57

本文利用仿射密码,对一个只含可打印字符的txt文件进行加密和解密。

//加解密时,文件内容为所有可打印字符,即ASCII码从32-126的95个字符
#include<iostream>
#include<fstream>
using namespace std;

//加密类
class Encrypt {
public:
    void set_AB(int a, int b) {A = a; B = b;}  //设置加密密钥

    int gcd(int a, int b) {
        while(b) {
            int r = a % b;
            a = b;
            b = r;
        }
        return a;
    }

    bool Judge(int a, int b) {  //判断密钥是否合法
        if(gcd(a, 95) == 1) {
            set_AB(a, b);
            return true;
        }
        else {
            cout << "密钥不合法,请重新输入!" << endl;
            return false;
        }
    }

    int get_A() {return A;}  //获取加密密钥
    int get_B() {return B;}

    int encrypt(char ch) {  //对单个字符进行加密
        int plaintext_id = ch - ' ';
        int A = get_A(), B = get_B();
        int ciphertext_id = (A * plaintext_id + B) % 95;
        return ciphertext_id + 32;
    }

private:
    int A, B;  //加密密钥
};

//解密类
class Decrypt {
public:

    int x, y;  //a*x + b*y = gcd(a, b)
    int extend_eulid(int a, int b) {
        if(b == 0) {
            x = 1;
            y = 0;
        }
        else {
            extend_eulid(b, a%b);
            int temp = x;
            x = y;
            y = temp - a / b * y;
        }
    }

    int get_inv(int a) { //求A的乘法逆元
        extend_eulid(a, 95);
        int inv = x;
        if(inv < 0) inv += 95;
        return inv;
    }

    void set_A(int a) {A = get_inv(a);}
    void set_B(int b) {B = b;}

    int get_A() {return A;}  //获取解密密钥
    int get_B() {return B;}

    int decrypt(char ch) {  //对单个字符进行解密
        int ciphertext_id = ch - ' ';
        int A = get_A(), B = get_B();
        int plaintext_id = A * (ciphertext_id - B + 95) % 95;
        return plaintext_id + 32;
    }

private:
    int A, B; //解密密钥
};

int main()
{
    Encrypt en;
    Decrypt de;
    int A, B;
    char ch;

    while(1) {  //输入加密密钥
        cin >> A >> B;
        if(en.Judge(A, B) == true) break;
    }
    de.set_A(A), de.set_B(B);  //设置解密密钥

    ifstream fin("F:text.txt", ios::in);   //以输入方式打开明文文件"text.txt"
    ofstream fout("F:ciphertext.txt", ios::out);  //以输出方式打开保存密文的文件"ciphertext.txt",并将其原有的内容清除
    if(!fin) {
        cout << "Can not open the plaintext file!" << endl;
    }
    while(fin.get(ch) != NULL) {
        int ciphertext_id = en.encrypt(ch);
        char ciphertext_ch = char(ciphertext_id);
        fout << ciphertext_ch;
    }  //从明文文件"F:test.txt"中一次读取一个字符进行加密,将加密后的文件保存为 "ciphertext.txt"
    fout.close();

    ifstream fin1("F:ciphertext.txt", ios::in); //以输入方式打开密文文件"ciphertext.txt"
    ofstream fout1("F:plaintext.txt", ios::out); //以输出方式打开保存解密后的文件"plaintext.txt",并将其原有的内容清除
    if(!fin1) {
        cout << "Can not open the ciphertext file!" << endl;
    }
    while(fin1.get(ch) != NULL) {
        int  plaintext_id = de.decrypt(ch);
        char plaintext_ch = char(plaintext_id);
        fout1 << plaintext_ch;
    } //从密文文件"ciphertext.txt"中一次读取一个字符进行解密,将解密后的文件保存为"plaintext.txt"
    fout1.close();

    return 0;
}