1

I have created keystore, truststore, private key and certificate using keytool as follows:

  1. Creating keystore, private key and certificate

    keytool -genkey -alias ssl_key -keyalg RSA -keypass passwd123 -keystore keystore.jks -storepass passwd123
    
  2. Exporting certificate from keystore to truststore

    keytool -import -v -trustcacerts -alias ssl_key -keypass passwd123 -file ssl_key.cer -keystore truststore.jks -storepass passwd123
    

Now I wanted to write java SSL client server. I referred some articles (1,2)and code online and wrote simple Java SSL server and client as follows:

Server

public class Server {
    static KeyStore ks;
    static KeyManagerFactory kmf;
    static TrustManagerFactory tmf;
    static SSLContext sc;
    static TrustManager[] trustManagers;

    static {
        try {
            ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("D:\\javasslstores\\keystore.jks"), "passwd123".toCharArray());

            kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, "passwd123".toCharArray());

            tmf = TrustManagerFactory.getInstance("SunX509"); 
            tmf.init(ks);

            sc = SSLContext.getInstance("TLS"); 
            sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
        }
    }

    public static void main(String[] args) throws IOException {
        System.out.println("SSL Server");
        SSLServerSocketFactory ssf = sc.getServerSocketFactory(); 
        SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(8089);
        System.out.println("Listening on port 8089");
        SSLSocket socket = (SSLSocket) s.accept();


        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
            String line;
            System.out.println("Data from client:");
            while((line = bufferedReader.readLine()) != null){
                System.out.println(line);
                out.println(line);
            }
        }
        System.out.println("Closed");
    }
}

Client

public class Client {
    static KeyStore ks;
    static KeyManagerFactory kmf;
    static TrustManagerFactory tmf;
    static SSLContext sc;
    static TrustManager[] trustManagers;

    static 
    {
        try 
        {
            ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("D:\\javasslstores\\keystore.jks"), "passwd123".toCharArray());

            kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, "passwd123".toCharArray());

            tmf = TrustManagerFactory.getInstance("SunX509"); 
            tmf.init(ks);

            sc = SSLContext.getInstance("TLS"); 
            sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
        }
    }

    public static void main(String[] args) throws IOException {
        SSLSocketFactory ssf = sc.getSocketFactory();
        SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", 8089);
        socket.startHandshake();

        PrintWriter out = new PrintWriter
                                (new BufferedWriter
                                (new OutputStreamWriter
                                (socket.getOutputStream())));

        System.out.println("SSL Client");

        out.println("GET / HTTP/1.0");
        out.println("From java ssl client");
        out.println("written by me");
        out.flush();

        if (out.checkError())
            System.out.println("SSLSocketClient:  java.io.PrintWriter error");

        BufferedReader in = new BufferedReader(
                                new InputStreamReader(
                                socket.getInputStream()));

        String inputLine;

        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);

        in.close();
        out.close();
        socket.close();
    }
}

Above code works.

Doubts

But I have following doubts:

  1. What to do?: Pass either keystore or truststore to client and server or both?
    Looking at examples at link 1, I have specified keystore and truststore in both client and server. That is I have following line in both:

    sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);  //point 0
    

    If I understand it correctly, server needs keystore and client need trustore. Thus, having following in server:

    sc.init(kmf.getKeyManagers(), null, null); //point 1
    

    and following in client:

    sc.init(null, tmf.getTrustManagers(), null); //point 2
    

    also works. But having this:

    sc.init(null, tmf.getTrustManagers(), null);
    

    in server AND/OR this:

    sc.init(kmf.getKeyManagers(), null, null);
    

    in client fails. So am I correct with point 1 and 2 above? When I need to specify both truststore and keystore as in point 0?

  2. Which key and certificate is used if there are multiple of them for communication over SSL?
    Keystore and truststore contains only single key and certificate. But in code, I didnt specify which key and certificate to use. I dont even know if I have to specify them explicitly. What if I have multiple keys and certificates in the stores? Do I have to specify which one to use explicitly. If yes, how can I do it? (It seems that am missing something basic :\ )

  3. Are there any official examples on oracle site explaining writing java SSL server and client using keystore and truststore?

Mahesha999
  • 22,693
  • 29
  • 116
  • 189
  • According to [SSL/RSA](https://www.pagedon.com/rsa-explained-simply/programming). Nothing wrong, truststore - needed by client, because your server using self-signed certificate (and you informing client about trusted certificates). Client will construct (or use java/operating system predefined) own seance public and private RSA keys. – Victor Gubin Jun 13 '18 at 12:28
  • didnt get what do you mean by "?seance? public and private". Also what about doubt 2? – Mahesha999 Jun 13 '18 at 12:38
  • X509 certificate is a format for storing/sending RSA public keys. When client connecting to server, it sends it RSA public key to server. Server answers by it public key (in X509 ASN.1 format) (SSL Handshake). Then client must be sure that server's public key can be trusted. I.e. server is really an owner of this certificate, otherwise connection is unsecured an client must reject it. Java/OS using some base of known (trusted) public keys - truststore. – Victor Gubin Jun 13 '18 at 12:59
  • If you don't specify custom trustore to client, it will use default (i.e. upload some Verisign database into some cache). Since your server certificate is self-singed (not provided by some external service) client will reject the connection. – Victor Gubin Jun 13 '18 at 12:59
  • keystore - is a Java proprietary format for storing servers private and public keys, when truststore is a java format for known servers public keys. – Victor Gubin Jun 13 '18 at 13:03
  • Find out more about [doubt 2](https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm) – Victor Gubin Jun 13 '18 at 13:07
  • And the [doubt 3](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html) – Victor Gubin Jun 13 '18 at 13:13
  • Thanks for all links. I have some doubts. [Does client really sends its public key?](https://gist.github.com/leommoore/da79ce0931a5471304d9) – Mahesha999 Jun 13 '18 at 13:21
  • Also I was talking about which key is used when there are many keys in ketstore not many keystore which is, I guess, first link you shared talks about. – Mahesha999 Jun 13 '18 at 13:22
  • >> The client generates a random symmetric key and encrypts it using the public key in the Certificate >> The client sends the encrypted symmetric key to the server – Victor Gubin Jun 13 '18 at 13:59
  • Ohh I thought you were saying [client sends its own public key at the starting of communication](https://stackoverflow.com/questions/50836704/doubts-about-writing-java-ssl-client-and-server-using-keystore-and-truststore?noredirect=1#comment88679524_50836704) – Mahesha999 Jun 13 '18 at 14:06
  • And one more https://stackoverflow.com/questions/6370745/can-we-load-multiple-certificates-keys-in-a-key-store – Victor Gubin Jun 13 '18 at 14:11
  • And an Handshake image https://hsto.org/files/e52/387/364/e5238736493f41489f5df57f94310962.png – Victor Gubin Jun 13 '18 at 14:14
  • I know we can have multiple certificates in keystore. Point is how to deal with them in code. In above code, I have not specified key name/alias in java code, which I have specified as `ssl_key` in `keytool` command – Mahesha999 Jun 13 '18 at 14:16

0 Answers0