Skip to content

Commit

Permalink
Support signing requests using Ed25519
Browse files Browse the repository at this point in the history
Allow requests to be signed using Ed25519 private keys by passing a nil digest.
This is similar to commit b0fc100 when signing certs.

Calling PKey#public_key is deprecated and does not work for Ed25519. The same
can be accomplished by passing the private key.
  • Loading branch information
joshcooper committed Nov 19, 2024
1 parent f1db5c8 commit d960903
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 6 deletions.
6 changes: 5 additions & 1 deletion ext/openssl/ossl_x509req.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
25 changes: 20 additions & 5 deletions test/openssl/test_x509req.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ def issue_csr(ver, dn, key, digest)
req = OpenSSL::X509::Request.new
req.version = ver
req.subject = dn
req.public_key = key.public_key
req.public_key = key
req.sign(key, digest)
req
end

def test_public_key
req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der)
assert_equal(@rsa1024.public_to_der, req.public_key.public_to_der)
req = OpenSSL::X509::Request.new(req.to_der)
assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der)
assert_equal(@rsa1024.public_to_der, req.public_key.public_to_der)

req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256'))
assert_equal(@dsa512.public_key.to_der, req.public_key.to_der)
assert_equal(@dsa512.public_to_der, req.public_key.public_to_der)
req = OpenSSL::X509::Request.new(req.to_der)
assert_equal(@dsa512.public_key.to_der, req.public_key.to_der)
assert_equal(@dsa512.public_to_der, req.public_key.public_to_der)
end

def test_version
Expand Down Expand Up @@ -132,6 +132,21 @@ def test_sign_and_verify_dsa_md5
issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('MD5')) }
end

def test_sign_and_verify_ed25519
# Ed25519 is not FIPS-approved.
omit_on_fips
# See ASN1_item_sign_ctx in ChangeLog for 3.8.1: https://github.com/libressl/portable/blob/master/ChangeLog
omit "Ed25519 not supported" unless openssl?(1, 1, 1) || libressl?(3, 8, 1)
ed25519 = OpenSSL::PKey::generate_key("ED25519")
req = issue_csr(0, @dn, ed25519, nil)
assert_equal(false, request_error_returns_false { req.verify(@rsa1024) })
assert_equal(false, request_error_returns_false { req.verify(@rsa2048) })
assert_equal(false, req.verify(OpenSSL::PKey::generate_key("ED25519")))
assert_equal(true, req.verify(ed25519))
req.public_key = @rsa1024.public_key
assert_equal(false, 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)
Expand Down

0 comments on commit d960903

Please sign in to comment.