Skip to content

Commit

Permalink
[fix] OpenSSL::X509::Request#verify with DSA public key
Browse files Browse the repository at this point in the history
this was a regression introduced in JOSSL 0.14.4
  • Loading branch information
kares committed Apr 12, 2024
1 parent ceeacba commit 968bff9
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 8 deletions.
28 changes: 20 additions & 8 deletions src/main/java/org/jruby/ext/openssl/impl/PKCS10Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,15 @@
import java.security.spec.InvalidKeySpecException;
import java.util.Enumeration;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.pkcs.CertificationRequestInfo;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.operator.DefaultAlgorithmNameFinder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
Expand Down Expand Up @@ -212,15 +213,26 @@ private String getPublicKeyAlgorithm() {
throw new IllegalStateException("no public key info");
}

final AlgorithmIdentifier algId = publicKeyInfo.getAlgorithm();
// NOTE: BC's DefaultAlgorithmNameFinder does not handle the EC oid
if (X9ObjectIdentifiers.id_ecPublicKey.equals(algId.getAlgorithm())) {
assert publicKeyInfo.getAlgorithm() != null : "null algorithm for public key info: " + publicKeyInfo;
final ASN1ObjectIdentifier algOID = publicKeyInfo.getAlgorithm().getAlgorithm();
assert algOID != null;

if (PKCSObjectIdentifiers.rsaEncryption.getId().equals(algOID.getId())) {
return "RSA";
}
if (X9ObjectIdentifiers.id_ecPublicKey.getId().equals(algOID.getId())) {
return "ECDSA";
}
// e.g. PKCSObjectIdentifiers.rsaEncryption -> "RSA"
final String algName = new DefaultAlgorithmNameFinder().getAlgorithmName(algId);
assert algId.getAlgorithm().getId() != algName : "could not resolve name for oid: " + algId.getAlgorithm();
return algName;
if (X9ObjectIdentifiers.id_dsa.getId().equals(algOID.getId())) {
return "DSA";
}

// final String algName = new DefaultAlgorithmNameFinder().getAlgorithmName(algId);
// assert algId.getAlgorithm().getId() != algName : "could not resolve name for oid: " + algId.getAlgorithm();
// return algName;

assert false : "unexpected public key algorithm oid: " + algOID.getId();
return null;
}

public PublicKey generatePublicKey() throws NoSuchAlgorithmException,
Expand Down
8 changes: 8 additions & 0 deletions src/test/ruby/fixtures/pkey/dsa256
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN DSA PRIVATE KEY-----
MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE
9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed
AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM
3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT
b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn
ISNX5cMzFHRW3Q==
-----END DSA PRIVATE KEY-----
70 changes: 70 additions & 0 deletions src/test/ruby/x509/test_x509req.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,59 @@

class TestX509Request < TestCase

def setup!
@rsa1024 = Fixtures.pkey("rsa1024")
@rsa2048 = Fixtures.pkey("rsa2048")
@dsa256 = Fixtures.pkey("dsa256")
@dsa512 = Fixtures.pkey("dsa512")
@dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou")
end
private :setup!

def test_public_key; setup!
req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
assert_equal(@rsa1024.public_key.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)

req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256'))
assert_equal(@dsa512.public_key.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)
end

def test_sign_and_verify_rsa_sha1; setup!
req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(true, req.verify(@rsa1024))
assert_equal(false, req.verify(@rsa2048))
assert_equal(false, request_error_returns_false { req.verify(@dsa256) })
assert_equal(false, request_error_returns_false { req.verify(@dsa512) })
# req.version = 1
# assert_equal(false, req.verify(@rsa1024))
#rescue OpenSSL::X509::RequestError # RHEL 9 disables SHA1
end

def test_sign_and_verify_rsa_md5; setup!
req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest.new('MD5'))
assert_equal(false, req.verify(@rsa1024))
assert_equal(true, req.verify(@rsa2048))
assert_equal(false, request_error_returns_false { req.verify(@dsa256) })
assert_equal(false, request_error_returns_false { req.verify(@dsa512) })
req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBar")
assert_equal(false, req.verify(@rsa2048))
#rescue OpenSSL::X509::RequestError # RHEL7 disables MD5
end

def test_sign_and_verify_dsa; setup!
req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256'))
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(@dsa256))
assert_equal(true, req.verify(@dsa512))
req.public_key = @rsa1024.public_key
assert_equal(false, req.verify(@dsa512))
end

def test_csr_request_extensions
key = OpenSSL::PKey::RSA.new(512)
csr = OpenSSL::X509::Request.new
Expand Down Expand Up @@ -77,6 +130,23 @@ def test_to_der_new_from_der; require 'base64'
OpenSSL::X509::Request.new(decoded) #=> OpenSSL::X509::RequestError: invalid certificate request data
end

private

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.sign(key, digest)
req
end

def request_error_returns_false
yield
rescue OpenSSL::X509::RequestError
false
end

TEST_KEY_RSA1024 = <<-_end_of_pem_
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx
Expand Down

0 comments on commit 968bff9

Please sign in to comment.