Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support signing requests and CRLs using ED25519 #804

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ext/openssl/ossl_x509crl.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,11 @@ ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest)

GetX509CRL(self, crl);
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_CRL_sign(crl, pkey, md)) {
ossl_raise(eX509CRLError, NULL);
}
Expand Down
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
12 changes: 3 additions & 9 deletions test/openssl/test_pkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def test_hmac_sign_verify
def test_ed25519
# Ed25519 is not FIPS-approved.
omit_on_fips
omit "Ed25519 not supported" unless openssl?(1, 1, 1) || libressl?(3, 8, 1)

# Test vector from RFC 8032 Section 7.1 TEST 2
priv_pem = <<~EOF
Expand All @@ -102,15 +103,8 @@ def test_ed25519
MCowBQYDK2VwAyEAPUAXw+hDiVqStwqnTRt+vJyYLM8uxJaMwM1V8Sr0Zgw=
-----END PUBLIC KEY-----
EOF
begin
priv = OpenSSL::PKey.read(priv_pem)
pub = OpenSSL::PKey.read(pub_pem)
rescue OpenSSL::PKey::PKeyError => e
# OpenSSL < 1.1.1
pend "Ed25519 is not implemented" unless openssl?(1, 1, 1)

raise e
end
priv = OpenSSL::PKey.read(priv_pem)
pub = OpenSSL::PKey.read(pub_pem)
assert_instance_of OpenSSL::PKey::PKey, priv
assert_instance_of OpenSSL::PKey::PKey, pub
assert_equal priv_pem, priv.private_to_pem
Expand Down
19 changes: 2 additions & 17 deletions test/openssl/test_x509cert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,24 +223,9 @@ def test_sign_and_verify_dsa_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)

omit "Ed25519 not supported" unless openssl?(1, 1, 1) || libressl?(3, 8, 1)
ed25519 = OpenSSL::PKey::generate_key("ED25519")
cert = issue_cert(@ca, ed25519, 1, [], nil, nil, digest: nil)
assert_equal(true, cert.verify(ed25519))
end
Expand Down
15 changes: 15 additions & 0 deletions test/openssl/test_x509crl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,21 @@ def test_sign_and_verify
assert_equal(false, crl.verify(@dsa512))
end

def test_sign_and_verify_ed25519
omit_on_fips
omit "Ed25519 not supported" unless openssl?(1, 1, 1) || libressl?(3, 8, 1)
ed25519 = OpenSSL::PKey::generate_key("ED25519")
cert = issue_cert(@ca, ed25519, 1, [], nil, nil, digest: nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
cert, ed25519, nil)
assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) })
assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) })
assert_equal(false, crl.verify(OpenSSL::PKey::generate_key("ED25519")))
assert_equal(true, crl.verify(ed25519))
crl.version = 0
assert_equal(false, crl.verify(ed25519))
end

def test_revoked_to_der
# revokedCertificates SEQUENCE OF SEQUENCE {
# userCertificate CertificateSerialNumber,
Expand Down
24 changes: 19 additions & 5 deletions test/openssl/test_x509req.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,26 @@ def setup
@dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou")
end


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.to_der, req.public_key.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.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.to_der, req.public_key.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.to_der)
end

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

def test_sign_and_verify_ed25519
omit_on_fips
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
Loading