Question

I am playing with SSL in Java for the first time, trying to create an echo server. I have managed to get it working when only the server needs to authenticate, with (after setting the properties to point to the appropriate KeyStore and TrustStore):

Server side:

    SSLServerSocketFactory serverSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
    SSLServerSocket serverSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(bancoPort);
    String [] supported = serverSocketFactory.getSupportedCipherSuites();
    serverSocket.setEnabledCipherSuites(supported);
    serverSocket.setEnabledProtocols(new String[]{"TLSv1"});
    SSLSocket s = (SSLSocket) serverSocket.accept();

Client side:

SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket bancoSocket = (SSLSocket) socketFactory.createSocket(bancoIP, bancoPort);
String[] suites = bancoSocket.getSupportedCipherSuites();
bancoSocket.setEnabledCipherSuites(suites);

Thanks to the debug mode I know the cipher suite used for authentication is TLS_ECDH_anon_WITH_AES_128_CBC_SHA:

main, READ: TLSv1 Handshake, length = 215
*** ClientHello, TLSv1
RandomCookie:  GMT: 1399451465 bytes = { 177, 86, 70, 228, 7, 0, 109, 56, 245, 8, 243, 18, 122, 186, 159, 138, 76, 99, 65, 224, 21, 100, 1, 90, 20, 109, 241, 216 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_ECDH_anon_WITH_RC4_128_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_RSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_anon_WITH_NULL_SHA, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
%% Initialized:  [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Negotiating:  [Session-1, TLS_ECDH_anon_WITH_AES_128_CBC_SHA]
*** ServerHello, TLSv1
RandomCookie:  GMT: 1399451466 bytes = { 252, 63, 206, 222, 115, 40, 143, 4, 55, 11, 88, 196, 5, 10, 114, 159, 76, 144, 181, 27, 73, 248, 196, 71, 169, 136, 228, 82 }
Session ID:  {83, 106, 239, 74, 65, 85, 23, 110, 97, 151, 196, 61, 224, 79, 140, 15, 11, 132, 208, 66, 112, 216, 122, 85, 27, 159, 194, 255, 104, 171, 81, 220}
Cipher Suite: TLS_ECDH_anon_WITH_AES_128_CBC_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
Cipher suite:  TLS_ECDH_anon_WITH_AES_128_CBC_SHA

If I add to the server code the line

serverSocket.setNeedClientAuth(true);

everything breaks down. The suite then used is TLS_KRB5_WITH_RC4_128_MD5, but the client is not apparently prepared to use Kerberos, since this is the error that pops up in the client when the first message to be echoed is sent:

may 08, 2014 3:31:30 AM echoclient.EchoClientSSL main
Grave: null
java.io.IOException: Invalid service principal name: host/desk-linux
    at sun.security.ssl.krb5.KerberosClientKeyExchangeImpl.getServiceTicket(KerberosClientKeyExchangeImpl.java:307)
    at sun.security.ssl.krb5.KerberosClientKeyExchangeImpl.init(KerberosClientKeyExchangeImpl.java:112)
    at sun.security.ssl.KerberosClientKeyExchange.init(KerberosClientKeyExchange.java:122)
    at sun.security.ssl.KerberosClientKeyExchange.<init>(KerberosClientKeyExchange.java:80)
    at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:873)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:285)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
    at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
    at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
    at java.io.DataOutputStream.write(DataOutputStream.java:107)
    at java.io.DataOutputStream.writeUTF(DataOutputStream.java:401)
    at java.io.DataOutputStream.writeUTF(DataOutputStream.java:323)
    at echoclient.EchoClientSSL.main(EchoClientSSL.java:45)
Caused by: KrbException: Cannot locate default realm
    at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:367)
    at sun.security.ssl.krb5.KerberosClientKeyExchangeImpl.getServiceTicket(KerberosClientKeyExchangeImpl.java:302)
    ... 15 more
Caused by: KrbException: Cannot locate default realm
    at sun.security.krb5.Config.getDefaultRealm(Config.java:1181)
    at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:365)
    ... 16 more
Caused by: KrbException: Generic error (description in e-text) (60) - Unable to locate Kerberos realm
    at sun.security.krb5.Config.getRealmFromDNS(Config.java:1277)
    at sun.security.krb5.Config.getDefaultRealm(Config.java:1162)
    ... 17 more

I have tried to setEnabledCipherSuites in the client to just the one I know that works (TLS_ECDH_anon_WITH_AES_128_CBC_SHA) instead of the whole allowed cipher suite, but if I do that I get the exception at the server "javax.net.ssl.SSLHandshakeException: no cipher suites in common". Log:

main, READ: TLSv1 Handshake, length = 114
*** ClientHello, TLSv1
RandomCookie:  GMT: 1399451199 bytes = { 43, 248, 163, 155, 250, 241, 124, 194, 33, 46, 197, 27, 122, 1, 148, 254, 255, 71, 219, 220, 213, 91, 180, 178, 126, 242, 166, 82 }
Session ID:  {}
Cipher Suites: [TLS_ECDH_anon_WITH_AES_128_CBC_SHA]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Initialized:  [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Invalidated:  [Session-1, SSL_NULL_WITH_NULL_NULL]
main, SEND TLSv1 ALERT:  fatal, description = handshake_failure
main, WRITE: TLSv1 Alert, length = 2
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: no cipher suites in common
may 08, 2014 3:38:56 AM echoserver.EchoServerSSL main
Grave: null
javax.net.ssl.SSLHandshakeException: no cipher suites in common

Both server and client are running on the same machine, so I don't get how a cipher suite that works to authenticate the server fails when trying to authenticate the client.

Was it helpful?

Solution 2

As @EJP said, those lines were counter-productive and needed to be removed. The problem was not in the code but on how the certificates in the keystore and truststore were created.

Once I followed the instructions here everything worked fine.

OTHER TIPS

String [] supported = serverSocketFactory.getSupportedCipherSuites();
serverSocket.setEnabledCipherSuites(supported);

and

String[] suites = bancoSocket.getSupportedCipherSuites();
bancoSocket.setEnabledCipherSuites(suites);

Don't mess with the enabled cipher suites. Take that code out and retest. You've enabled the anonymous suites, via which there is no authentication at all in either direction.

Cipher Suites: [TLS_ECDH_anon_WITH_AES_128_CBC_SHA]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top