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

OpenSSL 3.0.8中EVP_PKEY_decrypt私钥解密失败求助

OpenSSL 3.0.8中EVP_PKEY_decrypt私钥解密失败求助

我自己捣鼓了好半天都没找到解决办法,来这儿求助各位大佬!我正在用OpenSSL 3库写一个简单的加密聊天客户端-服务端程序,客户端和服务端的Socket模块都继承自abstract_secure_socket纯虚类,里面封装了RSA密钥对的生成逻辑——用公钥加密消息,私钥解密。

目前的实现步骤

  1. 首次启动生成密钥文件
    我定义了RSA密钥长度的宏,然后通过EVP_RSA_gen()生成密钥对,再写入PEM格式的文件中。这部分代码如下:
#define _RSA_KEY_LEN 2136 // 267长度的加密消息 (256有效符号(0-255) + 11填充)
typedef unsigned char uchar;

bool abstract_secure_socket::generateKeys() {
    int bytes = 0;
    std::string __err = _ERR "abstract_secSoc_generateKeys()" ;
    EVP_PKEY* temp_RSAkeypair = EVP_RSA_gen(_RSA_KEY_LEN);
    if(nullptr == temp_RSAkeypair){
        std::cerr << __err + "RSA keypair gen error" << std::endl;
        return false;
    }
    FILE*fp = nullptr;
    bool __res = false;
    do{
        // 写入公钥
        fp = fopen(encr_pub_key_path_.c_str(),"wt");
        if(nullptr == fp){
            std::cerr << __err + "pub key file write error" << std::endl;
            break;
        }
        bytes = PEM_write_PUBKEY(fp,temp_RSAkeypair);
        fclose(fp);
        std::cout << "PEM_write_PUBKEY() result::" << bytes << std::endl;
        if(!bytes){
            std::cerr << __err + "PEM_write public" << std::endl;
            break;
        }
        // 写入私钥
        fp = fopen(encr_priv_key_path_.c_str(),"wt");
        if(nullptr == fp){
            std::cerr << __err + "priv key file write error" << std::endl;
            break;
        }
        bytes = PEM_write_PrivateKey(fp,temp_RSAkeypair,NULL,NULL,0,NULL,NULL);
        fclose(fp);
        std::cout << "PEM_write_PrivateKey() result::" << bytes << std::endl;
        if(!bytes){
            std::cerr << __err + "PEM_write private" << std::endl;
            break;
        }
        __res = true;
    }while(false);
    EVP_PKEY_free(temp_RSAkeypair);
    return __res;
}
  1. 从文件加载密钥到内存
    生成密钥文件后,我会把密钥读取到字符串,再通过BIO结构加载为OpenSSL的EVP_PKEY对象,这部分的代码:
bool abstract_secure_socket::initInternalKeys() {
    std::string __err = _ERR "initInternalKeys()";
    if ( !fs::exists( encr_priv_key_path_) || !fs::exists(encr_pub_key_path_) ) {
        std::cout << "Missing server key/s file/s!! Let's gen new keypairs.." << std::endl;
        if(!generateKeys()){
            std::cerr << __err + "->generateKeys()" << std::endl;
            return false;
        }
        std::cout << _SUC "New keys ready.";
    }
    BIO* __temp_bio = BIO_new(BIO_s_mem());
    if(nullptr == __temp_bio){
        std::cerr << __err << std::endl;
        return false;
    }
    bool __res = false;
    do{
        // 加载私钥
        std::string __temp_key_str = CFileRead(encr_priv_key_path_);
        if(trim_copy(__temp_key_str).empty()){
            std::cerr << __err + "->CFileRead() private key file is empty." << std::endl;
        }
        if(!str2privKey(__temp_key_str, &encr_priv_key_, __temp_bio)){
            std::cerr << _D "abstract_secSoc:: str2privKey FAILED" << std::endl;
            break;
        }
        // 加载公钥
        encr_pub_key_str_ = CFileRead(encr_pub_key_path_);
        if(trim_copy(encr_pub_key_str_).empty()){
            std::cerr << __err + "->CFileRead() public key file is empty." << std::endl;
        }
        if(!str2pubKey(encr_pub_key_str_,&encr_pub_key_, __temp_bio)){
            std::cerr << _D "abstract_secSoc:: str2pubKey FAILED" << std::endl;
            break;
        }
        __res = true;
    }while(false);
    BIO_free(__temp_bio);
    return __res;
}

bool abstract_secure_socket::str2privKey(std::string const& privCipher__, EVP_PKEY**privKeyPtr, BIO* SSL_mem_bio__) {
    std::string __err = _ERR "str2privKey()";
    bool __res = false;
    if(nullptr == SSL_mem_bio__){
        std::cerr << __err << std::endl;
        return false;
    }
    do{
        int __bio_data_written = BIO_write(SSL_mem_bio__, privCipher__.c_str(), privCipher__.length());
        if(__bio_data_written <= 0){
            std::cout << __err + "bio_write" << std::endl;
            break;
        }
        std::cout << "str2privKey bytes::" << __bio_data_written << std::endl;
        EVP_PKEY* __temp_ptr = nullptr;
        PEM_read_bio_PrivateKey(SSL_mem_bio__,&__temp_ptr,0,0);
        if(nullptr == __temp_ptr){
            std::cerr << __err + "PEM_read_bio_Priv" << std::endl;
            break;
        }
        *privKeyPtr = __temp_ptr;
        __res = true;
    }while(false);
    return __res;
}

遇到的问题

前面的步骤看起来都正常:密钥生成后写入文件成功(PEM_write的返回值都是正数),加载密钥时BIO_write的字节数也和密钥文件的大小一致,PEM_read_bio_PrivateKey也成功返回了EVP_PKEY指针,但到了调用EVP_PKEY_decrypt解密消息的时候就失败了,返回值一直是错误状态。

我已经检查了加密时的填充模式(和解密保持一致,用的是默认的RSA_PKCS1_PADDING),加密后的消息长度也符合2136位密钥对应的267字节,但解密就是走不通。有没有大佬能帮我看看哪儿可能出了问题?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:54:34