rubygems: Fix Gem::Request for PQC support, adding integration connection tests#9615
Open
junaruga wants to merge 1 commit into
Open
rubygems: Fix Gem::Request for PQC support, adding integration connection tests#9615junaruga wants to merge 1 commit into
junaruga wants to merge 1 commit into
Conversation
Member
Author
|
@hsbt and @rhenium, could you review this PR, as the PR heavily related to Ruby OpenSSL and OpenSSL? I need to fix the failing CI cases first. Thanks. I confirmed the following command passed on my local. |
Member
Author
|
Ah, I may find the cause of the failures in some CI cases. The |
db97880 to
4d762fa
Compare
Member
Author
|
OK. After add the logic to omit PQC tests if Ruby OpenSSL < 4.0, all the tests passed. |
4d762fa to
b79248a
Compare
…tion tests
Added PQC server/client connection integration tests.
As test_pqc_ssl_client_cert_auth_connection failed with the following error
due to hardcoded `OpenSSL::PKey::RSA.new` in
`Gem::Request.configure_connection_for_https`, fixed it to support ML-DSA ssl_client_cert.
```
Error: test_pqc_ssl_client_cert_auth_connection(TestGemRemoteFetcherLocalSSLServer): OpenSSL::PKey::PKeyError: incorrect pkey type: UNDEF
/home/jaruga/.local/ruby-4.1.0-debug-3ef48ef9c8-openssl-4.1.0-7194354488/lib/ruby/4.1.0+1/openssl/pkey.rb:394:in 'OpenSSL::PKey::RSA#initialize'
/home/jaruga/.local/ruby-4.1.0-debug-3ef48ef9c8-openssl-4.1.0-7194354488/lib/ruby/4.1.0+1/openssl/pkey.rb:394:in 'Class#new'
/home/jaruga/.local/ruby-4.1.0-debug-3ef48ef9c8-openssl-4.1.0-7194354488/lib/ruby/4.1.0+1/openssl/pkey.rb:394:in 'OpenSSL::PKey::RSA.new'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/request.rb:64:in 'Gem::Request.configure_connection_for_https'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/request/https_pool.rb:7:in 'Gem::Request::HTTPSPool#setup_connection'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/request/http_pool.rb:43:in 'Gem::Request::HTTPPool#make_connection'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/request/http_pool.rb:23:in 'Gem::Request::HTTPPool#checkout'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/request.rb:136:in 'Gem::Request#connection_for'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/request.rb:194:in 'Gem::Request#perform_request'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/request.rb:161:in 'Gem::Request#fetch'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/remote_fetcher.rb:326:in 'Gem::RemoteFetcher#request'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/remote_fetcher.rb:217:in 'Gem::RemoteFetcher#fetch_http'
/home/jaruga/var/git/ruby/rubygems/lib/rubygems/remote_fetcher.rb:261:in 'Gem::RemoteFetcher#fetch_path'
/home/jaruga/var/git/ruby/rubygems/test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb:98:in 'block in TestGemRemoteFetcherLocalSSLServer#test_pqc_ssl_client_cert_auth_connection'
95: ":ssl_ca_cert: #{temp_ca_cert}\n" \
96: ":ssl_client_cert: #{temp_client_cert}\n"
97: ) do |fetcher|
=> 98: fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}/yaml")
99: end
100: end
101:
/home/jaruga/var/git/ruby/rubygems/test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb:174:in 'TestGemRemoteFetcherLocalSSLServer#with_configured_fetcher'
/home/jaruga/var/git/ruby/rubygems/test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb:94:in 'TestGemRemoteFetcherLocalSSLServer#test_pqc_ssl_client_cert_auth_connection'
```
In test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb,
created new tests, test_pqc_ssl_connection and test_pqc_ssl_client_cert_auth_connection
The `start_ssl_server` has 2 modes: :non_pqc (default) and :pqc.
With the mode :pqc, `start_ssl_server` runs with the RubyGems single PQC server with
ML-KEM (X25519MLKEM768) key exchange and ML-DSA-65 certification.
Selected X25519MLKEM768 because rubygems.org supports X25519MLKEM768 for now.
Selected ML-DSA-65 because it is used and tested
https://github.com/ruby/openssl/blob/master/test/openssl/test_ssl.rb
- test_pqc_sigalg
Created `tool/create_mldsa65_certs.sh` to create ML-DSA-65 cert files,
`test/rubygems/mldsa65_*.pem`. It is inspired by `tool/create_certs.sh` to
create RSA cert files, `test/rubygems/*.pem`. Note the 65 in ML-DSA-65 is not
bit length. ML-DSA-65 is algorithm name.
b79248a to
c7008ef
Compare
Member
Author
|
After rebasing the PR on the latest master branch, the following Bundler tests failed. https://github.com/ruby/rubygems/actions/runs/27404697338/job/80990818846?pr=9615 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is related to #9542.
Summary
Added PQC server/client connection integration tests. As test_pqc_ssl_client_cert_auth_connection failed with the following error due to hardcoded
OpenSSL::PKey::RSA.newinGem::Request.configure_connection_for_https, fixed it to support ML-DSA ssl_client_cert.In test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb, created new tests, test_pqc_ssl_connection and test_pqc_ssl_client_cert_auth_connection The
start_ssl_serverhas 2 modes: :non_pqc (default) and :pqc. With the mode :pqc,start_ssl_serverruns with the RubyGems single PQC server with ML-KEM (X25519MLKEM768) key exchange and ML-DSA-65 certification.Selected X25519MLKEM768 because rubygems.org supports X25519MLKEM768 for now. Selected ML-DSA-65 because it is used and tested
https://github.com/ruby/openssl/blob/master/test/openssl/test_ssl.rb - test_pqc_sigalg
Created
tool/create_mldsa65_certs.shto create ML-DSA-65 cert files,test/rubygems/mldsa65_*.pem. It is inspired bytool/create_certs.shto create RSA cert files,test/rubygems/*.pem. Note the 65 in ML-DSA-65 is not bit length. ML-DSA-65 is algorithm name.Notes
CI cases using OpenSSL >= 3.5 supporting PQC
Seeing the `.github/workflows/rubygems.yml, ubuntu-24.04 uses OpenSSL 3.0.13 which doesn't support PQC.
https://github.com/actions/runner-images/blob/ubuntu24/20260607.184/images/ubuntu/Ubuntu2404-Readme.md
However, macos-26 uses OpenSSL 3.6.2 which supports PQC. The new PQC should run on the macos-26 cases.
https://github.com/actions/runner-images/blob/macos-26-arm64/20260525.0107/images/macos/macos-26-arm64-Readme.md
Missing PQC dual server case
I wanted to add the mode - :pqc_dual to test with RubyGems dual certificate server. The code is as follows. However, in the case, RubyGems client needs a feature to control the signature algorithm such as
OpenSSL::SSL::SSLContext#sigalgsused in https://github.com/ruby/openssl/blob/master/test/openssl/test_ssl.rb -test_pqc_sigalg. Because without this feature, the priority of selected signature algorithm depends on OpenSSL implementation. It can be unstable test.It is possible to implement this feature by
OPENSSL_CONFenvironment variable, and custom openssl.conf on a sub process usingassert_separatelyto control the client's signature algorithm. but the logic is too complicated. So, I didn't add the PQC dual server test case. It is premature to add the case. Possibly we can implement the#sigalgsto the ruby/net-http first, then fetcher (Gem::RemoteFetcher) can implement#sigalgscalling ruby/net-http's#sigalgs.What was the end-user or developer problem that led to this PR?
Gem::Request.configure_connection_for_httpsdoesn't work with ML-DSA ssl_client_cert due to hardcodedOpenSSL::PKey::RSA.new.What is your fix for the problem, implemented in this PR?
Fixed the
Gem::Request.configure_connection_for_httpsto support ML-DSA ssl_client_cert.Added integration HTTPS server/client connection tests.
Make sure the following tasks are checked