ssljava-11adoptopenjdk

Since OpenJDk Java 11 getting javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure


Have recently updated application from Oracle Java 9 to AdoptJDk 11.0.6 and I am now seeing errors of the form this code:

 public static String convertWikidataUrl(String wikidataUrl)
    {
        String qPage  = wikidataUrl.substring(wikidataUrl.lastIndexOf('/') + 1);
        String apiUrl = WIKIDATA_IMAGE_API_URL + qPage;
        try
        {
            URL url = new URL(apiUrl);
            HttpURLConnection uc = (HttpURLConnection) url.openConnection();
            int responseCode = uc.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK)
            {
                MainWindow.logger.severe(":ResponseCode:"+responseCode);

            }

            //Everything ok so continue
            BufferedInputStream bis = new BufferedInputStream(uc.getInputStream());
            JAXBContext jc = getWikidataInitialContext();
            Unmarshaller um = jc.createUnmarshaller();
            Api api = (Api) um.unmarshal(bis);
            if(api.getClaims()!=null
                    && api.getClaims().getProperty()!=null
                    && api.getClaims().getProperty().getClaim()!=null
                    && api.getClaims().getProperty().getClaim().getMainsnak()!=null
                    && api.getClaims().getProperty().getClaim().getMainsnak().getDatavalue()!=null)
            {
                return api.getClaims().getProperty().getClaim().getMainsnak().getDatavalue().getValue();
            }
            else
            {
                return null;
            }
        }
        catch (JAXBException e)
        {
            MainWindow.logger.log(Level.SEVERE, e.getMessage(), e);
        }
        catch (MalformedURLException mue)
        {
            MainWindow.logger.log(Level.SEVERE, mue.getMessage(), mue);
        }
        catch (Exception ex)
        {
            MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
        }
        return null;
    }

fails with:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:307)
    at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:291)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:180)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1151)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1062)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
    at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567)
    at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
    at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1515)
    at java.base/java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:527)
    at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:334)
    at com.jthink.songkong.analyse.musicbrainz.WikipediaImage.convertWikipediaUrl(WikipediaImage.java:49)
    at com.jthink.songkong.analyse.musicbrainz.ArtistArtwork.findArtistImageLink(ArtistArtwork.java:54)
    at com.jthink.songkong.analyse.musicbrainz.ArtistArtworkOnlineLookup.call(ArtistArtworkOnlineLookup.java:63)
    at com.jthink.songkong.analyse.musicbrainz.ArtistArtworkOnlineLookup.call(ArtistArtworkOnlineLookup.java:26)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)

The problem has been seen on Windows but may occur on other platforms as well

The error is definitently due to changing JRE but I don't know if the issue is moving from Java 9 to 11, or moving from Oracle to AdoptJdk, how can I resolve this ?

Update

  1. The problem does not occur on MacOS using 11.0.6
  2. On Windows Updating from 11.0.6 to 11.0.7 had no effect
  3. On Windows adding -Dhttps.protocols=TLSv1.1,TLSv1.2 (to disabled TLS1.3 support) fixes the issue.
  4. Possibly version of this bug https://bugs.openjdk.java.net/browse/JDK-8206923

Solution

  • The client can't open a connection to the server because they likely don't support the same TLS versions or settings.

    Try to start the application with:

    TLSv1.2 (2008) is the currently supported version of TLS that is deployed everywhere and supported by everything. That's the safe default and what to force for things to just work.

    TLSv1.3 (2018) is the upcoming version. It's being rolled across everywhere slowly (web servers, applications, load balancers, CDN, etc...). The transition should be seamless but it's not quite. Of course no software can be perfect on the first try and there are some bugs and incompatibilities coming up. The JDK 11 introduces TLSv1.3 and tries to use it by default, which didn't go well given the error, the workaround is to force using TLSv1.2 instead. (update for 2021: TLS 1.3 has been adopted by browsers and major middleware over the past year or two, it's quite likely to come up when you upgrade software/infrastructure)

    There are tricky edge cases if you rely on TLS for client certificate authentication, often used in enterprise systems dealing with highly sensitive information, like banking APIs. TLS 1.3 changed the way client authentication happens, so both client and server software may need a fix to be able to operate under the newer version. HTTP/2 breaks client authentication by design, a RFC is pending to agree on a solution, in the meantime use HTTP/1.1.

    TLSv1.0 (1999) is an obsolete version that is prohibited from usage and removed in latest library versions (OpenSSL 1.1.x, JDK 11, etc...). It's still possible to encounter it as of 2020 if you work around legacy enterprise java apps that ain't been maintained for years (anything involving Java 6 or 7 is a red flag). These really need to be upgraded.