在Linux下使用C++实现文件加密,可以采用多种方法。以下介绍两种常用的方法:
OpenSSL是一个强大的加密库,支持多种加密算法和协议。通过C++调用OpenSSL库,可以方便地实现文件的加密和解密。
安装OpenSSL开发库
在大多数Linux发行版中,可以使用包管理器安装OpenSSL的开发库。例如,在Ubuntu上:
sudo apt-get update
sudo apt-get install libssl-dev
编写C++代码
下面是一个使用OpenSSL的AES-256-CBC算法对文件进行加密和解密的示例代码:
#include <iostream>
#include <fstream>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <cstring>
// 加密函数
bool encryptFile(const std::string& inputFile, const std::string& outputFile, const std::string& password) {
// 读取输入文件
std::ifstream inFile(inputFile, std::ios::binary);
if (!inFile) {
std::cerr << "无法打开输入文件。" << std::endl;
return false;
}
// 写入输出文件
std::ofstream outFile(outputFile, std::ios::binary);
if (!outFile) {
std::cerr << "无法打开输出文件。" << std::endl;
return false;
}
// 生成随机的盐
unsigned char salt[8];
if (!RAND_bytes(salt, sizeof(salt))) {
std::cerr << "生成盐失败。" << std::endl;
return false;
}
outFile.write(reinterpret_cast<const char*>(salt), sizeof(salt));
// 使用PBKDF2从密码派生密钥
AES_KEY enc_key;
unsigned char key[32]; // AES-256
if (!PKCS5_PBKDF2_HMAC(password.c_str(), password.size(),
salt, sizeof(salt),
10000, AES_KEYLEN_256, EVP_sha256(), sizeof(key), key)) {
std::cerr << "密钥派生失败。" << std::endl;
return false;
}
// 初始化加密上下文
if (!AES_set_encrypt_key(key, 256, &enc_key)) {
std::cerr << "设置加密密钥失败。" << std::endl;
return false;
}
// 写入IV(初始化向量)
unsigned char iv[AES_BLOCK_SIZE];
if (!RAND_bytes(iv, sizeof(iv))) {
std::cerr << "生成IV失败。" << std::endl;
return false;
}
outFile.write(reinterpret_cast<const char*>(iv), sizeof(iv));
// 加密数据
char inbuf[AES_BLOCK_SIZE];
char outbuf[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
while (inFile.good()) {
inFile.read(inbuf, sizeof(inbuf));
size_t bytesRead = inFile.gcount();
if (bytesRead > 0) {
AES_cbc_encrypt(inbuf, outbuf, bytesRead, &enc_key, iv, AES_ENCRYPT);
outFile.write(outbuf, sizeof(outbuf));
}
}
inFile.close();
outFile.close();
return true;
}
// 解密函数
bool decryptFile(const std::string& inputFile, const std::string& outputFile, const std::string& password) {
// 打开输入文件
std::ifstream inFile(inputFile, std::ios::binary);
if (!inFile) {
std::cerr << "无法打开输入文件。" << std::endl;
return false;
}
// 打开输出文件
std::ofstream outFile(outputFile, std::ios::binary);
if (!outFile) {
std::cerr << "无法打开输出文件。" << std::endl;
return false;
}
// 读取盐
unsigned char salt[8];
inFile.read(reinterpret_cast<char*>(salt), sizeof(salt));
if (!inFile) {
std::cerr << "读取盐失败。" << std::endl;
return false;
}
// 读取IV
unsigned char iv[AES_BLOCK_SIZE];
inFile.read(reinterpret_cast<char*>(iv), sizeof(iv));
if (!inFile) {
std::cerr << "读取IV失败。" << std::endl;
return false;
}
// 使用PBKDF2从密码派生密钥
AES_KEY dec_key;
unsigned char key[32]; // AES-256
if (!PKCS5_PBKDF2_HMAC(password.c_str(), password.size(),
salt, sizeof(salt),
10000, AES_KEYLEN_256, EVP_sha256(), sizeof(key), key)) {
std::cerr << "密钥派生失败。" << std::endl;
return false;
}
// 初始化解密上下文
if (!AES_set_decrypt_key(key, 256, &dec_key)) {
std::cerr << "设置解密密钥失败。" << std::endl;
return false;
}
// 解密数据
char inbuf[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
char outbuf[AES_BLOCK_SIZE];
while (inFile.good()) {
inFile.read(inbuf, sizeof(inbuf));
size_t bytesRead = inFile.gcount();
if (bytesRead > 0) {
AES_cbc_encrypt(inbuf, outbuf, bytesRead, &dec_key, iv, AES_DECRYPT);
outFile.write(outbuf, bytesRead);
}
}
inFile.close();
outFile.close();
return true;
}
int main(int argc, char* argv[]) {
if (argc != 4) {
std::cerr << "用法: " << argv[0] << " encrypt|decrypt 输入文件 输出文件 密码" << std::endl;
return 1;
}
std::string mode = argv[1];
std::string inputFile = argv[2];
std::string outputFile = argv[3];
std::string password = argv[4];
if (mode == "encrypt") {
if (encryptFile(inputFile, outputFile, password)) {
std::cout << "加密成功。" << std::endl;
} else {
std::cerr << "加密失败。" << std::endl;
}
}
else if (mode == "decrypt") {
if (decryptFile(inputFile, outputFile, password)) {
std::cout << "解密成功。" << std::endl;
} else {
std::cerr << "解密失败。" << std::endl;
}
}
else {
std::cerr << "未知模式。使用encrypt或decrypt。" << std::endl;
return 1;
}
return 0;
}
编译代码
使用g++编译时,需要链接OpenSSL的加密库:
g++ -o file_encrypt file_encrypt.cpp -lcrypto
使用示例
# 加密文件
./file_encrypt encrypt plaintext.txt encrypted.bin mypassword
# 解密文件
./file_encrypt decrypt encrypted.bin decrypted.txt mypassword
如果您的CPU支持AES-NI指令集,可以利用硬件加速来提高加密和解密的性能。下面介绍如何使用C++和Intel的Intel Intrinsics
来实现AES加密。
安装必要的开发工具
确保已安装GCC和相关的开发工具。大多数Linux发行版默认已安装。
编写C++代码
下面是一个使用AES-NI指令集进行AES-256-CBC加密和解密的示例代码:
#include <iostream>
#include <fstream>
#include <cstring>
#include <emmintrin.h> // 包含AES-NI指令集头文件
// 加密函数
bool aesni_encrypt_file(const std::string& inputFile, const std::string& outputFile, const unsigned char* key, const unsigned char* iv) {
// 打开输入文件
std::ifstream inFile(inputFile, std::ios::binary);
if (!inFile) {
std::cerr << "无法打开输入文件。" << std::endl;
return false;
}
// 打开输出文件
std::ofstream outFile(outputFile, std::ios::binary);
if (!outFile) {
std::cerr << "无法打开输出文件。" << std::endl;
return false;
}
// 写入IV
outFile.write(reinterpret_cast<const char*>(iv), AES_BLOCK_SIZE);
// 加密缓冲区
const int bufferSize = 4096; // 4KB缓冲区
unsigned char inbuf[bufferSize];
unsigned char outbuf[bufferSize + AES_BLOCK_SIZE];
while (inFile.good()) {
inFile.read(reinterpret_cast<char*>(inbuf), sizeof(inbuf));
size_t bytesRead = inFile.gcount();
if (bytesRead > 0) {
// AES-NI加密
for (size_t i = 0; i < bytesRead; i += AES_BLOCK_SIZE) {
__m128i aes_key = _mm_loadu_si128(reinterpret_cast<const __m128i*>(key));
__m128i aes_iv = _mm_loadu_si128(reinterpret_cast<const __m128i*>(iv));
__m128i in = _mm_loadu_si128(reinterpret_cast<const __m128i*>(inbuf + i));
__m128i out = _mm_aesenc_si128(in, aes_key);
out = _mm_aesenc_si128(out, aes_key);
out = _mm_aesenc_si128(out, aes_key);
out = _mm_aesenclast_si128(out, aes_key);
_mm_storeu_si128(reinterpret_cast<__m128i*>(outbuf + i), out);
}
outFile.write(reinterpret_cast<const char*>(outbuf), sizeof(outbuf));
}
}
inFile.close();
outFile.close();
return true;
}
// 解密函数
bool aesni_decrypt_file(const std::string& inputFile, const std::string& outputFile, const unsigned char* key, const unsigned char* iv) {
// 打开输入文件
std::ifstream inFile(inputFile, std::ios::binary);
if (!inFile) {
std::cerr << "无法打开输入文件。" << std::endl;
return false;
}
// 打开输出文件
std::ofstream outFile(outputFile, std::ios::binary);
if (!outFile) {
std::cerr << "无法打开输出文件。" << std::endl;
return false;
}
// 读取IV
unsigned char read_iv[AES_BLOCK_SIZE];
inFile.read(reinterpret_cast<char*>(read_iv), sizeof(read_iv));
if (!inFile) {
std::cerr << "读取IV失败。" << std::endl;
return false;
}
// 检查IV是否匹配
if (memcmp(read_iv, iv, AES_BLOCK_SIZE) != 0) {
std::cerr << "IV不匹配。" << std::endl;
return false;
}
// 解密缓冲区
const int bufferSize = 4096; // 4KB缓冲区
unsigned char inbuf[bufferSize + AES_BLOCK_SIZE];
unsigned char outbuf[bufferSize];
while (inFile.good()) {
inFile.read(reinterpret_cast<char*>(inbuf), sizeof(inbuf));
size_t bytesRead = inFile.gcount();
if (bytesRead > 0) {
// AES-NI解密
for (size_t i = 0; i < bytesRead; i += AES_BLOCK_SIZE) {
__m128i aes_key = _mm_loadu_si128(reinterpret_cast<const __m128i*>(key));
__m128i in = _mm_loadu_si128(reinterpret_cast<const __m128i*>(inbuf + i));
__m128i out = _mm_aesdec_si128(in, aes_key);
out = _mm_aesdec_si128(out, aes_key);
out = _mm_aesdec_si128(out, aes_key);
out = _mm_aesdeclast_si128(out, aes_key);
_mm_storeu_si128(reinterpret_cast<__m128i*>(outbuf + i), out);
}
outFile.write(reinterpret_cast<const char*>(outbuf), sizeof(outbuf));
}
}
inFile.close();
outFile.close();
return true;
}
int main(int argc, char* argv[]) {
if (argc != 5) {
std::cerr << "用法: " << argv[0] << " encrypt|decrypt 输入文件 输出文件 密钥 密码" << std::endl;
return 1;
}
std::string mode = argv[1];
std::string inputFile = argv[2];
std::string outputFile = argv[3];
std::string password = argv[4];
// 密钥派生(简单示例,使用PBKDF2需要额外实现)
// 这里假设已经有一个256位的密钥
unsigned char key[32] = { /* 256位密钥 */ };
unsigned char iv[AES_BLOCK_SIZE] = { /* 128位IV */ };
if (mode == "encrypt") {
if (aesni_encrypt_file(inputFile, outputFile, key, iv)) {
std::cout << "加密成功。" << std::endl;
} else {
std::cerr << "加密失败。" << std::endl;
}
}
else if (mode == "decrypt") {
if (aesni_decrypt_file(inputFile, outputFile, key, iv)) {
std::cout << "解密成功。" << std::endl;
} else {
std::cerr << "解密失败。" << std::endl;
}
}
else {
std::cerr << "未知模式。使用encrypt或decrypt。" << std::endl;
return 1;
}
return 0;
}
注意:
编译代码
使用g++编译时,可以启用AES-NI指令集优化:
g++ -o aesni_encrypt aesni_encrypt.cpp -mavx2
-mavx2
选项启用了AVX2指令集,包括AES-NI。如果您的CPU支持AES-NI但不支持AVX2,可以省略该选项或使用其他相关选项。
使用示例
# 加密文件
./aesni_encrypt encrypt plaintext.txt encrypted.bin
# 解密文件
./aesni_encrypt decrypt encrypted.bin decrypted.txt
以上介绍了两种在Linux下使用C++实现文件加密的方法:
根据具体需求选择合适的方法,并注意密钥管理和数据安全。