写一个C++程序以数字信封的形式对明文文件进行加密。不用大数库gmp要求如下: 发送方利用系统自带的伪随机数生成函数生成会话密钥 用接收方的公钥对会话密钥加密 用会话密钥以OFB的模式对明文文件p_text.txt(文件大于1KB)进行加密,结果存于密文文件c_text.txt 接收方利用私钥解密会话密钥,然后用会话密钥对密文文件解密,结果存于明文文件p1_text.txt,最后对比p_text.txt和p1_text.txt
时间: 2024-03-07 18:49:43 浏览: 188
为了完成这个任务,需要先生成RSA密钥对,然后实现OFB模式和RSA加解密算法。以下是一个可能的实现:
```c++
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <vector>
using namespace std;
// 生成RSA密钥对
void generateRSAKeys(int key_len, int &n, int &e, int &d)
{
srand(time(NULL));
int p = rand() % ((int)pow(10, key_len / 2) - 1) + (int)pow(10, key_len / 2 - 1);
int q = rand() % ((int)pow(10, key_len / 2) - 1) + (int)pow(10, key_len / 2 - 1);
n = p * q;
int phi_n = (p - 1) * (q - 1);
e = 65537; // 选择一个较小的e
while (__gcd(e, phi_n) != 1) {
e++;
}
int k = 1;
while ((k * phi_n + 1) % e != 0) {
k++;
}
d = (k * phi_n + 1) / e;
}
// 快速幂取模
int powMod(int a, int b, int n)
{
int res = 1;
while (b > 0) {
if (b & 1) {
res = (long long)res * a % n;
}
a = (long long)a * a % n;
b >>= 1;
}
return res;
}
// RSA加密
void rsaEncrypt(int m, int e, int n, int &c)
{
c = powMod(m, e, n);
}
// RSA解密
void rsaDecrypt(int c, int d, int n, int &m)
{
m = powMod(c, d, n);
}
// OFB加密
void ofbEncrypt(char *plainText, char *cipherText, int len, int key, int iv)
{
int block_size = sizeof(int);
int *block = new int[block_size];
memcpy(block, &iv, block_size);
for (int i = 0; i < len; i += block_size) {
int *iv_p = new int[block_size];
memcpy(iv_p, block, block_size);
rsaEncrypt(*iv_p, key, n, *iv_p); // 用RSA加密iv
memcpy(block, iv_p, block_size);
(*iv_p) ^= *((int *)(plainText + i));
memcpy(cipherText + i, iv_p, block_size);
delete[] iv_p;
}
delete[] block;
}
// OFB解密
void ofbDecrypt(char *cipherText, char *plainText, int len, int key, int iv)
{
int block_size = sizeof(int);
int *block = new int[block_size];
memcpy(block, &iv, block_size);
for (int i = 0; i < len; i += block_size) {
int *iv_p = new int[block_size];
memcpy(iv_p, block, block_size);
rsaEncrypt(*iv_p, key, n, *iv_p); // 用RSA加密iv
memcpy(block, iv_p, block_size);
*((int *)(plainText + i)) = (*iv_p) ^ *((int *)(cipherText + i));
delete[] iv_p;
}
delete[] block;
}
int main()
{
// 生成RSA密钥对
int key_len = 1024;
int n, e, d;
generateRSAKeys(key_len, n, e, d);
// 生成会话密钥
int session_key = rand() % ((int)pow(2, key_len) - 1);
// 加密会话密钥
int encrypted_key;
rsaEncrypt(session_key, e, n, encrypted_key);
// OFB加密
ifstream in("p_text.txt", ios::binary);
ofstream out("c_text.txt", ios::binary);
int iv = rand() % ((int)pow(2, key_len) - 1);
char *plainText = new char[1024];
char *cipherText = new char[1024];
while (!in.eof()) {
in.read(plainText, 1024);
int len = in.gcount();
ofbEncrypt(plainText, cipherText, len, session_key, iv);
out.write(cipherText, len);
}
delete[] plainText;
delete[] cipherText;
in.close();
out.close();
// 解密会话密钥并OFB解密
rsaDecrypt(encrypted_key, d, n, session_key);
in.open("c_text.txt", ios::binary);
out.open("p1_text.txt", ios::binary);
iv = 0;
plainText = new char[1024];
cipherText = new char[1024];
while (!in.eof()) {
in.read(cipherText, 1024);
int len = in.gcount();
ofbDecrypt(cipherText, plainText, len, session_key, iv);
out.write(plainText, len);
}
delete[] plainText;
delete[] cipherText;
in.close();
out.close();
// 对比p_text.txt和p1_text.txt
in.open("p_text.txt", ios::binary);
ifstream in1("p1_text.txt", ios::binary);
char ch, ch1;
while (!in.eof() && !in1.eof()) {
in.get(ch);
in1.get(ch1);
if (ch != ch1) {
cout << "Decryption error!" << endl;
break;
}
}
if (in.eof() != in1.eof()) {
cout << "Decryption error!" << endl;
}
return 0;
}
```
需要注意的是,为了方便处理,我们把明文分成固定大小的块进行加密。如果文件大小不是块的整数倍,需要在最后一块中添加填充数据,以保证块的大小一致。另外,由于OFB模式中,每个块的加密只依赖于上一个块的加密结果,因此需要在处理第一个块之前,先生成一个初始化向量(IV)。IV可以随机生成,也可以通过一定的方式从会话密钥中生成。
阅读全文