Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the certificate used by a Java SSL ServerSocket

Tags:

java

ssl

I want to open a secure listening socket in a Java server application. I know that the recommended way to do that is to just do this:

SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(443);

But this requires to pass the certificate of the server to the JVM when launching java. Because this would make some things in deployment more complicated for me, I would prefer to load the certificate at runtime.

So I have a key file and a password and I want a server socket. How do I get there? Well, I read the documentation and the only way I could find is this:

// these are my parameters for SSL encryption
char[] keyPassword =  "P@ssw0rd!".toCharArray();
FileInputStream keyFile = new FileInputStream("ssl.key"); 

// init keystore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyFile, keyPassword);
// init KeyManagerFactory
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyPassword);
// init KeyManager
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
// init the SSL context
SSLContext sslContext = SSLContext.getDefault();
sslContext.init(keyManagers, null, new SecureRandom());
// get the socket factory
SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();

// and finally, get the socket
ServerSocket serverSocket = socketFactory.createServerSocket(443);

And that doesn't even have any error handling. Is it really that complicated? Isn't there an easier way to do it?

like image 514
Philipp Avatar asked Sep 11 '12 13:09

Philipp


2 Answers

Use this.

public class KeyMaster
{
     public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e)
    {
        Assistance.log("Err: getSSLSocketFactory(), ");
    }

    return null;
}

public static SSLServerSocketFactory getSSLServerSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getServerSocketFactory();
    }
    catch(Exception e)
    {
        Assistance.log("Err: getSSLSocketFactory(), ");
    }

    return null;
}

public static SSLServerSocket getSSLServerSocket(SSLServerSocketFactory socketFactory, int port)
{
    try
    {
        return (SSLServerSocket) socketFactory.createServerSocket(port);
    }
    catch(Exception e)
    {Assistance.log("Err: getSSLSocket(), ");}

    return null;
}

public static KeyStore getFromPath(String path, String algorithm, String filePassword)//PKSC12
{
    try
    {
        File f = new File(path);

        if(!f.exists())
            throw new RuntimeException("Err: File not found.");

        FileInputStream keyFile = new FileInputStream(f);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(keyFile, filePassword.toCharArray());
        keyFile.close();

        return keystore;
    }
    catch(Exception e)
    {
        Assistance.log("Err: getFromPath(), " + e.toString());
    }

    return null;
}

and in main.

 KeyStore key = KeyMaster.getFromPath(".\\cssl.pfx", "PKCS12", "123");
        SSLServerSocketFactory fac = KeyMaster.getSSLServerSocketFactory(key, "TLS");
        listener = KeyMaster.getSSLServerSocket(fac, 49015);
like image 120
Ali Bagheri Avatar answered Oct 04 '22 00:10

Ali Bagheri


If you look at the code, you can see why it's necessarily complicated. This code decouples the implementation of the SSL protocol from:

  • the source of your key material (KeyStore)
  • certificate algorithm choice and key management (KeyManager)
  • management of peer trust rules (TrustManager) - not used here
  • secure random algorithm (SecureRandom)
  • NIO or socket implementation (SSLServerSocketFactory) - could use SSLEngine for NIO

Consider what your own implementation would look like if you were trying to reach the same goals!

like image 34
David Grant Avatar answered Oct 04 '22 01:10

David Grant