I have created keystore, truststore, private key and certificate using keytool
as follows:
Creating keystore, private key and certificate
keytool -genkey -alias ssl_key -keyalg RSA -keypass passwd123 -keystore keystore.jks -storepass passwd123
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:
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?
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 :\ )Are there any official examples on oracle site explaining writing java SSL server and client using keystore and truststore?