OpenSSL 3.0.8中EVP_PKEY_decrypt私钥解密失败求助
OpenSSL 3.0.8中EVP_PKEY_decrypt私钥解密失败求助
我自己捣鼓了好半天都没找到解决办法,来这儿求助各位大佬!我正在用OpenSSL 3库写一个简单的加密聊天客户端-服务端程序,客户端和服务端的Socket模块都继承自abstract_secure_socket纯虚类,里面封装了RSA密钥对的生成逻辑——用公钥加密消息,私钥解密。
目前的实现步骤
- 首次启动生成密钥文件
我定义了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; }
- 从文件加载密钥到内存
生成密钥文件后,我会把密钥读取到字符串,再通过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
相关产品推荐
相关产品推荐

