0
votes

I'm getting certificate verification errors from a simple SSLSocket (Java 8 u45) connection to a site with a valid certificate and domain.

    String hostName = "www.velocityfrequentflyer.com";
    SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
    SSLSocket sslsocket = (SSLSocket) factory.createSocket(hostName, 443);
    SSLSession session = sslsocket.getSession();
    java.security.cert.Certificate certicates[] = session.getPeerCertificates();
    X509Certificate cert = (X509Certificate) certicates[0];  //the peer certificate
    System.out.println("cert.getIssuerDN().getName(): " + cert.getIssuerDN().getName());
    System.out.println("cert.getSubjectDN().getName(): " + cert.getSubjectDN().getName());

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:431) at sslconnecting.Sslconnecting.main(Sslconnecting.java:33)

Looking at the certificate with OpenSSL everthing seems to be in order including the www. prefix and every browser I have tried this site on is happy with the certificate.

openssl s_client -showcerts -connect www.velocityfrequentflyer.com:443 | openssl x509 -noout -text | less

X509v3 extensions: X509v3 Subject Alternative Name: DNS:www.velocityfrequentflyer.com

Interestingly this works if I change the host to velocityfrequentflyer.com which has me really stumped.

Is there a way to call getPeerCertificates without JAVA doing checks?

I have tried using a TrustAll SocketFactory with the same result.

Edit 1:

After adding startHandshake() it seems its the handshake itself that is failing: ( Full SSL Debug: http://pastebin.com/ZKnjrGPR )

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at sun.security.ssl.Alerts.getSSLException(Unknown Source) at sun.security.ssl.Alerts.getSSLException(Unknown Source) at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source) at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) at sslconnecting.Sslconnecting.main(Sslconnecting.java:33)

Edit 2.

Turns out the site requires insecure cipher suite RC4? The java.security configuration is set to not use them.

jdk.tls.disabledAlgorithms=SSLv3,RC4

However as soon as RC4 is allowed the handshake completes. It still doesn't explain why the handshake goes through without the www. prefix.

1
Curious. Try calling startHandshake() before getSession(). It shouldn't make any difference, but ...user207421
Thanks for the suggestion, its given me some more paths to trace.AlbertoK

1 Answers

0
votes

Again very odd.

If the handshake fails, I would have expected getSession() to have thrown the same exception, as it calls startHandshake() if necessary AFAIK.

It looks like that peer doesn't speak TLSv1.2 or possibly wants RC4.

I suggest you get the peer certificate via a HandshakeCompletionListener rather than the way you're doing it now. That way what will fail is the first I/O on the socket, rather than getPeerCertificate(). In the listener you can close the socket if you don't like the peer certificate.