如何用C++(OpenSSL)解密Python RSA加密的消息?
RSA加密解密跨语言问题:Python加密,C++ OpenSSL解密报填充错误
问题背景
我用Python实现了RSA加密,代码如下:
import base64 from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 key = """-----BEGIN RSA PRIVATE KEY----- SOME_SECURE_KEY -----END RSA PRIVATE KEY-----""" private_key = RSA.import_key(key) cipher = PKCS1_v1_5.new(private_key) print(base64.b64encode(cipher.encrypt(b"SECRET MESSAGE")).decode())
尝试用C结合OpenSSL解密时,提示incorrect padding(填充错误),C代码如下:
int main() { std::string privateKey = "MY-KEY"; BIO *bio = BIO_new_mem_buf(privateKey.c_str(), privateKey.length()); // -1: assume string is null terminated RSA *rsa = PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr); BIO_free(bio); auto vec = a_function_that_decodes_base64(my_cipher_text); unsigned char arr[vec.size()]; std::copy(vec.begin(), vec.end(), arr); unsigned char decrypted[4098] = {}; int decrypt_len = RSA_private_decrypt(RSA_size(rsa), arr, decrypted, rsa, RSA_PKCS1_PADDING); if (decrypt_len == -1) { char *err = ERR_error_string(ERR_get_error(), NULL); std::cout << err << std::endl; } RSA_free(rsa); }
怀疑自定义Base64解码函数存在问题,附上代码:
typedef unsigned char BYTE; std::vector<BYTE> bbase64_decode(std::string const& encoded_string) { int in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; BYTE char_array_4[4], char_array_3[3]; std::vector<BYTE> ret; while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { char_array_4[i++] = encoded_string[in_]; in_++; if (i ==4) { for (i = 0; i <4; i++) char_array_4[i] = base64Mapping.find(char_array_4[i]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; (i < 3); i++) ret.push_back(char_array_3[i]); i = 0; } } if (i) { for (j = i; j <4; j++) char_array_4[j] = 0; for (j = 0; j <4; j++) char_array_4[j] = base64Mapping.find(char_array_4[j]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]); } return ret; }
解决方案
核心问题大概率出在自定义Base64解码函数上,手动实现的Base64容易出现编码映射、填充处理错误,直接改用OpenSSL原生接口即可解决。同时修正解密流程中的其他细节:
1. 替换自定义Base64解码为OpenSSL实现
用OpenSSL的EVP_DecodeBlock处理Base64解码,避免手动实现的错误:
#include <openssl/evp.h> #include <vector> #include <string> std::vector<unsigned char> base64_decode(const std::string& encoded) { int decoded_len = EVP_DecodedLength(encoded.size()); std::vector<unsigned char> decoded(decoded_len); int len; EVP_DecodeBlock(decoded.data(), reinterpret_cast<const unsigned char*>(encoded.c_str()), encoded.size()); // 清理末尾无效的填充0 len = decoded_len; while (len > 0 && decoded[len-1] == 0) { len--; } decoded.resize(len); return decoded; }
2. 修正后的完整C++解密代码
#include <iostream> #include <string> #include <vector> #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/evp.h> #include <openssl/err.h> std::vector<unsigned char> base64_decode(const std::string& encoded) { int decoded_len = EVP_DecodedLength(encoded.size()); std::vector<unsigned char> decoded(decoded_len); int len; EVP_DecodeBlock(decoded.data(), reinterpret_cast<const unsigned char*>(encoded.c_str()), encoded.size()); // 清理末尾无效的填充0 len = decoded_len; while (len > 0 && decoded[len-1] == 0) { len--; } decoded.resize(len); return decoded; } int main() { // 替换为完整的PEM格式私钥 std::string privateKey = R"(-----BEGIN RSA PRIVATE KEY----- SOME_SECURE_KEY -----END RSA PRIVATE KEY-----)"; BIO* bio = BIO_new_mem_buf(privateKey.c_str(), privateKey.length()); if (!bio) { std::cerr << "Failed to create BIO" << std::endl; return 1; } RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr); BIO_free(bio); if (!rsa) { char err_buf[256]; ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)); std::cerr << "Failed to load private key: " << err_buf << std::endl; return 1; } // 替换为实际的Base64加密字符串 std::string my_cipher_text = "YOUR_BASE64_ENCODED_CIPHERTEXT"; auto vec = base64_decode(my_cipher_text); std::vector<unsigned char> decrypted(RSA_size(rsa)); int decrypt_len = RSA_private_decrypt( vec.size(), vec.data(), decrypted.data(), rsa, RSA_PKCS1_PADDING ); if (decrypt_len == -1) { char err_buf[256]; ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)); std::cerr << "Decryption failed: " << err_buf << std::endl; RSA_free(rsa); return 1; } // 输出解密后的明文 std::cout << "Decrypted message: " << std::string(decrypted.begin(), decrypted.begin() + decrypt_len) << std::endl; RSA_free(rsa); return 0; }
3. 关键检查点
- 确保私钥格式完整:必须包含
-----BEGIN RSA PRIVATE KEY-----和-----END RSA PRIVATE KEY-----,不能仅写密钥内容。 - 避免非标准变长数组:不要用
unsigned char arr[vec.size()],直接用vec.data()传递数据。 - 密钥一致性:Python加密和C++解密必须使用同一套RSA密钥。
- 填充方式匹配:两边都使用PKCS1_v1.5填充,代码中已保持一致。
内容的提问来源于stack exchange,提问作者Alo M4hdi
相关产品推荐
相关产品推荐

