Skip to content

Commit 8ee6a58

Browse files
committed
pkey/dh: deprecate OpenSSL::PKey::DH#generate_key!
OpenSSL::PKey::DH#generate_key! will not work on OpenSSL 3.0 because keys are made immutable. Users should use OpenSSL::PKey.generate_key instead.
1 parent fc9aabc commit 8ee6a58

File tree

3 files changed

+34
-16
lines changed

3 files changed

+34
-16
lines changed

ext/openssl/ossl_pkey_dh.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,16 @@ VALUE eDHError;
5858
*
5959
* Examples:
6060
* # Creating an instance from scratch
61-
* dh = DH.new
61+
* # Note that this is deprecated and will not work on OpenSSL 3.0 or later.
62+
* dh = OpenSSL::PKey::DH.new
6263
* dh.set_pqg(bn_p, nil, bn_g)
6364
*
6465
* # Generating a parameters and a key pair
65-
* dh = DH.new(2048) # An alias of DH.generate(2048)
66+
* dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
6667
*
6768
* # Reading DH parameters
68-
* dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
69-
* dh.generate_key! # -> dh with public and private key
69+
* dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
70+
* dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
7071
*/
7172
static VALUE
7273
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)

lib/openssl/pkey.rb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,29 @@ def compute_key(pub_bn)
7171
# called first in order to generate the per-session keys before performing
7272
# the actual key exchange.
7373
#
74+
# <b>Deprecated in version 3.0</b>. This method is incompatible with
75+
# OpenSSL 3.0.0 or later.
76+
#
7477
# See also OpenSSL::PKey.generate_key.
7578
#
7679
# Example:
77-
# dh = OpenSSL::PKey::DH.new(2048)
78-
# public_key = dh.public_key #contains no private/public key yet
79-
# public_key.generate_key!
80-
# puts public_key.private? # => true
80+
# # DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later
81+
# dh0 = OpenSSL::PKey::DH.new(2048)
82+
# dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name)
83+
# dh.generate_key!
84+
# puts dh.private? # => true
85+
# puts dh0.pub_key == dh.pub_key #=> false
86+
#
87+
# # With OpenSSL::PKey.generate_key
88+
# dh0 = OpenSSL::PKey::DH.new(2048)
89+
# dh = OpenSSL::PKey.generate_key(dh0)
90+
# puts dh0.pub_key == dh.pub_key #=> false
8191
def generate_key!
92+
if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000
93+
raise DHError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \
94+
"use OpenSSL::PKey.generate_key instead"
95+
end
96+
8297
unless priv_key
8398
tmp = OpenSSL::PKey.generate_key(self)
8499
set_key(tmp.pub_key, tmp.priv_key)

test/openssl/test_pkey_dh.rb

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,19 @@ def test_new_break
2626
end
2727

2828
def test_derive_key
29-
dh1 = Fixtures.pkey("dh1024").generate_key!
30-
dh2 = Fixtures.pkey("dh1024").generate_key!
29+
params = Fixtures.pkey("dh1024")
30+
dh1 = OpenSSL::PKey.generate_key(params)
31+
dh2 = OpenSSL::PKey.generate_key(params)
3132
dh1_pub = OpenSSL::PKey.read(dh1.public_to_der)
3233
dh2_pub = OpenSSL::PKey.read(dh2.public_to_der)
34+
3335
z = dh1.g.mod_exp(dh1.priv_key, dh1.p).mod_exp(dh2.priv_key, dh1.p).to_s(2)
3436
assert_equal z, dh1.derive(dh2_pub)
3537
assert_equal z, dh2.derive(dh1_pub)
3638

39+
assert_raise(OpenSSL::PKey::PKeyError) { params.derive(dh1_pub) }
40+
assert_raise(OpenSSL::PKey::PKeyError) { dh1_pub.derive(params) }
41+
3742
assert_equal z, dh1.compute_key(dh2.pub_key)
3843
assert_equal z, dh2.compute_key(dh1.pub_key)
3944
end
@@ -74,19 +79,16 @@ def test_public_key
7479
end
7580

7681
def test_generate_key
77-
dh = Fixtures.pkey("dh1024").public_key # creates a copy
82+
# Deprecated in v3.0.0; incompatible with OpenSSL 3.0
83+
dh = Fixtures.pkey("dh1024").public_key # creates a copy with params only
7884
assert_no_key(dh)
7985
dh.generate_key!
8086
assert_key(dh)
81-
end
8287

83-
def test_key_exchange
84-
dh = Fixtures.pkey("dh1024")
8588
dh2 = dh.public_key
86-
dh.generate_key!
8789
dh2.generate_key!
8890
assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key))
89-
end
91+
end if !openssl?(3, 0, 0)
9092

9193
def test_params_ok?
9294
dh0 = Fixtures.pkey("dh1024")

0 commit comments

Comments
 (0)