On 0.19.3, a TLS server with an EC certificate fails every handshake; RSA works. 0.16.2 works with both.
require "openssl"
require "socket"
key = ARGV[0] == "rsa" ? OpenSSL::PKey::RSA.new(2048) : OpenSSL::PKey::EC.generate("prime256v1")
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = 1
cert.subject = cert.issuer = OpenSSL::X509::Name.parse("/CN=localhost")
cert.public_key = key
cert.not_before = Time.now - 60
cert.not_after = Time.now + 3600
cert.sign(key, "SHA256")
ctx = OpenSSL::SSL::SSLContext.new(:TLSv1_2)
ctx.cert = cert
ctx.key = key
server = OpenSSL::SSL::SSLServer.new(TCPServer.new("127.0.0.1", 0), ctx)
Thread.new { c = server.accept; c.puts(c.gets); c.close }
client = OpenSSL::SSL::SSLSocket.new(TCPSocket.new("127.0.0.1", server.to_io.addr[1]),
OpenSSL::SSL::SSLContext.new(:TLSv1_2))
client.connect
client.puts("ping")
client.gets
puts "OK #{client.ssl_version}"
jruby repro.rb rsa prints OK TLSv1.2; jruby repro.rb ec fails (JRuby 9.4.15.0, OpenJDK 21):
OpenSSL::SSL::SSLError: org.bouncycastle.tls.TlsFatalAlert: handshake_failure(40); [server #2 @…] found no selectable cipher suite among …
OpenSSL::SSL::SSLError: Socket closed
The same happens with TLS 1.3 and with P-384 keys.
Cause: 0.19 prefers BCJSSE (SecurityHelper.java#L556-L569). KeyManagerImpl.chooseAlias requires an exact key-type match (SSLContext.java#L1242-L1252), but BCJSSE asks for ECDHE_ECDSA (TLS 1.2) or EC/secp256r1 etc. (TLS 1.3), never plain EC, so no credential is found.
Normalising the key type in chooseAlias (strip /<group> and check the key's curve matches it; map ECDHE_ECDSA to EC, ECDHE_RSA/DHE_RSA to RSA, DHE_DSS to DSA) fixed it in a local build of 0.19.3 for P-256 and P-384 on TLS 1.2 and 1.3.
On 0.19.3, a TLS server with an EC certificate fails every handshake; RSA works. 0.16.2 works with both.
jruby repro.rb rsaprintsOK TLSv1.2;jruby repro.rb ecfails (JRuby 9.4.15.0, OpenJDK 21):The same happens with TLS 1.3 and with P-384 keys.
Cause: 0.19 prefers BCJSSE (SecurityHelper.java#L556-L569).
KeyManagerImpl.chooseAliasrequires an exact key-type match (SSLContext.java#L1242-L1252), but BCJSSE asks forECDHE_ECDSA(TLS 1.2) orEC/secp256r1etc. (TLS 1.3), never plainEC, so no credential is found.Normalising the key type in
chooseAlias(strip/<group>and check the key's curve matches it; mapECDHE_ECDSAtoEC,ECDHE_RSA/DHE_RSAtoRSA,DHE_DSStoDSA) fixed it in a local build of 0.19.3 for P-256 and P-384 on TLS 1.2 and 1.3.