Search code examples
javasslrmi

Implementing SSL in java rmi


I am trying to implement SSL using Java RMI, where only the server needs to certificate.

I created my certificate using this guide!

when I run the server and the client using CMD and the following commands

% java -Djavax.net.ssl.keyStore=keystore \
  -Djavax.net.ssl.keyStorePassword=password Server

% java -Djavax.net.ssl.trustStore=truststore \
  -Djavax.net.ssl.trustStorePassword=trustword Client

everything works great .. but I want to import those commands inside my eclipse project, so what I do is for the server:

  super(0, new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory());
  System.setProperty("javafx.net.ssl.keyStore","C:\\Users\\Slavi\\workspace\\rmiSSL\\keystore.jks");
  System.setProperty("javafx.net.ssl.keyStorePassword","password");    

and for the client:

  System.setProperty("javafx.net.ssl.trustStore","C:\\Users\\Slavi\\workspace\\rmiSSL\\truststore.jks");
  System.setProperty("javafx.net.ssl.trustStorePassword","trustword");    

and I get the following errors when the client connects

    C:\Users\Slavi\workspace\rmiSSL>java HelloClient
Exception in thread "main" java.rmi.ConnectIOException: error during JRMP connec
tion establishment; nested exception is:
        javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_fai
lure
        at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
        at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
        at sun.rmi.server.UnicastRef.invoke(Unknown Source)
        at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn
own Source)
        at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
        at com.sun.proxy.$Proxy0.sayHello(Unknown Source)
        at HelloClient.main(HelloClient.java:12)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_
failure
        at sun.security.ssl.Alerts.getSSLException(Unknown Source)
        at sun.security.ssl.Alerts.getSSLException(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source
)
        at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source)
        at sun.security.ssl.AppOutputStream.write(Unknown Source)
        at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
        at java.io.BufferedOutputStream.flush(Unknown Source)
        at java.io.DataOutputStream.flush(Unknown Source)
        ... 7 more    

I think the problem is that the server doesn't set the property at the beggining and using something by default but I have no idea what actually the reason for this is and I am pretty stuck it :(

Any ideas?

EDIT

Server code :

public class HelloImpl extends UnicastRemoteObject implements Hello {
public HelloImpl() throws RemoteException {
    super(0, new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory());
    System.setProperty("javax.net.ssl.keyStore","C:\\Users\\Slavi\\workspace\\rmiSSL\\keystore.jks");
    System.setProperty("javax.net.ssl.keyStorePassword","password");
    LocateRegistry.createRegistry(3000);
    System.out.println("RMI registry running on port 3000");
}
public String sayHello() {
    return "Hello World!";
}
public static void main(String args[]) throws Exception {

    // Get reference to the RMI registry running on port 3000 in the local host
    Registry registry = LocateRegistry.getRegistry(null, 3000);
    // Bind this object instance to the name "HelloServer"
    HelloImpl obj = new HelloImpl();
    registry.bind("HelloServer", obj);
    System.out.println("HelloServer bound in registry");
}    

and the Client

public class HelloClient {
public static void main(String args[]) throws Exception {
    System.setProperty("javax.net.ssl.trustStore","C:\\Users\\Slavi\\workspace\\rmiSSL\\truststore.jks");
    System.setProperty("javax.net.ssl.trustStorePassword","trustword");
    // Get reference to the RMI registry running on port 3000 in the local host
    Registry registry = LocateRegistry.getRegistry(null, 3000);
    // Lookup the remote reference bound to the name "HelloServer"
    Hello obj = (Hello) registry.lookup("HelloServer");
    String message = obj.sayHello();
    System.out.println(message);
}   

Solution

  • javafx.net.ssl.keyStore
    

    That should be

    javax.net.ssl.keyStore
    

    Same for the other three.

    You need to put these files elsewhere. Your user directory won't be there on the target machines.

    And of course you need to set these properties before creating any remote objects that rely on them.