From 95531e042c07d863ce9340ee2304bd7cf2f673f6 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Tue, 8 Oct 2024 11:52:11 -0700 Subject: [PATCH] Support signing requests using ED25519 Allow requests to be signed using ED25519 private keys by passing a nil digest. This is similar to commit f463f5620583a927653772ae7cee95736a963a55 when signing certs. Note ED25519 keys do not implement the same `public_key` method, so the test must special case based on oid. --- ext/openssl/ossl_x509req.c | 6 +++++- test/openssl/test_x509req.rb | 29 ++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c index 37ba03728..4a4d3f286 100644 --- a/ext/openssl/ossl_x509req.c +++ b/ext/openssl/ossl_x509req.c @@ -312,7 +312,11 @@ ossl_x509req_sign(VALUE self, VALUE key, VALUE digest) GetX509Req(self, req); pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = ossl_evp_get_digestbyname(digest); + if (NIL_P(digest)) { + md = NULL; /* needed for some key types, e.g. Ed25519 */ + } else { + md = ossl_evp_get_digestbyname(digest); + } if (!X509_REQ_sign(req, pkey, md)) { ossl_raise(eX509ReqError, NULL); } diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb index b98754b8c..89f348907 100644 --- a/test/openssl/test_x509req.rb +++ b/test/openssl/test_x509req.rb @@ -17,7 +17,11 @@ def issue_csr(ver, dn, key, digest) req = OpenSSL::X509::Request.new req.version = ver req.subject = dn - req.public_key = key.public_key + if key.oid == "ED25519" + req.public_key = key + else + req.public_key = key.public_key + end req.sign(key, digest) req end @@ -132,6 +136,29 @@ def test_sign_and_verify_dsa_md5 issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('MD5')) } end + def test_sign_and_verify_ed25519 + # See test_ed25519 in test_pkey.rb + + # Ed25519 is not FIPS-approved. + omit_on_fips + + begin + ed25519 = OpenSSL::PKey::generate_key("ED25519") + rescue OpenSSL::PKey::PKeyError => e + # OpenSSL < 1.1.1 + # + pend "Ed25519 is not implemented" unless openssl?(1, 1, 1) + + raise e + end + + # See ASN1_item_sign_ctx in ChangeLog for 3.8.1: https://github.com/libressl/portable/blob/master/ChangeLog + pend 'ASN1 signing with Ed25519 not yet working' unless openssl? or libressl?(3, 8, 1) + + req = issue_csr(0, @dn, ed25519, nil) + assert_equal(true, req.verify(ed25519)) + end + def test_dup req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) assert_equal(req.to_der, req.dup.to_der)