Don’t forget to set the cipher suite!

I was attempting to use a vanilla SSL server and client socket (such as outlined in this article) but kept getting the dreaded:

javax.net.ssl.SSLException: No available certificate corresponds
to the SSL cipher suites which are enabled.

The usual searches turned up a million posts about junk I already knew. The JSSE ref guide is great for people that already know what they’re doing an is therefore self deprecating.

The long and short of it is that if you use a default SSLServerSocketFactory and create a socket then you must have an anonymous cipher suite installed. For example:

final SSLServerSocketFactory sslSocketFactory =
(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
final SSLServerSocket sslServerSocket =
(SSLServerSocket)sslSocketFactory.createServerSocket(port);
// use an anonymous cipher suite so that a KeyManager or TrustManager
// is not needed
// NOTE:  this assumes that the cipher suite is known.  A check -should-
//        be done first.
final String[] enabledCipherSuites = { "SSL_DH_anon_WITH_RC4_128_MD5" };
sslServerSocket.setEnabledCipherSuites(enabledCipherSuites);

A unless you do the same on the client side, you will receive the following:

javax.net.ssl.SSLHandshakeException: no cipher suites in common
javax.net.ssl.SSLHandshakeException:
Received fatal alert: handshake_failure

Link-back to main entry: NIO and SSL.

Advertisements

33 comments

  1. Thanks! .. I was trying all manner of things to make it work for 5 hours!! .. And you solved it .. Thanks 😉

  2. Hi Rod,
    I also tried it but it’s still not working. I’ve also tried to list all the supported cypher suites and enabled them but no luck and this thing is really supposed to be working for yesterday.
    D.

  3. Well, let’s start with defining “not working”. What are the exceptions and can you pare down the code to just something that we can work with?
    Email me directly if you want so that we can expidite this.

  4. Don’t worry, it did worked 🙂 I was just setting the cypher suites on the client side and I just forgot to do it on the server side when I wanted to give a message back.
    It’s all good now, I mean, on the test server, because on the customer side, I still got problem but with some socket closed problem, I think it has to see with the certificates and all. I hope to solve it by the end of the day, but your help was more than appreciated.
    D.

  5. If you dont want to have to use an anonymous set of cipher suites you can use the following:
    System.setProperty(“javax.net.ssl.keyStore”, System.getProperty(“user.home”) + File.separator + “keystore”);
    System.setProperty(“javax.net.ssl.keyStorePassword”, “yourpassword”);
    SSLServerSocketFactory factory =(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
    serverSocket = (SSLServerSocket) factory.createServerSocket(port); // Create the ServerSocket
    Make sure you have a valid keystore (Server) and Truststore (Client)
    If you want to create them follow these instructions and you cant go wrong: http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html#CreateKeystore
    -Rich

  6. Thanks for the tip Rich!
    I feel obligated to point out though that I would not use that code in anything other than a proof of concept or a test. Java security 101 says that passwords should never be passed around as Strings (they should be char[]s) and even with a suitable SecurityManager, putting the keystore password in the environment (System.XXXProperties) is not a good idea.

  7. javax.net.ssl.SSLException: No available certificate corresponds to the SSL cipher suites which are enabled.
    at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.a(DashoA6275)
    at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.accept(DashoA6275)

  8. I’m assuming jitendra that that’s a question. You’re going to need to provide a bit more information such as what -are- the available cipher suites, what JDK (version and provider) and any other relevant factors (perhaps platform, other jars, etc).

  9. Thanks for the helpful page. It got me going in the right direction. Sometimes, your client will settle for an anonymous cipher, but Sun’s Java (1.4.1) does not enable those by default. To let clients use whatever your libraries support do something like:
    SSLServerSocketFactory socket_fact = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
    SSLServerSocket ssl_server_socket = (SSLServerSocket)SSLServerSocketFactory.getDefault().createServerSocket(port);
    ssl_server_socket.setEnabledCipherSuites(ssl_server_socket.getSupportedCipherSuites());
    Regards,
    Stephen

  10. Thanks this was a very helpful page I found through google. I was doing a quick test to make sure that I could get a custom SSL client talking to a custom SSL server, and got it working quickly thanks to your page.
    I was following the directions on this page for my quick-bang proof of concept:
    http://javaalmanac.com/egs/javax.net.ssl/Server.html?l=rel
    It does not mention setting the cypher suite there, but that fixed it. First I did the anonymous cyhpher as you suggested, and then I read in the comments about making all the available cyphers available, and that worked too.
    I don’t understand why it does not just do that automatically really! If I specify that all the ciphers are enabled, which one does it use? Does it really matter? Is the transaction still secure?

  11. How is it possible to enable the cipher if i want to acces my server via my browser (IE) ??
    also, where do i enable them in my tomcat??

  12. I ran into this problem when I imported my CA certificates into the wrong keystore, and tried a lot of suggestions from many other formus before coming across this solution:
    *** Make sure you import the CA certificates into the same keystore you used to create the certificate request. ***
    That ensures that you have a valid key entry in the keystore so keytool or whatever can build the proper certificate chain.
    Thawte’s website has a nice set of troubleshooting tips.
    http://search.thawte.com/thawte/solutionDisplay.do;jsessionid=F9CD74D583D00F11B0804A367BB324BD?clusterName=DefaultCluster&groupId=1&docType=1006&docProp=$solution_id&docPropValue=vs7948&gotoLink=0&resultType=5002&directSolutionLink=1

  13. Hi All, I have configured tomcat for https. and have given heystore path inside the server.xml explicitly for verisign.keystore. but when i try to start the server i get
    “SEVERE: Endpoint [SSL: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=8080]] ignored exception: java.net.SocketException:
    SSL handshake errorjavax.net.ssl.SSLException: No available certificate corresponds to the SSL cipher suites which are enabled.”
    plz help

  14. Priolkar, it’s difficult to help without knowing what you’ve already tried. I’m assuming that you’ve read all of the other comments associated with this entry including the one from Mr. Hanweck?

  15. Thanks for the tips on JSSE, i tried to implement the same and solved quite a lot of problems, but now im encounterring something new
    below is the code snippet in Server.java
    SSLServerSocketFactory sslSrvFact = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
    s =(SSLServerSocket)sslSrvFact.createServerSocket(PORT);
    final String[] enabledCipherSuites = { “SSL_DH_anon_WITH_RC4_128_MD5” };
    s.setEnabledCipherSuites(enabledCipherSuites);
    SSLSocket c = (SSLSocket)s.accept();
    Code Snippet from Client.java is as follows
    SSLSocketFactory sslFact =
    (SSLSocketFactory)SSLSocketFactory.getDefault();
    SSLSocket socket =
    (SSLSocket)sslFact.createSocket(LOCALHOST, PORT);
    final String[] enabledCipherSuites = { “SSL_DH_anon_WITH_RC4_128_MD5” };
    socket.setEnabledCipherSuites(enabledCipherSuites);
    the exception i encounter on Client Side is
    java.net.ConnectException: Connection refused: connect
    java.net.ConnectException: Connection refused: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(Unknown Source)
    at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(Unknown Source)
    at the same time i get the following exception on Server side
    ( Server.java:82) – java.net.BindException: Address already in use: JVM_Bind
    host is specified as localhost
    and port is specified as 8123
    the abv program works with plain socket communication.
    Please let me know the solution if you have any
    thanks in advance

  16. I’m trying to get ssl (https) working in JBoss (which is actually tomcat underneath) and I am obviously not “in the know” when it comes down to it. I’ve been able to setup SSL certs for Apache and IIS in minutes….I’ve been banging on Tomcat for a week now and it just doesn’t make sense.
    This article is the most descriptive, however, you don’t mention how this would apply in my case?
    I actually ran your code using port 8443 and it didn’t fail…but I don’t see how I could run this “server” while running JBoss at the same time, the ports would conflict.
    What can I do?

  17. V. Jenks, this post was initially about a standalone SSL server (which I was writing as part of a security product). Unfortunately, it doesn’t help you in any way and for that I apologize. I’ve heard of people having your exact problems but I don’t know of anyone that has a quick and fast solution. Again, sorry. If you do ever come up with a solution please remember to post it someplace (here, perhaps) so that your knowledge can help everyone!
    Good luck!

  18. Hello, I have the server working with alot of reading and trail/error approach. The issue that I’m having is getting curl to talk to the java ssl server. All the examples use a server.cer file and curl needs a server.pem. I have created a cert with CA.sh and imported it on the server side, but know I get the no cipher suites in common error. Help and thank you in advance. BTW, I get the same error from my browser.

  19. Thanks a lot for this thread, it saved my day. While perfectly working with Java on Windows, my application kept complaining about missing cipher suites on Linux. This line of code I found here did the job:
    serverSocket.setEnabledCipherSuites(serverSocket.getSupportedCipherSuites());
    Thanks,
    Drakanor

  20. Great post. I was messing around with ssl (new area for me) and couldn’t figure out how to get it working. This helped a lot, thanks.

  21. It’s a good idea to explain how to configure the cipher suites, but perhaps this entry should come with a word of warning. Anonymous cipher suites offer virtually no security against man-in-the-middle attacks, which are one of the main reasons to use SSL in the first place. An SSL connection that uses an anonymous cipher suite is virtually as good as not using SSL at all: these cipher suites should never be used in production.
    Cheers.

  22. Thanks dude! After full weekend we resolved the problem with this post! Sounds stupid but true!
    Best regards from Barcelona, Catalonia

  23. How to disable the anon suites for some particulat port.

    We are enabling the anon suites in our code .
    on server
    socket.setEnabledCipherSuites(SERVER_SOCKET_ANON_SUITES);
    on client
    socket.setEnabledCipherSuites( SSL_SOCKET_ANON_SUITES )

    And this is working fine but now we want to disable it for specific port .
    We tried
    on server
    socket.setEnabledCipherSuites(SERVER_SOCKET_NON_ANON_SUITES);.
    on client
    socket.setEnabledCipherSuites(SSL_SOCKET_NON_ANON_SUITES);

    Both the conditions are there depending upon the port.

    Its throwing
    javax.net.ssl.SSLException: No available certificate corresponds
    to the SSL cipher suites which are enabled.

  24. I tried an SSL java client server on windows and this was not necessary. When I tried doing this on a Linux machine ( with the same exact code ) this was exactly the problem. Thanks.

  25. I have set the cipher suit on server side using socket.setEnabledCipherSuit() method. How can I set this on client. My client is a java code running on java6


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s