Description
Summary and motivation
I am considering contributing unit-tests to test post-quantum cryptography (PQC) [1] cases in this repository. In my understanding, the PQC is a kind of enhanced crypto which people can use safely in the age of the quantum computing which is more powerful computer than the current computing. I would cite the [1]'s Background section below. That means the practical use of quantum computers which break the current cryptography may come after 20 years. However, I think it's better to prepare for that from now according to the document in the section.
Some engineers even predict that within the next twenty or so years sufficiently large quantum computers will be built to break essentially all public key schemes currently in use. Historically, it has taken almost two decades to deploy our modern public key cryptography infrastructure. Therefore, regardless of whether we can estimate the exact time of the arrival of the quantum computing era, we must begin now to prepare our information security systems to be able to resist quantum computing.
One of the approved cryptographies for the PQC is ML-DSA (FIPS 204)[2]. So, my plan is to contribute one unit test case to the test/openssl/test_ssl.rb
, running TLS dual certificates server with ML-DSA (PQC supported) and RSA (PQC not supported) using the test/openssl/utils.rb#start_server
, then the 1st client with ML-DSA certificate connects to the server, then 2nd client with RSA certificate connects to the server. Both clients use the test/openssl/test_ssl.rb#server_connect
. Both client connections should succeed because the TLS server has the dual certificates. Note that the [3] is a Red Hat's document about PQC. I referred to the document to select the test case and understand the implementation using the openssl s_server
and openssl s_client
.
Proof of Concept
I created a proof-of-concept using the Bash and Ruby scripts.[4] I tested the scripts with the current latest openssl/openssl master branch.
Let me explain the scripts in [4].
The following command in a Bash script is to run the TLS server with dual certificates, ML-DSA and RSA.
$ /path/to/openssl s_server \
-cert localhost-mldsa.crt -key localhost-mldsa.key \
-dcert localhost-rsa.crt -dkey localhost-rsa.key
And the following command in a Bash script is to connect to the server the ML-DSA certificate. And I see the expected result.
$ /path/to/openssl s_client \
-connect localhost:4433 \
-CAfile localhost-mldsa.crt </dev/null
...
Peer signature type: mldsa65
Negotiated TLS1.3 group: X25519MLKEM768
...
And the following command in a Bash script is to connect to the server the RSA certificate. And I see the expected result.
$ /path/to/openssl s_client \
-connect localhost:4433 \
-CAfile localhost-rsa.crt \
-sigalgs 'rsa_pss_pss_sha256:rsa_pss_rsae_sha256' </dev/null
...
Peer signing digest: SHA256
Peer signature type: rsa_pss_rsae_sha256
Negotiated TLS1.3 group: X25519MLKEM768
...
And I want to implement the TLS server and client implemented in Ruby that behave the same as the Bash scripts above. The file start-dual-cert-server.rb
is for the TLS server. I confirmed the script behaves as the above openssl s_server
. And the script connect.rb
is for the TLS client with ML-DSA or RSA certificate.
Questions
So, here are 2 questions.
First. How to get the following header values that openssl s_client
outputs, in a Ruby TLS client script?
Peer signing digest:
Peer signature type:
Negotiated TLS1.3 group:
Second, on the [4], the TLS server implemented in Ruby behaves as expected. However, the TLS client connecting with an RSA certificate behaves differently in the following output from the openssl s_server
between the Bash and Ruby scripts. I am looking for a way for the Ruby TLS client to behave the same as the Bash script. Do you know how to do it?
Below is the output from the openssl s_server
when connecting from a TLS client with an RSA certificate implemented in Bash (./pqc.sh connect-rsa
= openssl s_client
).
Shared ciphers:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA
Signature Algorithms: rsa_pss_pss_sha256:RSA-PSS+SHA256
Shared Signature Algorithms: rsa_pss_pss_sha256:RSA-PSS+SHA256
Supported groups: X25519MLKEM768:x25519:secp256r1:x448:secp384r1:secp521r1:ffdhe2048:ffdhe3072
Shared groups: X25519MLKEM768:x25519:secp256r1:x448:secp384r1:secp521r1:ffdhe2048:ffdhe3072
Below is the output from the openssl s_server
when connecting from a TLS client with RSA certifiate implmented in Ruby (ruby -I/path/to/ruby/openssl/lib connect.rb rsa
).
Shared ciphers:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA
Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Shared Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Supported groups: x25519:secp256r1:x448:secp521r1:secp384r1:ffdhe2048:ffdhe3072:ffdhe4096:ffdhe6144:ffdhe8192
Shared groups: x25519:secp256r1:x448:secp521r1:secp384r1:ffdhe2048:ffdhe3072
What do you think?
Tasks (added this section later)
Below are the tasks to complete this issue ticket.
- Add the
SSLContext#sigalgs=
: ssl: add SSLContext#sigalgs= and #client_sigalgs= #895 - Rename the
SSLContext#ecdh_curves=
to#groups=
: ssl: renameSSLContext#ecdh_curves=
to#groups=
#900 - Support provider-only pkeys (reported at this comment): pkey: add support for OpenSSL 3 provider-only pkeys #898
- Add features to get the following data from a TLS client
- Peer signing digest
- Peer signature type
- Negotiated TLS1.3 group
- Add PQC unit tests