如何利用MySQL和C++开发一个简单的文件加密功能

来源:中国站长站作者:香港程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《如何利用MySQL和C++开发一个简单的文件加密功能》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何利用MySQL和C++开发一个简单的文件加密功能》有用,将其分享出去将是对创作者最好的鼓励。

在本地应用开发中,文件加密是保护敏感数据的常见需求,结合MySQL存储加密元数据、C++实现加密逻辑,可以搭建一套完整的简单文件加密功能,既完成文件内容的加密处理,又能通过数据库管理加密文件的相关信息。

如何利用MySQL和C++开发一个简单的文件加密功能

环境准备

开发前需要准备对应的依赖环境,确保后续代码可以正常运行:

  • 安装MySQL数据库,并且创建好对应的测试库和测试用户,确保C++程序可以正常连接数据库
  • 安装C++开发环境,比如GCC或者Visual Studio,支持C++11及以上标准
  • 安装OpenSSL库,用于实现AES加密逻辑,同时安装MySQL Connector/C++库,用于C++操作MySQL数据库

数据库表设计

我们需要在MySQL中创建一张表,用来存储加密文件的相关元数据,方便后续查询和管理,表结构设计如下:

字段名类型说明
file_idINT PRIMARY KEY AUTO_INCREMENT加密文件唯一ID
file_nameVARCHAR(255)原始文件名称
encrypt_keyVARCHAR(64)加密使用的密钥(实际生产环境建议加密存储)
encrypt_timeDATETIME文件加密时间
file_pathVARCHAR(512)加密后文件的存储路径

创建表的SQL语句如下:

