From 9593e5aea7b6f9c92a76fbe71a82d474df053c42 Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Mon, 17 Aug 2026 13:39:37 +0100 Subject: [PATCH 1/3] CI: Fix core_assertions LoadError in Windows cases This commit fixes the following CI failures in Windows. I don't know why this change fixed. Perhaps Bundler's handling with git repository is different. https://github.com/ruby/drb/actions/runs/32029577375/job/95386338154?pr=54 ``` D:/a/drb/drb/test/lib/helper.rb:2:in 'Kernel#require': cannot load such file -- core_assertions (LoadError) from D:/a/drb/drb/test/lib/helper.rb:2:in '' from :139:in 'Kernel#require' rake aborted! Command failed with status (1) D:/a/drb/drb/vendor/bundle/ruby/4.1.0+4/gems/rake-13.4.2/exe/rake:27:in '' D:/rubyinstaller-head-x64/bin/bundle:33:in '
' Tasks: TOP => default => test (See full trace by running task with --trace) Error: Process completed with exit code 1. ``` --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index e673971..39549fe 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,4 @@ gemspec gem "rake" gem "test-unit" -gem "test-unit-ruby-core", git: "https://github.com/ruby/test-unit-ruby-core" +gem "test-unit-ruby-core" From f83310f35492e290cd860b2e4f2ef0c2796ecbfc Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Tue, 18 Aug 2026 16:13:28 +0100 Subject: [PATCH 2/3] Remove OpenSSL::PKey::RSA#public_key OpenSSL::PKey::RSA#public_key is obsolete according to ruby/openssl#1092. --- lib/drb/ssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb index 096f355..302c71c 100644 --- a/lib/drb/ssl.rb +++ b/lib/drb/ssl.rb @@ -180,7 +180,7 @@ def setup_certificate cert.issuer = name cert.not_before = Time.now cert.not_after = Time.now + (365*24*60*60) - cert.public_key = rsa.public_key + cert.public_key = rsa ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) cert.extensions = [ From 328508f3b42417fd1fcf3b33ff81a1a622662d8d Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Wed, 29 Jul 2026 11:00:28 +0100 Subject: [PATCH 3/3] Add post-quantum cryptography (PQC) support to SSLConfig DRb::DRbSSLSocket::SSLConfig already works with pre-generated ML-DSA cert/key by :SSLCertificate and :SSLPrivateKey config options. This commit adds the following features in PQC use cases to #setup_certificate and #setup_ssl_context. * Add :SSLCertificates config option accepting an Array of [certificate, private_key] pairs for multiple certificate support via OpenSSL::SSL::SSLContext#add_certificate changing from OpenSSL::SSL::SSLContext#cert and #key. Because an SSL server that accepts clients with either ML-DSA-NN or RSA certificates is useful in the use case of PQC migration from RSA (non-PQC) to ML-DSA (PQC). :SSLCertificate and :SSLPrivateKey are available for backward compatibility. But use OpenSSL::SSL::SSLContext#add_certificate internally. This is a behavior change. * Add :SSLPrivateKeyAlgorithms option accepting an Array of key algorithms (RSA, ML-DSA-44, ML-DSA-65, ML-DSA-87) for multi-certificate generation, defaulting to ["RSA"] for backward compatibility. * Add :SSLGroups option to control key exchange group such as ML-KEM in PQC. * Add :SSLSignatureAlgorithms, :SSLClientSignatureAlgorithms to control signature algorithms such as ML-DSA-NN in PQC, and RSA in non-PQC. * Add tool/create_certs.rb to generate test/drb/fixtures/*.{crt,key} to test with pre-generated certs/keys and add DRbTests::Fixtures module to read the certs/keys. * Add test/drb/test_ssl.rb to test lib/drb/ssl.rb at the unit test level. This approach aligns with test/drb/test_acl.rb to test lib/drb/acl.rb at the unit test level. * Add TestDRbSSLPQC, TestDRbSSLPQCMultipleCert in test/drb/test_drbssl.rb. TestDRbSSLPQC is to test single PQC ML-KEM/ML-DSA server and client. TestDRbSSLPQCMultipleCert is to test ML-DSA-65 (PQC) and RSA (non-PQC) multiple certificate server with client certificate verification. The test is designed for a high-security use case with :SSLVerifyMode OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT. Assisted-by: Claude:claude-opus-4-6[1m] --- lib/drb/ssl.rb | 163 ++++++++---- test/drb/drbtest.rb | 72 ++++++ test/drb/drbtest_utils.rb | 34 +++ test/drb/fixtures/mldsa65_ca.crt | 119 +++++++++ test/drb/fixtures/mldsa65_client.crt | 118 +++++++++ test/drb/fixtures/mldsa65_client.key | 88 +++++++ test/drb/fixtures/mldsa65_server.crt | 119 +++++++++ test/drb/fixtures/mldsa65_server.key | 88 +++++++ test/drb/fixtures/rsa_ca.crt | 20 ++ test/drb/fixtures/rsa_client.crt | 20 ++ test/drb/fixtures/rsa_client.key | 28 +++ test/drb/fixtures/rsa_server.crt | 20 ++ test/drb/fixtures/rsa_server.key | 28 +++ test/drb/test_drbssl.rb | 143 +++++++++++ test/drb/test_ssl.rb | 361 +++++++++++++++++++++++++++ tool/create_certs.rb | 84 +++++++ 16 files changed, 1459 insertions(+), 46 deletions(-) create mode 100644 test/drb/drbtest_utils.rb create mode 100644 test/drb/fixtures/mldsa65_ca.crt create mode 100644 test/drb/fixtures/mldsa65_client.crt create mode 100644 test/drb/fixtures/mldsa65_client.key create mode 100644 test/drb/fixtures/mldsa65_server.crt create mode 100644 test/drb/fixtures/mldsa65_server.key create mode 100644 test/drb/fixtures/rsa_ca.crt create mode 100644 test/drb/fixtures/rsa_client.crt create mode 100644 test/drb/fixtures/rsa_client.key create mode 100644 test/drb/fixtures/rsa_server.crt create mode 100644 test/drb/fixtures/rsa_server.key create mode 100644 test/drb/test_ssl.rb create mode 100755 tool/create_certs.rb diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb index 302c71c..3f46d09 100644 --- a/lib/drb/ssl.rb +++ b/lib/drb/ssl.rb @@ -25,19 +25,25 @@ class SSLConfig # # See DRb::DRbSSLSocket::SSLConfig.new for more details DEFAULT = { - :SSLCertificate => nil, - :SSLPrivateKey => nil, - :SSLClientCA => nil, - :SSLCACertificatePath => nil, - :SSLCACertificateFile => nil, - :SSLTmpDhCallback => nil, - :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, - :SSLVerifyDepth => nil, - :SSLVerifyCallback => nil, # custom verification - :SSLCertificateStore => nil, + :SSLCertificates => nil, + :SSLCertificate => nil, + :SSLPrivateKey => nil, + :SSLPrivateKeyAlgorithms => ["RSA"], + :SSLClientCA => nil, + :SSLCACertificatePath => nil, + :SSLCACertificateFile => nil, + :SSLSignatureAlgorithms => nil, + :SSLClientSignatureAlgorithms => nil, + :SSLGroups => nil, + :SSLTmpDhCallback => nil, + :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, + :SSLVerifyDepth => nil, + :SSLVerifyCallback => nil, # custom verification + :SSLCertificateStore => nil, # Must specify if you use auto generated certificate. - :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]] - :SSLCertComment => "Generated by Ruby/OpenSSL" + # e.g. [["CN", "fqdn.example.com"]] + :SSLCertName => nil, + :SSLCertComment => "Generated by Ruby/OpenSSL" } # Create a new DRb::DRbSSLSocket::SSLConfig instance @@ -51,13 +57,29 @@ class SSLConfig # # From +config+ Hash: # + # :SSLCertificates :: + # An Array of [certificate, private_key] pairs. Each element + # is an Array of an OpenSSL::X509::Certificate and its + # corresponding private key. This option is prioritized over + # :SSLCertificate and :SSLPrivateKey. See + # OpenSSL::SSL::SSLContext#add_certificate + # # :SSLCertificate :: # An instance of OpenSSL::X509::Certificate. If this is not provided, # then a generic X509 is generated, with a correspond :SSLPrivateKey # # :SSLPrivateKey :: - # A private key instance, like OpenSSL::PKey::RSA. This key must be - # the key that signed the :SSLCertificate + # A private key instance, like OpenSSL::PKey::RSA for RSA + # and OpenSSL::PKey::PKey for ML-DSA-44, ML-DSA-65, + # ML-DSA-87. This key must be the key that signed the + # :SSLCertificate + # + # :SSLPrivateKeyAlgorithms :: + # An Array of private key algorithms used to generate + # certificates when :SSLCertificates, :SSLCertificate and + # :SSLPrivateKey are not provided. Supported algorithms are + # RSA, ML-DSA-44, ML-DSA-65, and ML-DSA-87. + # Defaults to ["RSA"] # # :SSLClientCA :: # An OpenSSL::X509::Certificate, or Array of certificates that will @@ -70,6 +92,15 @@ class SSLConfig # :SSLCACertificateFile :: # A path to a CA certificate file, in PEM format. # + # :SSLSignatureAlgorithms :: + # Signature algorithms. See OpenSSL::SSL::SSLContext#sigalgs= + # + # :SSLClientSignatureAlgorithms :: + # Client signature algorithms. See OpenSSL::SSL::SSLContext#client_sigalgs= + # + # :SSLGroups :: + # Key exchange groups. See OpenSSL::SSL::SSLContext#groups= + # # :SSLTmpDhCallback :: # A DH callback. See OpenSSL::SSL::SSLContext.tmp_dh_callback # @@ -133,10 +164,14 @@ class SSLConfig # c.setup_certificate # def initialize(config) - @config = config - @cert = config[:SSLCertificate] - @pkey = config[:SSLPrivateKey] - @ssl_ctx = nil + @config = config + @certs = if config.key?(:SSLCertificates) + config[:SSLCertificates] + elsif config[:SSLCertificate] && config[:SSLPrivateKey] + [[config[:SSLCertificate], config[:SSLPrivateKey]]] + end + @pkey_algs = self[:SSLPrivateKeyAlgorithms] + @ssl_ctx = nil end # A convenience method to access the values like a Hash @@ -162,17 +197,74 @@ def accept(tcp) ssl end - # Ensures that :SSLCertificate and :SSLPrivateKey have been provided - # or that a new certificate is generated with the other parameters - # provided. + # Ensures that :SSLCertificates or :SSLCertificate and + # :SSLPrivateKey have been provided, or that new certificates + # are generated with the other parameters provided. def setup_certificate - if @cert && @pkey + if @certs return end - rsa = OpenSSL::PKey::RSA.new(2048) + @certs = @pkey_algs.map { |pkey_alg| setup_certificate_one(pkey_alg) } + end + + # Establish the OpenSSL::SSL::SSLContext with the configuration + # parameters provided. + def setup_ssl_context + ctx = ::OpenSSL::SSL::SSLContext.new + @certs&.each do |cert, pkey| + ctx.add_certificate(cert, pkey) + end + ctx.min_version = self[:SSLMinVersion] + ctx.max_version = self[:SSLMaxVersion] + ctx.client_ca = self[:SSLClientCA] + ctx.ca_path = self[:SSLCACertificatePath] + ctx.ca_file = self[:SSLCACertificateFile] + if self[:SSLSignatureAlgorithms] + ctx.sigalgs = self[:SSLSignatureAlgorithms] + end + if self[:SSLClientSignatureAlgorithms] + ctx.client_sigalgs = self[:SSLClientSignatureAlgorithms] + end + if self[:SSLGroups] + ctx.groups = self[:SSLGroups] + end + ctx.tmp_dh_callback = self[:SSLTmpDhCallback] + ctx.verify_mode = self[:SSLVerifyMode] + ctx.verify_depth = self[:SSLVerifyDepth] + ctx.verify_callback = self[:SSLVerifyCallback] + ctx.cert_store = self[:SSLCertificateStore] + @ssl_ctx = ctx + end + + private + def setup_certificate_one(pkey_alg) cert = OpenSSL::X509::Certificate.new + + case pkey_alg + when "RSA" + pkey = OpenSSL::PKey::RSA.new(2048) + cert.public_key = pkey + digest = "SHA256" + when "ML-DSA-44", "ML-DSA-65", "ML-DSA-87" + # OpenSSL >= 3.5.0 support ML-DSA. OpenSSL::PKey.generate_key raises + # OpenSSL::PKey::PKeyError if ML-DSA algorithm is not supported. + # https://openssl-library.org/post/2025-04-08-openssl-35-final-release/ + pkey = OpenSSL::PKey.generate_key(pkey_alg) + # OpenSSL::PKey::PKey#public_to_der was added in openssl gem 2.2.0. + # https://github.com/ruby/openssl/blob/v2.2.0/History.md?plain=1#L72-L75 + cert.public_key = OpenSSL::PKey.read(pkey.public_to_der) + # OpenSSL::X509::Certificate#sign doesn't accept explicit digest + # algorithm, in ML-DSA because ML-DSA has a built-in digest. + digest = nil + else + raise(ArgumentError, + "#{pkey_alg} algorithm not found. "\ + "RSA, ML-DSA-44, ML-DSA-65, and ML-DSA-87 "\ + "algorithms are supported") + end + cert.version = 2 # This means v3 cert.serial = 0 name = OpenSSL::X509::Name.new(self[:SSLCertName]) @@ -180,7 +272,6 @@ def setup_certificate cert.issuer = name cert.not_before = Time.now cert.not_after = Time.now + (365*24*60*60) - cert.public_key = rsa ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) cert.extensions = [ @@ -192,29 +283,9 @@ def setup_certificate if comment = self[:SSLCertComment] cert.add_extension(ef.create_extension("nsComment", comment)) end - cert.sign(rsa, "SHA256") - - @cert = cert - @pkey = rsa - end + cert.sign(pkey, digest) - # Establish the OpenSSL::SSL::SSLContext with the configuration - # parameters provided. - def setup_ssl_context - ctx = ::OpenSSL::SSL::SSLContext.new - ctx.cert = @cert - ctx.key = @pkey - ctx.min_version = self[:SSLMinVersion] - ctx.max_version = self[:SSLMaxVersion] - ctx.client_ca = self[:SSLClientCA] - ctx.ca_path = self[:SSLCACertificatePath] - ctx.ca_file = self[:SSLCACertificateFile] - ctx.tmp_dh_callback = self[:SSLTmpDhCallback] - ctx.verify_mode = self[:SSLVerifyMode] - ctx.verify_depth = self[:SSLVerifyDepth] - ctx.verify_callback = self[:SSLVerifyCallback] - ctx.cert_store = self[:SSLCertificateStore] - @ssl_ctx = ctx + [cert, pkey] end end diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb index 03e4ca1..f104305 100644 --- a/test/drb/drbtest.rb +++ b/test/drb/drbtest.rb @@ -4,6 +4,7 @@ require 'drb/drb' require 'drb/extservm' require 'timeout' +require_relative 'drbtest_utils' module DRbTests @@ -393,4 +394,75 @@ def test_07_break_18 end +# A PQC Utilities module inspired from ruby/rubygems omit_unless_support_pqc +module DRbPQCUtilities + # PQC algorithms ML-KEM and ML-DSA require OpenSSL >= 3.5. + # https://openssl-library.org/post/2025-04-08-openssl-35-final-release/ + # Ruby OpenSSL >= 4.0 has useful methods in PQC use cases. + # https://github.com/ruby/openssl/blob/v4.0.0/History.md?plain=1#L25-L35 + # And fixed the following bug related to PQC. + # https://github.com/ruby/openssl/pull/898 + # However, we don't check OpenSSL and Ruby OpenSSL versions here + # for a flexible check for other SSL libraries such as LibreSSL and AWS-LC. + def omit_unless_support_pqc + # Even with a new enough OpenSSL, the runtime may keep PQC groups and + # signature algorithms out of its default negotiation lists (for example + # RHEL's system-wide crypto policies). The PQC server forces both, while + # the gem fetcher connects with the default client configuration, so a + # real loopback handshake is the only reliable way to tell whether this + # environment can negotiate PQC at all. + unless support_pqc_handshake? + yield if block_given? + omit 'OpenSSL or Ruby OpenSSL is too old to support PQC, '\ + 'or PQC handshake is not available in this OpenSSL configuration' + end + end + + # Probe an actual PQC handshake between a forced-PQC server and a + # default-configured client, mirroring what the integration tests exercise. + # Memoized so the probe runs at most once per process. + def support_pqc_handshake? + return @support_pqc_handshake unless @support_pqc_handshake.nil? + + @support_pqc_handshake = probe_pqc_handshake + end + + def probe_pqc_handshake + server = TCPServer.new('127.0.0.1', 0) + ctx = OpenSSL::SSL::SSLContext.new + cert = Fixtures.read_cert('mldsa65_server.crt') + pkey = Fixtures.read_pkey('mldsa65_server.key') + ctx.add_certificate(cert, pkey) + + # ctx.groups (OpenSSL::SSL::SSLContext#groups) requires Ruby OpenSSL >= 4.0. + return nil unless ctx.respond_to?(:groups=) + + ctx.groups = 'X25519MLKEM768' + ssl_server = OpenSSL::SSL::SSLServer.new(server, ctx) + + port = server.addr[1] + server_thread = Thread.new do + client = ssl_server.accept + client.close + rescue OpenSSL::OpenSSLError + nil + end + + client_ctx = OpenSSL::SSL::SSLContext.new + client_ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE + socket = TCPSocket.new('127.0.0.1', port) + ssl = OpenSSL::SSL::SSLSocket.new(socket, client_ctx) + ssl.connect + ssl.close + true + rescue OpenSSL::PKey::PKeyError, OpenSSL::OpenSSLError, SystemCallError + false + ensure + server_thread&.join(5) + server_thread&.kill if server_thread&.alive? + ssl_server&.close + server&.close + end +end + end diff --git a/test/drb/drbtest_utils.rb b/test/drb/drbtest_utils.rb new file mode 100644 index 0000000..e560aeb --- /dev/null +++ b/test/drb/drbtest_utils.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: false + +# This file does not require test/unit unlike drbtest.rb because it can +# be loaded by child processes (ut_*.rb) where +# test-unit's at_exit autorunner would cause errors. + +require 'openssl' + +module DRbTests + +module Fixtures + module_function + + def file_path(name) + File.join(__dir__, 'fixtures', name) + end + + def read_file(name) + @file_cache ||= {} + @file_cache[name] ||= File.read(file_path(name)) + end + + # Raises OpenSSL::PKey::PKeyError when reading an ML-DSA-65 key file + # with old OpenSSL versions. + def read_pkey(name) + OpenSSL::PKey.read(read_file(name)) + end + + def read_cert(name) + OpenSSL::X509::Certificate.new(read_file(name)) + end +end + +end diff --git a/test/drb/fixtures/mldsa65_ca.crt b/test/drb/fixtures/mldsa65_ca.crt new file mode 100644 index 0000000..a99d450 --- /dev/null +++ b/test/drb/fixtures/mldsa65_ca.crt @@ -0,0 +1,119 @@ +-----BEGIN CERTIFICATE----- +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 +AAAAAAAAAAAAAAAAAAAAAAYMERchJQ== +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/mldsa65_client.crt b/test/drb/fixtures/mldsa65_client.crt new file mode 100644 index 0000000..abd449d --- /dev/null +++ b/test/drb/fixtures/mldsa65_client.crt @@ -0,0 +1,118 @@ +-----BEGIN CERTIFICATE----- +MIIVsjCCCK+gAwIBAgIBAjALBglghkgBZQMEAxIwPDELMAkGA1UEBhMCSlAxDjAM +BgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJUZXN0MQswCQYDVQQDDAJDQTAeFw0w +OTAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMEAxCzAJBgNVBAYTAkpQMQ4wDAYD +VQQIDAVUb2t5bzEQMA4GA1UECgwHRFJiVGVzdDEPMA0GA1UEAwwGQ2xpZW50MIIH +sjALBglghkgBZQMEAxIDggehAOYhNsWj54At29gSht7N161dMQ/eNO9LMw9mP2Iz +pGSmNlmOX/O+pFG0/uEYiwonEDWg71ud/GxLFfojUvTOEvMcTc7/MVVY/PL6MbHW +Rm4J1SP2p4wn3AiWeX3paizWfuKq1GMy+o1fyAQODx3ZECco6wWBPMKXMNQWU5uS +gctjwI3awFkECnMnzmUoZQNKf7KRmZKHupYB7nqjyLGVtWyPDT7hJuOiRF+w7ui0 +FQZ4lQoWLiXnzTr/WjWYBgsfnNDZZXICcZDkOs/xAQm4elPgfbeYGPVFIz41xH7s +MSRliNNFXOJOvhDyZvDmKSDAVJ656g7j0kaF/IVS2Y9tpA1425G8UGKpN4ssnfyL +riLozc8fbDhdYFw+E26EhVtrRYKn3sMT9XKcbhyG2sKyd2fGIIvFZpFsyDodGjSY ++0lhtIRHyLTmG98UaT/laT2CNOlm8NBZIaFAytk7OpUP1zQYGe+9DGq35Z7d5RHu +5At0Y43M9+Tmgfmvj/dgmFb6rlveQ7I4TP25DkPnFCOqpfHvqJRBpp6G/oCW8BR/ +xYwDtXN95yvKDV7aAoDQfsgDKx4UnkAUVPegwS9Ftw9sMF7fgkb48Bjd0v08zX4h +JatB9Y5jG5OQdGXtVMgFMdzUI/Q2WhrwN+LHgQT9LdfoEmwTccEWsze4XxebwuA+ +69nbUc4OmxR6Iwoe1HdqNk3dRGT4bGbp7kv/lpCWVD7+FzV5pGyhpycVbttyAFC5 +SOATpR/jfCs3kUOYdunXROVwZK3/F0anz3eKbQIeGZ6Q6cOfkJkzm+dWXXc7KgfX +DFHso+6jmvZKCZ0jrv78cHgX3JKZi/dgSmoq4EfjG+hRCzLg9NXDsY1Upx96ULxa +xJutZxWsiFKcc17vsvqbw6QZA3PfbcAD7luIGfaVga/NOdfse+U+xRcUt3NuByWC +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 +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/mldsa65_client.key b/test/drb/fixtures/mldsa65_client.key new file mode 100644 index 0000000..4fb3d72 --- /dev/null +++ b/test/drb/fixtures/mldsa65_client.key @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +pZaeTxnvF8grJHjdTU+dpKtu +-----END PRIVATE KEY----- diff --git a/test/drb/fixtures/mldsa65_server.crt b/test/drb/fixtures/mldsa65_server.crt new file mode 100644 index 0000000..489f58e --- /dev/null +++ b/test/drb/fixtures/mldsa65_server.crt @@ -0,0 +1,119 @@ +-----BEGIN CERTIFICATE----- +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 +AAAAAAAAAAAAChMXGh4m +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/mldsa65_server.key b/test/drb/fixtures/mldsa65_server.key new file mode 100644 index 0000000..fc53750 --- /dev/null +++ b/test/drb/fixtures/mldsa65_server.key @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +WDMPrwGZIBYpU3qMkPdtubXu +-----END PRIVATE KEY----- diff --git a/test/drb/fixtures/rsa_ca.crt b/test/drb/fixtures/rsa_ca.crt new file mode 100644 index 0000000..79f998c --- /dev/null +++ b/test/drb/fixtures/rsa_ca.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWTCCAkGgAwIBAgIUMJ94MNG5Lm+VVMWn5MSvOuzCZ78wDQYJKoZIhvcNAQEL +BQAwPDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJU +ZXN0MQswCQYDVQQDDAJDQTAeFw0wOTAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTla +MDwxCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEQMA4GA1UECgwHRFJiVGVz +dDELMAkGA1UEAwwCQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCq +cx13jFjiyEhrP6XKsU/RNcNfxT8Gca2prc5AJ37jyWHZ//DZMm2cALx6/kHsnT6r +qMrQ8+n7HHN+5hS/7C+VCUR0r/Zxgh+D16sYbrbHfprGNqKt15UztUUiWtorTwHJ +T3zMOTs5lWT5/ndmAz/5ioF+HrbmVO11EA1HNaC+qdrJlSg5zNWE2Qa/TubJh955 +qEbZjWpJ2W/GoQZInMYKYYTAs55QVN7W20CiF4yJJ8IU4BnU/s6GwsYTZ/3zLw6N +LMAOey0la115vNqjIbB1VmpoSRAL7ccMpuxIIjFSYIwj4f5Zj9RQsUrdeT/waHd7 +fq22YLfgorKHGLZp+2U1AgMBAAGjUzBRMB0GA1UdDgQWBBRYL1NOxxKS45RVVk5g +ALnFUxhBxDAfBgNVHSMEGDAWgBRYL1NOxxKS45RVVk5gALnFUxhBxDAPBgNVHRMB +Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCRQUMrjbal+sK3/GTYY+D8cCrZ +AEm0EGh4ZC1q8SaUG765WasT/upeNLObS3zR2h8ySS5w4ssBI9QY6e1SfCy9yEcF +RjD5RxtR9IwvCAsWblGBL+aQcu5tphwKGm7UpXY294dB/DyEcZ6fuLT8nlPIpGXZ +TNwQOxUCAiVCwrwx9xDpd4YhNsx0+3658a+ytbBefvah9sZb0mMpSoEp3qTYpI7C +xsunxV19LeQkFmLhqrzFPis9/KEhg//0DhHALBXqscdn8kUhBfD9gkqaJDJE04C6 +2Eh0zPnRJSx2JwdtlYQFFIFTZUL3qE00Kbv461OnLRNW22/XjITcTkMjifsv +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/rsa_client.crt b/test/drb/fixtures/rsa_client.crt new file mode 100644 index 0000000..abbea4e --- /dev/null +++ b/test/drb/fixtures/rsa_client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOTCCAiGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MQswCQYDVQQGEwJKUDEO +MAwGA1UECAwFVG9reW8xEDAOBgNVBAoMB0RSYlRlc3QxCzAJBgNVBAMMAkNBMB4X +DTA5MDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowQDELMAkGA1UEBhMCSlAxDjAM +BgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJUZXN0MQ8wDQYDVQQDDAZDbGllbnQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC74d63srK1LXiotAkWdBA2 +lmLENgdZ3rF5SDEY8Y3Kf112Hj5tZyxP4rOrdL296bHzTUgBJIDlK8nuiM9SVooo +VTzRT4dFnnIEM5HVgW9LiJKpa51WlHKgLJ9W/3ba3oW1cdWmE78lghyBob6ruIQ9 +8kBiGru44JAwQcTPNvOopW01O+/jg7E/FCJO58F+ymMgZRumURpxuuoCpV0CrMsk +s1Mkmr1x/RbvYcK7jAiMqVQuo3h0cj0RBGgsm8hA3fC0igOCXDw9bRp6x4TE/2Cs +pGwS0mQsVaZ9pK32z7EcZLgBoMAVsumyELxhKtwwF+pmpiva6KTrnwB+rdKCn9Tp +AgMBAAGjQjBAMB0GA1UdDgQWBBTBzUfuSYOlsgEiEvhxpahBGVsPlDAfBgNVHSME +GDAWgBRYL1NOxxKS45RVVk5gALnFUxhBxDANBgkqhkiG9w0BAQsFAAOCAQEApJue +3OYpoD7AblEvan9VloAauc35kp0/MMix1tbVDVii1rl8DhjPtG4cne3HQqW6+mbf +9fn5oUhgot26yNtLl4yzPJ93uSMNSsWf4Ay4x7CjSc0ElAGin2a+WEc3gnfz48M6 +PFlxwkiINo8KBsiLwrVmTp2M3iXLTU9KleEMLWz7IgRUsjhODvL8v7LpFU8ETntK +k91rfw1g1Q14ZIwOx3300+B+0y8/dwUm2p9Iz20WMmQ2MskR8dLIGl5e6c7uqqks +siUiiuT40qYnHdR6tXddf0ibvwQT2oo75Ods+Rxu4qN806wcujGdwcwJKhr71ajG +pLSmMtU0OaacrHkQdQ== +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/rsa_client.key b/test/drb/fixtures/rsa_client.key new file mode 100644 index 0000000..0626849 --- /dev/null +++ b/test/drb/fixtures/rsa_client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC74d63srK1LXio +tAkWdBA2lmLENgdZ3rF5SDEY8Y3Kf112Hj5tZyxP4rOrdL296bHzTUgBJIDlK8nu +iM9SVoooVTzRT4dFnnIEM5HVgW9LiJKpa51WlHKgLJ9W/3ba3oW1cdWmE78lghyB +ob6ruIQ98kBiGru44JAwQcTPNvOopW01O+/jg7E/FCJO58F+ymMgZRumURpxuuoC +pV0CrMsks1Mkmr1x/RbvYcK7jAiMqVQuo3h0cj0RBGgsm8hA3fC0igOCXDw9bRp6 +x4TE/2CspGwS0mQsVaZ9pK32z7EcZLgBoMAVsumyELxhKtwwF+pmpiva6KTrnwB+ +rdKCn9TpAgMBAAECggEABWI17XnGzPy/fUa4D5yQngkl+DKGeDuH8S5Ro9dAxXRB +WMIJ7rzFrwiotn7Fn28WcjQ9HjVDe+2gNMAsVVMVVI20DK5fSq4n3Q7KPL3fqHXX +zVgqqGwKsyQcMRQTEzdMSbRNl4ZE1FMRCeDj3mFO6W8rNknG+8ee3MHMXStZWjQj +VbpwoDXBXiVthoN0aUZoENQfM70SlWkm9jUXGVlylJ5R2tcifj1oq8xah4mch++V +fwAMlaEoUFT8d2hdcnja/KW86g/0cxJkFl+Mjjc78WaxPkYFCbsGY9TgHdDlgfOC +TzZbJ1j3HG5NjVIBJxaC5zfUAKW9Bh34tkh7D7NDYQKBgQDyu9bEYXJitlgj4vVx +C65xDCSig2rx59RrNfylj/mibokLUZtAuxZHnoA2CLP1LTEdEA++UdhBYlqRrOVc +u6mWrXfftKavToKWvzXRrs2E2MY6F6Di05bWcp+dUcQdQ/hfOj8YbxP0xmbi0Jhr +oBqaHQgrvfFyUUzNz/rBkt+X0QKBgQDGJpaG22K2zJrSV1G88QEFaoGbnE0YAxG3 +Fc+g7d8B2dxgaIs6UgO18Xyjd72tQwfrJ3/7qJs9j5wEdCAiXFis7uw2HtxjnOgP +0ta4z2ePGxDl/4USu7emljxcmzpzXWnqDkexTUqi5Fv6iaVhc8hgcccYDV6S8eKq +PzU0vdvJmQKBgQCigpoOToOLjTNDi37x2XVH4G5ik4O1Q5YW1UU5/0ONuV1tQ4yi +8N7AwmBqTLdXDZOVNpyjuh4D4Hpsj4nb5RRseeUI0+TI99I8ZPX+VX7pU0ybthgT +5L9XAdTVOdoIEeqmrtNxY2TD+1UEw81YOQ+2YHuI9ZlCBSZboMPsd43VEQKBgEN4 +6FDLa3WrfhyZty+LMTnS5odCVc4TXXjmaGj4FrPep3f8oUwemTzfGf3fzCqvZIbi +UGY1J4dy20F4+Wg54cghIzXalFknGK4qsQsFNNI5+SsYMwwJ96M2DR/Li7+001fr +vOXW189XyyoorLPeZSDSHWVHSCjpTLGEDG4FKE4hAoGBANOnTS2Owyyv+B1eLLyv +Wznb+VjyRTaYtsMYwQw0qoo2gULqxIMehDC+rRBRoOiN7JM9tU2WgJEGZ++1WBWi +08sCbpoOBA3tG7MRR7skdD4TFqF0OLIWBAVP02mqWsHY4M1bSPUszryZh6/7sEHO +p2PYPIQ0uXVk07NUZqisBEfE +-----END PRIVATE KEY----- diff --git a/test/drb/fixtures/rsa_server.crt b/test/drb/fixtures/rsa_server.crt new file mode 100644 index 0000000..9e59c1f --- /dev/null +++ b/test/drb/fixtures/rsa_server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUjCCAjqgAwIBAgIBATANBgkqhkiG9w0BAQsFADA8MQswCQYDVQQGEwJKUDEO +MAwGA1UECAwFVG9reW8xEDAOBgNVBAoMB0RSYlRlc3QxCzAJBgNVBAMMAkNBMB4X +DTA5MDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowQzELMAkGA1UEBhMCSlAxDjAM +BgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJUZXN0MRIwEAYDVQQDDAlsb2NhbGhv +c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDxRQYmlsGlGIrBUUzX +glGB9oRkSWy+qbaOZCtKiVuuDO4wS3B+U82I3jin1o+uyFj9+aomFHIiMiQuk1xI +NLTLWPFC9RRGjM+1OLS/+fpQ9C1jZDkjkAYgdvAF5CxPiFCwMCKxvnbPtmDrsU4e +7Q5A6byRpcy3Lum5HC2EOtCzm1sAyaSg0gvayLMD/qYewzkwJ/xwNHRqt9NUhQY5 +ydeHoWqPpkTu0sc79wuXv54IceYT/KLVvC4s0BnwtUx1liNSXxshHFYEYSEvTVJR +sU4AUYmIo6EVHiR1dsqSev5f053fDe5kutEHd0evrwSs3kkWwqWSSGdvUIEgE7Mh +g6GpAgMBAAGjWDBWMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAdBgNVHQ4EFgQUJ+ix ++o0BKly75JACuTJiVBfVfSMwHwYDVR0jBBgwFoAUWC9TTscSkuOUVVZOYAC5xVMY +QcQwDQYJKoZIhvcNAQELBQADggEBAH+f7mbE9puyBNixSjxzQx/Xl7Go6XBYQ3gm +cy/C4rWruj+kkYzqAIjDIP2bDoO/Zk2PuHAukjkkyclzrAg8LPs8UDLkxYmOsV0I +J5T0kp6iXllVKHC3GVHTnFgzeFuqOBHWQiL5YUzCf1WoYKkgCyHVEAsr5o9w/tTv +g757j4FNIBYUbcITJC/ZF4AvMZwyhCuAISaQ8pSqUWmXISsuywrU0YrjobzxGhl1 +C9KLEOFPyZb50x7wLyFzWxWb4vaAfC187LlBy+TET850UnKzkJDhe9jNEN042d7s +msysO0mPtEmNzhq3apDZYheHkVx3NdkrpqtGkGBwU0m2mAflq+U= +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/rsa_server.key b/test/drb/fixtures/rsa_server.key new file mode 100644 index 0000000..414a66c --- /dev/null +++ b/test/drb/fixtures/rsa_server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDxRQYmlsGlGIrB +UUzXglGB9oRkSWy+qbaOZCtKiVuuDO4wS3B+U82I3jin1o+uyFj9+aomFHIiMiQu +k1xINLTLWPFC9RRGjM+1OLS/+fpQ9C1jZDkjkAYgdvAF5CxPiFCwMCKxvnbPtmDr +sU4e7Q5A6byRpcy3Lum5HC2EOtCzm1sAyaSg0gvayLMD/qYewzkwJ/xwNHRqt9NU +hQY5ydeHoWqPpkTu0sc79wuXv54IceYT/KLVvC4s0BnwtUx1liNSXxshHFYEYSEv +TVJRsU4AUYmIo6EVHiR1dsqSev5f053fDe5kutEHd0evrwSs3kkWwqWSSGdvUIEg +E7Mhg6GpAgMBAAECggEAIVgySOwF+EzDhIM5dQFwRV9uHbQeIN2wus4yQ3tnXc8w +riEG+5aWbeeUefHH6taKohM6xkeGHJ7EbGF2XA5YvE/fDCt18WgtnrSnGm8wfra4 +fSeRVA5oIl19v7qwuw8yY59LdDhIEF362CgpjVGi6irDoneBKwIDUE+KJN/CD0hR +HALK5aX1DuBC2+gCchY3p2bijoGxg/5VFhKnGjF5r+7AShqnNfpJZBVFvTLN0XOS +ADIjllC+MV1xT4854bUBcpRFeH5+gLWATc//mzC3eVbbokwQlLKJ3ufen5tl9HfT +2nOaVYGuHVLVM6Zf04ApFo+Bkx2nrKtdCm7f5an3pwKBgQD/Ao31m6ZPM2mnGQyR +X2hffMDwbtGU/IQftRZkc61ZuEoLoCUaeOedE8fU/dO3T9O85GeuKUlPIpb2neVS +SyNTvArhccQhbYQ9QtTqaZ6fDjEFiTacvKP3kIx4cSh0e/vvsFL6XUYb/1xpRTz5 +UArrlNX3Ia8olj1VvsNYaUvuswKBgQDyNNA9vYMNZO2TGV9si+VZxm/opn8mcCus +JlCRf4xgmhDNxsOI31QrLZtBx8rjekyUHVyhyoa59GZQFEqsHfWDRbp37blR9r93 +nzA45fyItAWb8m7X6+mPtM2ssDIXB4gjBHofOjQJNypxBV8qMBkz6TZRsEGpZMD8 +fwHprVqcMwKBgFgVHM3CRq7CtnK2T0YDa3zYDZi+3nuUwVpmZWarIiyEYGclmMtN +CcuS4opqZm/CDgQH7NwWfLDt5LEoluZW98vbfvKiJjnZpzy10e9qLhUIhNxBqfB3 +pDdF4Y9UnsGldb8z62V5RFc1XEksVkRTZoI69bEYHHVrd6Ifc0AdltHLAoGAB1q/ +MAC/J/r2k87jbOJaln1GDKRxm/MwAEwxihl7Y7uJ4xWz/kX5wk3iNv8gFAQ0qxKx +K2CA8siPCsNy+QL334KQhO+8/tYlPjahOjkRj/0XZoLYBsptDyYIUMQQ4U4jPhz2 +sFgOGHGKYmAtYZSQT1k3gwd9Fu2uRnx8zGGtLK0CgYA3a0WqBzIN70t4grPnsGo2 +mGtoteFM4dJH5qskowMgnc0EDcnWe6ftI1Ug7YT9+T4+K2k4JhixL9YjBf3e5jbb +KRRV9n1yGuLm/MzDgg/WIRHTt+9fd/XF+1/+OJdWRvlrJhOgsZfKKhzLvRZ/Fpi4 +J4sKM2oql9L2XDgQ05meIQ== +-----END PRIVATE KEY----- diff --git a/test/drb/test_drbssl.rb b/test/drb/test_drbssl.rb index f2d9a20..4d94827 100644 --- a/test/drb/test_drbssl.rb +++ b/test/drb/test_drbssl.rb @@ -78,6 +78,149 @@ def setup end end +# Test drbssl protocol with auto-generated PQC-supported ML-DSA-65 certificate +# and PQC-supported ML-KEM key exchange (X25519MLKEM768). +class TestDRbSSLPQC < Test::Unit::TestCase + include DRbPQCUtilities + + def setup + omit_unless_support_pqc + + server_config = { + SSLCertName: [['C', 'JP'], ['O', 'Foo.DRuby.Org'], + ['CN', 'Sample']], + SSLPrivateKeyAlgorithms: ['ML-DSA-65'], + SSLGroups: 'X25519MLKEM768', + SSLSignatureAlgorithms: 'mldsa65', + SSLVerifyMode: OpenSSL::SSL::VERIFY_PEER, + SSLVerifyCallback: lambda { |ok, x509_store| + true + } + } + @server = DRb::DRbServer.new('drbssl://localhost:0', nil, + server_config) + + client_config = { + SSLGroups: 'X25519MLKEM768', + SSLSignatureAlgorithms: 'mldsa65', + SSLVerifyMode: OpenSSL::SSL::VERIFY_PEER, + SSLVerifyCallback: lambda { |ok, x509_store| + true + } + } + DRb.start_service(nil, nil, client_config) + end + + def teardown + @server&.stop_service + DRb.stop_service + DRb::DRbConn.stop_pool + end + + def test_group_sigalg + # Test client connection + DRb::DRbConn.open(@server.uri) do |conn| + ssl = conn.instance_variable_get(:@protocol).stream + assert_instance_of(OpenSSL::SSL::SSLSocket, ssl) + assert_equal('X25519MLKEM768', ssl.group) + assert_nil(ssl.sigalg) + assert_equal('mldsa65', ssl.peer_sigalg) + [true, nil] + end + end +end + +# Test drbssl protocol with pre-generated ML-DSA-65 (PQC) and RSA (non-PQC) +# multiple server certificates, PQC-supported ML-KEM key exchange +# (SecP384r1MLKEM1024), and client certificate verification with both ML-DSA-65 +# and RSA signature algorithms. +class TestDRbSSLPQCMultipleCert < Test::Unit::TestCase + include DRbPQCUtilities + + def setup + omit_unless_support_pqc + + store = OpenSSL::X509::Store.new + store.add_cert(Fixtures.read_cert('mldsa65_ca.crt')) + store.add_cert(Fixtures.read_cert('rsa_ca.crt')) + + server_config = { + SSLCertificates: [ + [Fixtures.read_cert('mldsa65_server.crt'), + Fixtures.read_pkey('mldsa65_server.key')], + [Fixtures.read_cert('rsa_server.crt'), + Fixtures.read_pkey('rsa_server.key')] + ], + SSLGroups: 'SecP384r1MLKEM1024', + SSLSignatureAlgorithms: 'mldsa65:rsa_pss_rsae_sha256', + # CA certificates to verify client's certificate (mldsa65_client.crt or + # rsa_client.crt) + SSLCertificateStore: store, + # CA certificate(s) sent to the client indicating which certificates the + # server accepts. Helps the client choose which certificate to present. + SSLClientCA: [ + Fixtures.read_cert('mldsa65_ca.crt'), + Fixtures.read_cert('rsa_ca.crt') + ], + SSLVerifyMode: OpenSSL::SSL::VERIFY_PEER | + OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + } + @server = DRb::DRbServer.new('drbssl://localhost:0', nil, + server_config) + end + + def teardown + @server&.stop_service + DRb.stop_service + DRb::DRbConn.stop_pool + end + + def test_group_sigalg_mldsa65 + client_config = { + SSLCertificate: Fixtures.read_cert('mldsa65_client.crt'), + SSLPrivateKey: Fixtures.read_pkey('mldsa65_client.key'), + SSLGroups: 'SecP384r1MLKEM1024', + SSLSignatureAlgorithms: 'mldsa65', + SSLCACertificateFile: Fixtures.file_path('mldsa65_ca.crt'), + SSLVerifyMode: OpenSSL::SSL::VERIFY_PEER | + OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + } + DRb.start_service(nil, nil, client_config) + + # Test client connection + DRb::DRbConn.open(@server.uri) do |conn| + ssl = conn.instance_variable_get(:@protocol).stream + assert_instance_of(OpenSSL::SSL::SSLSocket, ssl) + assert_equal('SecP384r1MLKEM1024', ssl.group) + assert_equal('mldsa65', ssl.sigalg) + assert_equal('mldsa65', ssl.peer_sigalg) + [true, nil] + end + end + + def test_group_sigalg_rsa + client_config = { + SSLCertificate: Fixtures.read_cert('rsa_client.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_client.key'), + SSLGroups: 'SecP384r1MLKEM1024', + SSLSignatureAlgorithms: 'rsa_pss_rsae_sha256', + SSLCACertificateFile: Fixtures.file_path('rsa_ca.crt'), + SSLVerifyMode: OpenSSL::SSL::VERIFY_PEER | + OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + } + DRb.start_service(nil, nil, client_config) + + # Test client connection + DRb::DRbConn.open(@server.uri) do |conn| + ssl = conn.instance_variable_get(:@protocol).stream + assert_instance_of(OpenSSL::SSL::SSLSocket, ssl) + assert_equal('SecP384r1MLKEM1024', ssl.group) + assert_equal('rsa_pss_rsae_sha256', ssl.sigalg) + assert_equal('rsa_pss_rsae_sha256', ssl.peer_sigalg) + [true, nil] + end + end +end end diff --git a/test/drb/test_ssl.rb b/test/drb/test_ssl.rb new file mode 100644 index 0000000..702e474 --- /dev/null +++ b/test/drb/test_ssl.rb @@ -0,0 +1,361 @@ +# frozen_string_literal: false +require 'test/unit' +require_relative 'drbtest' + +begin + require 'drb/ssl' +rescue LoadError +end + +module DRbTests + +if Object.const_defined?('OpenSSL') + +class TestSSLConfig < Test::Unit::TestCase + include DRbPQCUtilities + + CERT_NAME = [['C', 'JP'], ['O', 'Foo.DRuby.Org'], ['CN', 'localhost']] + + def test_setup_certificate_default + config = { + SSLCertName: CERT_NAME + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::RSA, certs[0][1]) + end + + def test_setup_certificate_rsa + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['RSA'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::RSA, certs[0][1]) + end + + def test_setup_certificate_ml_dsa_44 + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-44'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-44/, certs[0][1].inspect) + end + + def test_setup_certificate_ml_dsa_65 + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-65'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-65/, certs[0][1].inspect) + end + + def test_setup_certificate_ml_dsa_87 + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-87'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-87/, certs[0][1].inspect) + end + + def test_setup_certificate_ml_dsa_65_rsa + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-65', 'RSA'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_equal(2, certs.length) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-65/, certs[0][1].inspect) + assert_instance_of(OpenSSL::X509::Certificate, certs[1][0]) + assert_instance_of(OpenSSL::PKey::RSA, certs[1][1]) + end + + def test_setup_certificate_invalid_algorithm + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['INVALID'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(ArgumentError) do + ssl_conf.setup_certificate + end + assert_equal('INVALID algorithm not found. '\ + 'RSA, ML-DSA-44, ML-DSA-65, and ML-DSA-87 '\ + 'algorithms are supported', + error.message) + end + + def test_setup_certificate_unsupported_mldsa + unless OpenSSL::PKey.respond_to?(:generate_key) + omit 'OpenSSL::PKey.generate_key not available' + end + + orig = OpenSSL::PKey.method(:generate_key) + OpenSSL::PKey.define_singleton_method(:generate_key) do |alg| + raise OpenSSL::PKey::PKeyError, 'algorithm ML-DSA-65 not found' + end + begin + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-65'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(OpenSSL::PKey::PKeyError) do + ssl_conf.setup_certificate + end + assert_equal('algorithm ML-DSA-65 not found', + error.message) + ensure + OpenSSL::PKey.define_singleton_method( + :generate_key, orig) + end + end + + def test_setup_certificate_preserves_existing_cert_and_key + pkey = Fixtures.read_pkey('rsa_server.key') + cert = Fixtures.read_cert('rsa_server.crt') + config = { + SSLCertificate: cert, + SSLPrivateKey: pkey + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_same(cert, certs[0][0]) + assert_same(pkey, certs[0][1]) + end + + def test_setup_ssl_context_sigalgs + ctx_class = OpenSSL::SSL::SSLContext + omit 'sigalgs= not supported' unless ctx_class.method_defined?(:sigalgs=) + + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_sigalgs_pqc + ctx_class = OpenSSL::SSL::SSLContext + omit 'sigalgs= not supported' unless ctx_class.method_defined?(:sigalgs=) + omit_unless_support_pqc + + config = { + SSLCertificates: [ + [Fixtures.read_cert('mldsa65_server.crt'), + Fixtures.read_pkey('mldsa65_server.key')], + [Fixtures.read_cert('rsa_server.crt'), + Fixtures.read_pkey('rsa_server.key')] + ], + SSLSignatureAlgorithms: 'mldsa65:rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_sigalgs_method_not_supported + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:sigalgs=) + omit 'sigalgs= already not supported' + end + + orig = ctx_class.instance_method(:sigalgs=) + ctx_class.undef_method(:sigalgs=) + begin + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(NoMethodError) do + ssl_conf.setup_ssl_context + end + assert_equal("undefined method 'sigalgs=' for "\ + "an instance of OpenSSL::SSL::SSLContext", + error.message) + ensure + ctx_class.define_method(:sigalgs=, orig) + end + end + + def test_setup_ssl_context_client_sigalgs + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:client_sigalgs=) + omit 'client_sigalgs= not supported' + end + + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLClientSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_client_sigalgs_pqc + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:client_sigalgs=) + omit 'client_sigalgs= not supported' + end + omit_unless_support_pqc + + config = { + SSLCertificate: Fixtures.read_cert('mldsa65_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('mldsa65_server.key'), + SSLClientSignatureAlgorithms: 'mldsa44:mldsa65:mldsa87' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_client_sigalgs_not_supported + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:client_sigalgs=) + omit 'client_sigalgs= already not supported' + end + + orig = ctx_class.instance_method(:client_sigalgs=) + ctx_class.undef_method(:client_sigalgs=) + begin + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLClientSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(NoMethodError) do + ssl_conf.setup_ssl_context + end + assert_equal("undefined method 'client_sigalgs=' for "\ + "an instance of OpenSSL::SSL::SSLContext", + error.message) + ensure + ctx_class.define_method(:client_sigalgs=, orig) + end + end + + def test_setup_ssl_context_groups + ctx_class = OpenSSL::SSL::SSLContext + omit 'groups= not supported' unless ctx_class.method_defined?(:groups=) + + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLGroups: 'P-256:P-384' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_groups_pqc + ctx_class = OpenSSL::SSL::SSLContext + omit 'groups= not supported' unless ctx_class.method_defined?(:groups=) + omit_unless_support_pqc + + config = { + SSLCertificate: Fixtures.read_cert('mldsa65_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('mldsa65_server.key'), + SSLGroups: 'X25519MLKEM768' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_groups_not_supported + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:groups=) + omit 'groups= already not supported' + end + + orig = ctx_class.instance_method(:groups=) + ctx_class.undef_method(:groups=) + begin + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLGroups: 'P-256:P-384' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(NoMethodError) do + ssl_conf.setup_ssl_context + end + assert_equal("undefined method 'groups=' for "\ + "an instance of OpenSSL::SSL::SSLContext", + error.message) + ensure + ctx_class.define_method(:groups=, orig) + end + end +end + +end + +end diff --git a/tool/create_certs.rb b/tool/create_certs.rb new file mode 100755 index 0000000..716c4bf --- /dev/null +++ b/tool/create_certs.rb @@ -0,0 +1,84 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# This script creates RSA and ML-DSA-65 SSL/TLS test certificates. +# It requires OpenSSL >= 3.5 for ML-DSA-65 support. + +require 'fileutils' + +TOP_DIR = `git rev-parse --show-toplevel`.chomp +FIXTURES_DIR = File.join(TOP_DIR, 'test', 'drb', 'fixtures') +TMP_DIR = File.join(TOP_DIR, 'tmp', 'create_certs') + +def sh(*cmd) + system(*cmd, exception: true) +end + +def create_certs(genpkey_args, prefix) + dir = File.join(TMP_DIR, prefix) + FileUtils.mkdir_p(dir) + + # CA + sh 'openssl', 'genpkey', *genpkey_args, + '-out', File.join(dir, 'ca.key') + sh 'openssl', 'req', '-x509', + '-key', File.join(dir, 'ca.key'), + '-subj', '/C=JP/ST=Tokyo/O=DRbTest/CN=CA', + '-not_before', '090101000000Z', + '-not_after', '491231235959Z', + '-out', File.join(dir, 'ca.crt') + + # Server + sh 'openssl', 'genpkey', *genpkey_args, + '-out', File.join(dir, 'server.key') + sh 'openssl', 'req', '-new', + '-key', File.join(dir, 'server.key'), + '-subj', '/C=JP/ST=Tokyo/O=DRbTest/CN=localhost', + '-addext', 'subjectAltName=DNS:localhost', + '-out', File.join(dir, 'server.csr') + sh 'openssl', 'x509', '-req', + '-in', File.join(dir, 'server.csr'), + '-CA', File.join(dir, 'ca.crt'), + '-CAkey', File.join(dir, 'ca.key'), + '-set_serial', '1', + '-copy_extensions', 'copyall', + '-not_before', '090101000000Z', + '-not_after', '491231235959Z', + '-out', File.join(dir, 'server.crt') + + # Client + sh 'openssl', 'genpkey', *genpkey_args, + '-out', File.join(dir, 'client.key') + sh 'openssl', 'req', '-new', + '-key', File.join(dir, 'client.key'), + '-subj', '/C=JP/ST=Tokyo/O=DRbTest/CN=Client', + '-out', File.join(dir, 'client.csr') + sh 'openssl', 'x509', '-req', + '-in', File.join(dir, 'client.csr'), + '-CA', File.join(dir, 'ca.crt'), + '-CAkey', File.join(dir, 'ca.key'), + '-set_serial', '2', + '-not_before', '090101000000Z', + '-not_after', '491231235959Z', + '-out', File.join(dir, 'client.crt') + + FileUtils.mkdir_p(FIXTURES_DIR) + FileUtils.cp(File.join(dir, 'ca.crt'), + File.join(FIXTURES_DIR, "#{prefix}_ca.crt")) + FileUtils.cp(File.join(dir, 'server.crt'), + File.join(FIXTURES_DIR, "#{prefix}_server.crt")) + FileUtils.cp(File.join(dir, 'server.key'), + File.join(FIXTURES_DIR, "#{prefix}_server.key")) + FileUtils.cp(File.join(dir, 'client.crt'), + File.join(FIXTURES_DIR, "#{prefix}_client.crt")) + FileUtils.cp(File.join(dir, 'client.key'), + File.join(FIXTURES_DIR, "#{prefix}_client.key")) +end + +FileUtils.rm_rf(TMP_DIR) + +# RSA +create_certs(['-algorithm', 'rsa', '-pkeyopt', 'rsa_keygen_bits:2048'], 'rsa') + +# ML-DSA-65 +create_certs(['-algorithm', 'mldsa65'], 'mldsa65')