使用C++的OpenSSL 库实现 AES 加密和解密文件

如果C++不知道做什么项目,可以编写一个文件加密和解密工具,支持诸如 AES 和 RSA 等常见的加密算法。这样的项目可以帮助学习和理解现代加密技术,并为日常文件保护提供便利。以下是一个基本的设计思路和实现步骤:

1. 设计思路

a. 功能需求
  1. 文件加密:支持对文件进行加密。
  2. 文件解密:支持对加密文件进行解密。
  3. 加密算法选择:支持选择不同的加密算法,如 AES、RSA 等。
  4. 密钥管理:生成和管理加密密钥。
  5. 文件操作:能够读取和写入文件。
b. 技术选型
  1. 加密库:使用 OpenSSL 或 Crypto++ 等成熟的加密库来实现加密和解密功能。
  2. 文件 I/O:使用 C++ 标准库中的文件操作功能来读取和写入文件。
  3. 命令行界面:使用简单的命令行界面(CLI)来接收用户输入和显示结果。

2. 实现步骤

a. 环境准备
  • 安装 OpenSSL 或 Crypto++ 库。
  • 创建一个新的 C++ 项目。
b. 使用 OpenSSL 实现 AES 加密和解密

OpenSSL 提供了丰富的加密功能,以下是如何实现 AES 加密和解密的示例。

#include <openssl/evp.h>
#include <openssl/rand.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <iostream>
#include <string>
// 以上是下面加密算法和解密算法要用到的头文件
参数:
  • const std::string& file:要加密的文件的路径。
  • const std::string& algorithm:使用的加密算法(目前仅支持 "aes")。

生成 AES-256 加密所需的 32 字节密钥(key)和 16 字节初始化向量(IV),使用 RAND_bytes 函数生成随机字节。同时将生成的密钥和 IV 写入一个名为 file.key 的文件中,以便解密时使用。

void encrypt_file(const std::string& file, const std::string& algorithm) {
    // 也就是说当前仅支持AES加密算法
    if (algorithm != "aes") {
        std::cerr << "不支持该加密算法: " << algorithm << std::endl;
        return;
    }

    const unsigned int key_len = 32; // AES-256 key length
    const unsigned int iv_len = 16;  // IV length
    unsigned char key[key_len], iv[iv_len];

    // 生成密钥和 IV
    RAND_bytes(key, key_len);
    RAND_bytes(iv, iv_len);

    // 保存密钥和 IV
    std::ofstream key_file(file + ".key", std::ios::binary);
    key_file.write((char*)key, key_len);
    key_file.write((char*)iv, iv_len);
    key_file.close();

    // 打开输入文件
    std::ifstream infile(file, std::ios::binary);
    if (!infile) {
        std::cerr << "无法打开文件: " << file << std::endl;
        return;
    }

    // 打开输出文件
    std::ofstream outfile(file + ".enc", std::ios::binary);
    if (!outfile) {
        std::cerr << "无法新建输出文件." << std::endl;
        return;
    }

    // 初始化加密上下文
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);

    // 加密文件
    unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
    int inlen, outlen;
    while (infile.good()) {
        infile.read((char*)inbuf, sizeof(inbuf));
        inlen = infile.gcount();
        if (inlen > 0) {
            EVP_EncryptUpdate(ctx, outbuf, &outlen, inbuf, inlen);
            outfile.write((char*)outbuf, outlen);
        }
    }

    // 结束加密
    EVP_EncryptFinal_ex(ctx, outbuf, &outlen);
    outfile.write((char*)outbuf, outlen);

    // 清理
    EVP_CIPHER_CTX_free(ctx);
    infile.close();
    outfile.close();

    std::cout << "文件加密成功: " << file + ".enc" << std::endl;
}