CREATE TABLE `encrypt_file_record` (
  `file_id` int NOT NULL AUTO_INCREMENT,
  `file_name` varchar(255) NOT NULL,
  `encrypt_key` varchar(64) NOT NULL,
  `encrypt_time` datetime NOT NULL,
  `file_path` varchar(512) NOT NULL,
  PRIMARY KEY (`file_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心加密逻辑实现

我们使用AES-256-CBC模式实现文件加密,加密前需要生成对应的密钥和初始化向量,以下是加密和解密的核心函数实现:

#include <openssl/aes.h>
#include <openssl/rand.h>
#include <fstream>
#include <vector>
#include <string>
#include <iostream>

// 生成随机的初始化向量
std::vector<unsigned char> generate_iv() {
    std::vector<unsigned char> iv(AES_BLOCK_SIZE);
    RAND_bytes(iv.data(), AES_BLOCK_SIZE);
    return iv;
}

// AES-256-CBC加密函数,返回加密后的数据和使用的IV
std::pair<std::vector<unsigned char>, std::vector<unsigned char>> aes_encrypt(const std::vector<unsigned char>& plaintext, const std::vector<unsigned char>& key) {
    // 密钥长度需要是32字节(256位)
    if (key.size() != 32) {
        std::cerr << "密钥长度必须为32字节" << std::endl;
        return {};
    }
    std::vector<unsigned char> iv = generate_iv();
    AES_KEY aes_key;
    AES_set_encrypt_key(key.data(), 256, &aes_key);
    
    // 计算填充后的长度
    int plaintext_len = plaintext.size();
    int padded_len = (plaintext_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
    std::vector<unsigned char> ciphertext(padded_len);
    // PKCS7填充
    int padding_len = padded_len - plaintext_len;
    std::vector<unsigned char> padded_plaintext = plaintext;
    padded_plaintext.insert(padded_plaintext.end(), padding_len, padding_len);
    
    AES_cbc_encrypt(padded_plaintext.data(), ciphertext.data(), padded_plaintext.size(), &aes_key, iv.data(), AES_ENCRYPT);
    return {ciphertext, iv};
}

// AES-256-CBC解密函数
std::vector<unsigned char> aes_decrypt(const std::vector<unsigned char>& ciphertext, const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv) {
    if (key.size() != 32) {
        std::cerr << "密钥长度必须为32字节" << std::endl;
        return {};
    }
    AES_KEY aes_key;
    AES_set_decrypt_key(key.data(), 256, &aes_key);
    std::vector<unsigned char> plaintext(ciphertext.size());
    AES_cbc_encrypt(ciphertext.data(), plaintext.data(), ciphertext.size(), &aes_key, (unsigned char*)iv.data(), AES_DECRYPT);
    
    // 去除PKCS7填充
    int padding_len = plaintext.back();
    plaintext.resize(plaintext.size() - padding_len);
    return plaintext;
}

文件加密与数据库存储实现

接下来实现完整的文件加密流程,读取原始文件内容,调用加密函数,将加密后的内容写入新文件,同时将元数据存入MySQL数据库:

#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <ctime>

// 读取文件内容到字节数组
std::vector<unsigned char> read_file(const std::string& file_path) {
    std::ifstream file(file_path, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << "无法打开文件: " << file_path << std::endl;
        return {};
    }
    file.seekg(0, std::ios::end);
    size_t file_size = file.tellg();
    file.seekg(0, std::ios::beg);
    std::vector<unsigned char> buffer(file_size);
    file.read((char*)buffer.data(), file_size);
    return buffer;
}

// 将字节数组写入文件
bool write_file(const std::string& file_path, const std::vector<unsigned char>& data) {
    std::ofstream file(file_path, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << "无法创建文件: " << file_path << std::endl;
        return false;
    }
    file.write((const char*)data.data(), data.size());
    return true;
}

// 字节数组转十六进制字符串,方便存入数据库
std::string bytes_to_hex(const std::vector<unsigned char>& bytes) {
    std::string hex_str;
    for (unsigned char byte : bytes) {
        char buf[3];
        sprintf(buf, "%02x", byte);
        hex_str += buf;
    }
    return hex_str;
}

// 十六进制字符串转字节数组
std::vector<unsigned char> hex_to_bytes(const std::string& hex_str) {
    std::vector<unsigned char> bytes;
    for (size_t i = 0; i < hex_str.size(); i += 2) {
        std::string byte_str = hex_str.substr(i, 2);
        unsigned char byte = (unsigned char)strtol(byte_str.c_str(), nullptr, 16);
        bytes.push_back(byte);
    }
    return bytes;
}

// 执行文件加密并存储记录到MySQL
void encrypt_file_and_save_record(const std::string& original_file, const std::string& encrypted_file, sql::Connection* conn) {
    // 生成32字节的随机密钥
    std::vector<unsigned char> key(32);
    RAND_bytes(key.data(), 32);
    
    // 读取原始文件
    std::vector<unsigned char> file_content = read_file(original_file);
    if (file_content.empty()) {
        return;
    }
    
    // 执行加密
    auto [ciphertext, iv] = aes_encrypt(file_content, key);
    if (ciphertext.empty()) {
        return;
    }
    
    // 将IV和密文一起写入加密文件,方便后续解密
    std::vector<unsigned char> file_to_write;
    file_to_write.insert(file_to_write.end(), iv.begin(), iv.end());
    file_to_write.insert(file_to_write.end(), ciphertext.begin(), ciphertext.end());
    if (!write_file(encrypted_file, file_to_write)) {
        return;
    }
    
    // 将记录存入MySQL
    try {
        sql::PreparedStatement* pstmt = conn->prepareStatement(
            "INSERT INTO encrypt_file_record (file_name, encrypt_key, encrypt_time, file_path) VALUES (?, ?, NOW(), ?)"
        );
        pstmt->setString(1, original_file);
        pstmt->setString(2, bytes_to_hex(key));
        pstmt->setString(3, encrypted_file);
        pstmt->executeUpdate();
        delete pstmt;
        std::cout << "文件加密完成,记录已存入数据库" << std::endl;
    } catch (sql::SQLException& e) {
        std::cerr << "数据库操作失败: " << e.what() << std::endl;
    }
}

完整调用示例

以下是主函数的调用示例,包含数据库连接和加密功能的触发:

int main() {
    // 连接MySQL数据库
    sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();
    sql::Connection* conn = driver->connect("tcp://127.0.0.1:3306", "test_user", "test_password");
    conn->setSchema("test_db");
    
    // 调用加密函数
    encrypt_file_and_save_record("test.txt", "test_encrypted.bin", conn);
    
    // 关闭连接
    delete conn;
    return 0;
}

注意事项

实际生产环境中需要注意以下几点:

  • 本文示例中的密钥直接以明文形式存入数据库,实际使用时需要对密钥进行二次加密存储,避免密钥泄露
  • 加密后的文件将IV放在文件开头,解密时需要先读取前16字节作为IV,再读取后续内容作为密文
  • 文件路径建议使用绝对路径,避免程序运行目录变化导致文件找不到的问题
  • 操作数据库和文件时需要添加更多的异常处理逻辑,确保程序稳定性

MySQLC++文件加密AES_加密数据库存储修改时间:2026-07-15 12:06:46

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。