0

I've searched everywhere on StackOverflow but those issues seem different from mine and I'm having a lot of trouble fixing it.

For now, my program should just make a Client-Server connection with SSL Sockets where the Client sends just one message and it closes (I'll add more stuff to it later)

I get the problem with the message part and No Cipher Suites in Common error. Below I'll post my Server and Client code along with the output. I'm using Ubuntu 16.04 and Netbeans 8.2

Server code:

public static void main(String[] args) 
        throws IOException, KeyStoreException, NoSuchAlgorithmException, 
        CertificateException, UnrecoverableKeyException, KeyManagementException {

    FileInputStream keyFile = new FileInputStream(archivoKey);//Server.jks with Client.crt and .key as well as Server.crt and .key
    char[] archivopwd = mypassword.toCharArray();
    String password = mypassword;

    System.setProperty("javax.net.ssl.trustStore", archivoKey);
    System.setProperty("javax.net.ssl.trustStorePassword", password); 

    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(keyFile, archivopwd);

    KeyManagerFactory keyManagerFactory = 
            KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(keyStore, archivopwd);
    KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();

    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(keyManagers, null, null);


    SSLServerSocketFactory factory=(SSLServerSocketFactory) 
            SSLServerSocketFactory.getDefault();
    SSLServerSocket ss = (SSLServerSocket) factory.createServerSocket(6000);
    System.out.println("Esperando conexion...");
    ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
    SSLSocket so =(SSLSocket) ss.accept();
    so.startHandshake();
    System.out.println("Conexion realizada");

    BufferedReader in = new BufferedReader
        (new InputStreamReader(so.getInputStream()));
    String msg = in.readLine();
    System.out.println(msg);

}

Server Output:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:292)
at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:1045)
at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:741)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:224)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at servidorseguridad.ServidorSeguridad.main(ServidorSeguridad.java:73)

Client code

public static void main(String[] args) {
    int port = 6000;
    String host = "localhost";
    String password = mypassword;
    System.setProperty("javax.net.ssl.trustStore", archivoKey);
    System.setProperty("javax.net.ssl.trustStorePassword", password); 
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        InputStream keyFile = new FileInputStream(archivoKey); //Client.jks, exactly the same as the Server.jks
        try {
            keyStore.load(keyFile, archivopwd);
        } finally {
            if (keyFile != null) {
                keyFile.close();
            }
        }
        KeyManagerFactory keyManagerFactory = 
                KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, archivopwd);

        sc.init(null,  null, null);

        SocketFactory factory = sc.getSocketFactory();

        System.out.println("Buscando conexion...");

        try (SSLSocket so = (SSLSocket) factory.createSocket(host, port)) {
            so.getEnabledCipherSuites();
            so.startHandshake();

            System.out.println("Conexion exitosa!");

            DataOutputStream os = new DataOutputStream(so.getOutputStream());

            os.writeUTF("Prueba!");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Client output

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at clienteseguridad.ClienteSeguridad.main(ClienteSeguridad.java:65)

Most stuff (like the System.setProperty stuff) was me testing out several options I've read on here. The .jks were generated by getting the crt and key files to p12 ones and adding these to the .jks.

I'm really out of ideas here so any help is appreciated. Anything else you need you can just ask. Thank you

luismzk
  • 93
  • 1
  • 2
  • 7

1 Answers1

0

This exception usually means that the server didn't have a private key. That means it can only support the anonymous cipher suites, and if the client doesn't allow those, as it shouldn't, there are no cipher suites in common.

Your setup code is bizarre:

  • You are both loading the truststore and setting the system properties: you don't need to do both.
  • You are using the same file for the keystore and truststore, which is technically valid but never advisable.

You need to create a server-side keystore, a keypair, and then either

  1. a self-signed certificate, whihc you need to export to the client's truststore, or better still
  2. a CSR, get it signed by the CA, and then import the signed certificate into the server keystore using the same alias you used to create the keypair.

Finally:

ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());

Remove this line. It is insecure. Never do this.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Hi, thanks for the answer! As I said, some lines were added as I was trying to fix it (like the setEnabledCipherSuites) but thanks for telling me it's insecure. I already have the CSR signed by an authority and it's imported in the .p12 mentioned in the end. I used that mentioned because it was said it was the best workaround. Should I not have done that and instead imported something else to the jks keystores? – luismzk Jul 13 '17 at 03:43
  • Please define 'The .jks were generated by getting the crt and key files to p12 ones and adding these to the .jks.'. – user207421 Jul 13 '17 at 05:02
  • I followed the instructions in [this post](https://stackoverflow.com/questions/17695297/importing-the-private-key-public-certificate-pair-in-the-java-keystore) – luismzk Jul 13 '17 at 11:25
  • You mean the instructions in the question, or one of the answers? – user207421 Jul 14 '17 at 03:48