@@ -101,23 +101,29 @@ void HybridDiffieHellman::initWithSize(double primeLength, double generator) {
101101std::shared_ptr<ArrayBuffer> HybridDiffieHellman::generateKeys () {
102102 ensureInitialized ();
103103
104- EVP_PKEY_CTX_ptr kctx (EVP_PKEY_CTX_new (_pkey.get (), nullptr ), EVP_PKEY_CTX_free);
105- if (!kctx) {
106- throw std::runtime_error (" DiffieHellman: failed to create keygen context" );
107- }
108-
109- if (EVP_PKEY_keygen_init (kctx.get ()) <= 0 ) {
110- throw std::runtime_error (" DiffieHellman: failed to initialize key generation" );
104+ // EVP_PKEY_get0_DH may return a provider-cached copy in OpenSSL 3.x,
105+ // so we must detach the DH, generate keys on it directly (like ncrypto),
106+ // then re-wrap in a fresh EVP_PKEY.
107+ DH * dh = EVP_PKEY_get1_DH (_pkey.get ());
108+ if (!dh) {
109+ throw std::runtime_error (" DiffieHellman: failed to get DH key" );
111110 }
112111
113- EVP_PKEY * newKey = nullptr ;
114- if (EVP_PKEY_keygen (kctx.get (), &newKey) <= 0 ) {
112+ // DH_generate_key preserves an existing private key and only computes the
113+ // public key. When no private key is set it generates both.
114+ if (!DH_generate_key (dh)) {
115+ DH_free (dh);
115116 throw std::runtime_error (" DiffieHellman: failed to generate key pair" );
116117 }
117118
118- // Replace parameters-only key with full key (which includes parameters)
119- _pkey.reset (newKey);
119+ EVP_PKEY_ptr newPkey (EVP_PKEY_new (), EVP_PKEY_free);
120+ if (!newPkey || EVP_PKEY_assign_DH (newPkey.get (), dh) != 1 ) {
121+ DH_free (dh);
122+ throw std::runtime_error (" DiffieHellman: failed to assign DH to EVP_PKEY" );
123+ }
124+ // EVP_PKEY_assign_DH took ownership of dh
120125
126+ _pkey = std::move (newPkey);
121127 return getPublicKey ();
122128}
123129
0 commit comments