void decrypt_file(const std::string& file, const std::string& algorithm) {
    if (algorithm != "aes") {
        std::cerr << "不支持该算法: " << algorithm << std::endl;
        return;
    }

    const unsigned int key_len = 32; // AES-256 key length
    const unsigned int iv_len = 16;  // IV length
    unsigned char key[key_len], iv[iv_len];

    // 读取密钥和 IV
    std::ifstream key_file(file + ".key", std::ios::binary);
    if (!key_file) {
        std::cerr << "无法打开密钥文件." << std::endl;
        return;
    }
    key_file.read((char*)key, key_len);
    key_file.read((char*)iv, iv_len);
    key_file.close();

    // 打开输入文件
    std::ifstream infile(file, std::ios::binary);
    if (!infile) {
        std::cerr << "无法打开输入文件: " << file << std::endl;
        return;
    }

    // 打开输出文件
    std::ofstream outfile(file + ".dec", std::ios::binary);
    if (!outfile) {
        std::cerr << "无法创建输出文件." << std::endl;
        return;
    }

    // 初始化解密上下文
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);

    // 解密文件
    unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
    int inlen, outlen;
    while (infile.good()) {
        infile.read((char*)inbuf, sizeof(inbuf));
        inlen = infile.gcount();
        if (inlen > 0) {
            EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen);
            outfile.write((char*)outbuf, outlen);
        }
    }

    // 结束解密
    EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
    outfile.write((char*)outbuf, outlen);

    // 清理
    EVP_CIPHER_CTX_free(ctx);
    infile.close();
    outfile.close();

    std::cout << "文件解密成功: " << file + ".dec" << std::endl;
}
c. 命令行界面设计

设计一个简单的命令行界面,接收用户的输入并执行相应的操作。

void show_help() {
    std::cout << "用法: encryptor [options]" << std::endl;
    std::cout << "参数选项:" << std::endl;
    std::cout << "  -e <file> <algorithm>  加密文件" << std::endl;
    std::cout << "  -d <file> <algorithm>  解密文件" << std::endl;
    std::cout << "  -h                     帮助信息" << std::endl;
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        show_help();
        return 1;
    }

    std::string option = argv[1];
    if (option == "-h") {
        show_help();
    } else if (option == "-e" && argc == 4) {
        std::string file = argv[2];
        std::string algorithm = argv[3];
        // 调用加密函数
        encrypt_file(file, algorithm);
    } else if (option == "-d" && argc == 4) {
        std::string file = argv[2];
        std::string algorithm = argv[3];
        // 调用解密函数
        decrypt_file(file, algorithm);
    } else {
        std::cerr << "无效参数" << std::endl;
        show_help();
        return 1;
    }

    return 0;
}

3. 运行和测试

编译并运行你的程序,确保能够正确加密和解密文件。可以通过以下命令进行测试:encryptor是你生成的可执行文件名称

# 加密文件
./encryptor -e input.txt aes

# 解密文件
./encryptor -d input.txt.enc aes

4. 扩展功能

你可以进一步扩展这个工具的功能,例如:

  • 支持多种加密算法:如 RSA、DES 等。
  • 用户输入密钥:允许用户输入或选择密钥。
  • 图形用户界面:使用 Qt 或 wxWidgets 等库来创建一个图形界面。

总结

通过这个项目,你不仅可以学习到如何使用 OpenSSL 或 Crypto++ 等加密库,还能深入理解现代加密技术的工作原理,希望这个设计思路和实现步骤能对你有帮助。

相关推荐
林的快手4 分钟前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
FeboReigns5 分钟前
C++简明教程(4)(Hello World)
c语言·c++
FeboReigns6 分钟前
C++简明教程(10)(初识类)
c语言·开发语言·c++
学前端的小朱7 分钟前
处理字体图标、js、html及其他资源
开发语言·javascript·webpack·html·打包工具
千天夜13 分钟前
多源多点路径规划:基于启发式动态生成树算法的实现
算法·机器学习·动态规划
zh路西法16 分钟前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
从以前19 分钟前
准备考试:解决大学入学考试问题
数据结构·python·算法
.Vcoistnt42 分钟前
Codeforces Round 994 (Div. 2)(A-D)
数据结构·c++·算法·贪心算法·动态规划
小k_不小1 小时前
C++面试八股文:指针与引用的区别
c++·面试
摇光931 小时前
js高阶-async与事件循环
开发语言·javascript·事件循环·宏任务·微任务