6daba0
From 558128594de16add5b453833fd5b043a24c1b7f5 Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Wed, 22 Dec 2021 01:38:47 +0900
6daba0
Subject: [PATCH 1/3] Use OpenSSL::PKey::EC.generate to generate ECC key pairs
6daba0
6daba0
When Ruby/OpenSSL is built against OpenSSL 3.0, OpenSSL::PKey::PKey
6daba0
instances are immutable and OpenSSL::PKey::EC#generate_key cannot work
6daba0
because it modifies the receiver.
6daba0
6daba0
OpenSSL::PKey::EC.generate is available on Ruby 2.4 (Ruby/OpenSSL 2.0)
6daba0
or later.
6daba0
---
6daba0
 lib/rubygems/security.rb | 10 +++++++---
6daba0
 1 file changed, 7 insertions(+), 3 deletions(-)
6daba0
6daba0
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
6daba0
index 22759972070..2aa07381d69 100644
6daba0
--- a/lib/rubygems/security.rb
6daba0
+++ b/lib/rubygems/security.rb
6daba0
@@ -490,9 +490,13 @@ def self.create_key(algorithm)
6daba0
       when 'rsa'
6daba0
         OpenSSL::PKey::RSA.new(RSA_DSA_KEY_LENGTH)
6daba0
       when 'ec'
6daba0
-        domain_key = OpenSSL::PKey::EC.new(EC_NAME)
6daba0
-        domain_key.generate_key
6daba0
-        domain_key
6daba0
+        if RUBY_VERSION >= "2.4.0"
6daba0
+          OpenSSL::PKey::EC.generate(EC_NAME)
6daba0
+        else
6daba0
+          domain_key = OpenSSL::PKey::EC.new(EC_NAME)
6daba0
+          domain_key.generate_key
6daba0
+          domain_key
6daba0
+        end
6daba0
       else
6daba0
         raise Gem::Security::Exception,
6daba0
         "#{algorithm} algorithm not found. RSA, DSA, and EC algorithms are supported."
6daba0
6daba0
From 60067d4f09b7fb9c23bed38e91acfde0293f29a0 Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Wed, 22 Dec 2021 01:49:05 +0900
6daba0
Subject: [PATCH 2/3] Use OpenSSL::X509::Certificate#check_private_key
6daba0
6daba0
The method is for the exact purpose: to check that an instance of
6daba0
OpenSSL::PKey::PKey matches the public key in a certificate.
6daba0
---
6daba0
 lib/rubygems/security.rb        | 2 +-
6daba0
 lib/rubygems/security/policy.rb | 4 +---
6daba0
 2 files changed, 2 insertions(+), 4 deletions(-)
6daba0
6daba0
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
6daba0
index 2aa07381d69..2906819bd34 100644
6daba0
--- a/lib/rubygems/security.rb
6daba0
+++ b/lib/rubygems/security.rb
6daba0
@@ -530,7 +530,7 @@ def self.re_sign(expired_certificate, private_key, age = ONE_YEAR,
6daba0
     raise Gem::Security::Exception,
6daba0
           "incorrect signing key for re-signing " +
6daba0
           "#{expired_certificate.subject}" unless
6daba0
-      expired_certificate.public_key.to_pem == get_public_key(private_key).to_pem
6daba0
+      expired_certificate.check_private_key(private_key)
6daba0
 
6daba0
     unless expired_certificate.subject.to_s ==
6daba0
            expired_certificate.issuer.to_s
6daba0
diff --git a/lib/rubygems/security/policy.rb b/lib/rubygems/security/policy.rb
6daba0
index 3c3cb647ee3..06eae073f4a 100644
6daba0
--- a/lib/rubygems/security/policy.rb
6daba0
+++ b/lib/rubygems/security/policy.rb
6daba0
@@ -115,11 +115,9 @@ def check_key(signer, key)
6daba0
       raise Gem::Security::Exception, 'missing key or signature'
6daba0
     end
6daba0
 
6daba0
-    public_key = Gem::Security.get_public_key(key)
6daba0
-
6daba0
     raise Gem::Security::Exception,
6daba0
       "certificate #{signer.subject} does not match the signing key" unless
6daba0
-        signer.public_key.to_pem == public_key.to_pem
6daba0
+        signer.check_private_key(key)
6daba0
 
6daba0
     true
6daba0
   end
6daba0
6daba0
From 6819e3d0fadc10ce8d10919402eedb730cf0e43f Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Wed, 22 Dec 2021 01:54:10 +0900
6daba0
Subject: [PATCH 3/3] Fix Gem::Security.get_public_key on OpenSSL 3.0
6daba0
6daba0
Ruby/OpenSSL 2.2 added OpenSSL::PKey::PKey#public_to_der for serializing
6daba0
only the public key components contained in the instance. This works
6daba0
for all possible key types.
6daba0
---
6daba0
 lib/rubygems/security.rb | 2 ++
6daba0
 1 file changed, 2 insertions(+)
6daba0
6daba0
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
6daba0
index 2906819bd34..f21c1756422 100644
6daba0
--- a/lib/rubygems/security.rb
6daba0
+++ b/lib/rubygems/security.rb
6daba0
@@ -424,6 +424,8 @@ def self.create_cert(subject, key, age = ONE_YEAR, extensions = EXTENSIONS,
6daba0
   # Gets the right public key from a PKey instance
6daba0
 
6daba0
   def self.get_public_key(key)
6daba0
+    # Ruby 3.0 (Ruby/OpenSSL 2.2) or later
6daba0
+    return OpenSSL::PKey.read(key.public_to_der) if key.respond_to?(:public_to_der)
6daba0
     return key.public_key unless key.is_a?(OpenSSL::PKey::EC)
6daba0
 
6daba0
     ec_key = OpenSSL::PKey::EC.new(key.group.curve_name)