C++ EVP_Cipher AES-256-CBC加密文件后OpenSSL命令行解密失败求助
问题分析:AES-256-CBC加密文件后无法用OpenSSL命令行解密
我用EVP_Cipher API实现了AES-256-CBC加密文件的C++代码,代码自身可以正常解密,但用OpenSSL命令行解密加密后的文件时,一直提示“Bad decrypt”错误。
使用的OpenSSL命令:
openssl enc -aes-256-cbc -d -K ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290 -iv 3fa6d97f4807e145b37451fc344e58ca -in test.enc -out test.out -nosalt
我的C++代码如下:
using namespace std; void encDecFile(const char * input_filepath, bool encrypt) { const unsigned char * key = (const unsigned char * ) "ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290"; const unsigned char * iv = (const unsigned char * ) "3fa6d97f4807e145b37451fc344e58ca"; int intent = encrypt ? 1 : 0; std::string output_filepath = input_filepath; if (encrypt) { const char * ext = ".enc"; output_filepath = output_filepath + std::string(".enc"); } else { auto pos = output_filepath.find_last_of("."); output_filepath = output_filepath.substr(0, pos) + std::string(".out"); } ifstream input_file(input_filepath, std::ios::binary); ofstream output_file(output_filepath.c_str(), std::ios::binary); int out_len = 0; printf("encDecFile - Entry \n"); if (!(input_file.is_open() && output_file.is_open())) { const char * whichFile = input_file.is_open() ? output_filepath.c_str() : input_filepath; printf("encDecFile Failed to open %s \n", whichFile); return; } input_file.seekg(0, std::ios::end); long long file_size = input_file.tellg(); input_file.seekg(0, std::ios::beg); printf("encDecFile - Input file %s is of Size %lld is opened! \n", input_filepath, file_size); EVP_CIPHER_CTX * ctx; ctx = EVP_CIPHER_CTX_new(); EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv, 1); EVP_CIPHER_CTX_set_padding(ctx, 1); unsigned int blocksize = EVP_CIPHER_block_size(EVP_aes_256_cbc()); char * in_buf = new char[2048]; char * out_buf = new char[2048 + blocksize]; int count = 0; while (!input_file.eof()) { input_file.read(in_buf, (1 << 20)); std::streamsize dataSize = input_file.gcount(); printf("encDecFile - Reading %d chunk of data of size %d \n", ++count, (int) dataSize); if (1 == EVP_CipherUpdate(ctx, (unsigned char * ) out_buf, & out_len, (const unsigned char * ) in_buf, (int) dataSize)) { output_file.write(out_buf, out_len); printf("encDecFile - Written %d bytes of encrypted data \n", out_len); } else { printf("Encryption failed after for %d Chunk! \n", count); break; } } if (1 == EVP_CipherFinal_ex(ctx, (unsigned char * ) out_buf, & out_len)) { output_file.write(out_buf, out_len); printf("encDecFile - Written %d bytes of final encrypted data \n", out_len); } else { printf("Encryption failed after to update Final \n"); } input_file.close(); output_file.close(); delete[] out_buf; EVP_CIPHER_CTX_cleanup(ctx); EVP_CIPHER_CTX_free(ctx); printf("encDecFile - Done!! \n"); return; }
核心问题分析
问题出在密钥和IV的格式处理上:
- 代码中直接把十六进制字符串当作字节数组传递给
EVP_CipherInit_ex,但OpenSSL命令行的-K和-iv参数要求的是十六进制对应的原始字节值。 - 比如你写的
"ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290"是64个字符的十六进制字符串,对应32字节的AES-256密钥,但代码中传递的是这个字符串的ASCII字节(每个字符占1字节),相当于用了64字节的错误密钥,而非32字节的正确密钥。 - IV同理,你传递的是32字符的ASCII字符串(32字节),但AES-CBC的IV需要16字节(对应32个十六进制字符的解码值)。
解决步骤
- 编写十六进制字符串转字节数组的函数:将密钥和IV的十六进制字符串解码成原始字节数组,比如把"ae"转换成
0xAE字节。
示例转换函数:bool hexToBytes(const std::string& hexStr, std::vector<unsigned char>& bytes) { if (hexStr.length() % 2 != 0) return false; bytes.reserve(hexStr.length() / 2); for (size_t i = 0; i < hexStr.length(); i += 2) { std::string byteStr = hexStr.substr(i, 2); char byte = (char)strtol(byteStr.c_str(), nullptr, 16); bytes.push_back(byte); } return true; } - 修改代码中的密钥和IV初始化:
std::string keyHex = "ae0479555eca5b5228a0ee00ecef15aab729f47ee881cf8b1d3ff18561a47290"; std::string ivHex = "3fa6d97f4807e145b37451fc344e58ca"; std::vector<unsigned char> keyBytes, ivBytes; if (!hexToBytes(keyHex, keyBytes) || !hexToBytes(ivHex, ivBytes)) { printf("Invalid hex key or IV\n"); return; } - 传递正确的字节数组给EVP API:
EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, keyBytes.data(), ivBytes.data(), 1); - 额外检查点:代码中已设置
EVP_CIPHER_CTX_set_padding(ctx, 1),对应OpenSSL默认的PKCS#7填充,无需修改。
内容的提问来源于stack exchange,提问作者Sourabh Pandit
相关产品推荐
相关产品推荐

