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

时间:2022-06-10 05:42:22

本文利用仿射密码,对一个只含可打印字符的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;
}