You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:10:27