如何在内存中解密文件?CryptoPP内存解密失败问题
内存中AES-CTR解密失败问题
背景代码
文件加密实现
#include <cryptopp/files.h> #include <cryptopp/modes.h> #include <cryptopp/osrng.h> #include <cryptopp/base64.h> #include <cryptopp/hex.h> #include <Windows.h> #include <iostream> #include <fstream> void FileEncrypt(byte key[], byte iv[] , const std::string& file, const std::string& dest) { CTR_Mode< AES >::Encryption cipher; cipher.SetKeyWithIV(key, strlen((char*)key), iv, strlen((char*)iv)); std::ifstream in{file, std::ios::binary}; std::ofstream out{dest, std::ios::binary}; CryptoPP::FileSource{in, true, new CryptoPP::StreamTransformationFilter{ cipher, new CryptoPP::FileSink{out}}}; } INT main(INT argc, PCHAR* argv) { std::string file = "..."; std::string dest = "..."; unsigned char* key[] = "p3s6v9y$B&E)H@Mc"; unsigned char* iv[] = "VkXp2s5v8y/B?E(H"; FileEncrypt(key, iv, file, dest); FileDecrypt(key, iv, file, dest); }
磁盘文件解密实现
void FileDecrypt(byte key[], byte iv[] , const std::string& file, const std::string& dest) { CTR_Mode< AES >::Decryption cipher; cipher.SetKeyWithIV(key, strlen((char*)key), iv, strlen((char*)iv)); std::ifstream in{file, std::ios::binary}; std::ofstream out{dest, std::ios::binary}; CryptoPP::FileSource{in, true, new StreamTransformationFilter{ cipher, new CryptoPP::FileSink{out}}}; }
问题描述
上述磁盘解密会将结果写入磁盘,现在需要在内存中直接解密已下载到内存的加密文件。尝试了以下代码,但dec变量未得到正确解密结果:
std::string data; FileDownload(data, "https://github.com/...")); //... std::string dec; try { CTR_Mode< AES >::Decryption d; d.SetKeyWithIV(key, strlen((char*)key), iv, strlen((char*)iv)); StringSource s(data, true, new StreamTransformationFilter(d, new StringSink(dec))); } catch (const CryptoPP::Exception& e) { std::cerr << e.what() << std::endl; }
解决方案及问题分析
密钥/IV的类型与长度问题
原代码中unsigned char* key[] = "p3s6v9y$B&E)H@Mc";是错误写法,这里声明的是指针数组而非单个指针,正确写法应为const unsigned char* key = (const unsigned char*)"p3s6v9y$B&E)H@Mc";。另外要明确:AES密钥长度必须是128/192/256位(对应16/24/32字节),你的密钥正好是16字节(128位),符合要求;CTR模式下IV通常和AES块大小一致(16字节),你的IV长度也合规,但必须保证加密、解密使用完全相同的密钥和IV。
下载数据的完整性问题
确保FileDownload函数以二进制模式下载数据。如果默认用文本模式,会自动转换部分二进制字节(如0x0A、0x0D),导致加密数据损坏,解密必然失败。修正后的内存解密代码
#include <cryptopp/modes.h> #include <cryptopp/filters.h> #include <cryptopp/strings.h> #include <string> #include <iostream> // 正确定义密钥和IV const unsigned char* key = (const unsigned char*)"p3s6v9y$B&E)H@Mc"; const unsigned char* iv = (const unsigned char*)"VkXp2s5v8y/B?E(H"; int main() { std::string encrypted_data; // 确保FileDownload以二进制方式获取数据 FileDownload(encrypted_data, "https://github.com/..."); std::string decrypted_data; try { CryptoPP::CTR_Mode<CryptoPP::AES>::Decryption decryptor; // 明确指定密钥和IV长度,避免strlen处理二进制数据出错 decryptor.SetKeyWithIV(key, 16, iv, 16); CryptoPP::StringSource( encrypted_data, true, new CryptoPP::StreamTransformationFilter( decryptor, new CryptoPP::StringSink(decrypted_data) ) ); // 验证解密结果,比如输出数据长度或对比本地解密内容 std::cout << "Decryption successful, data length: " << decrypted_data.size() << std::endl; } catch (const CryptoPP::Exception& e) { std::cerr << "Decryption error: " << e.what() << std::endl; } return 0; }额外验证步骤
- 将加密文件本地解密,把本地解密后的二进制内容和内存解密得到的
decrypted_data做字节对比,确认一致性; - 如果下载的数据是Base64编码的加密内容,需要添加
Base64Decoder过滤器处理:CryptoPP::StringSource( encrypted_data, true, new CryptoPP::Base64Decoder( new CryptoPP::StreamTransformationFilter( decryptor, new CryptoPP::StringSink(decrypted_data) ) ) );
- 将加密文件本地解密,把本地解密后的二进制内容和内存解密得到的
内容的提问来源于stack exchange,提问作者Cesar
相关产品推荐
相关产品推荐

