How to have multiple SSL certificates for Java server


Lawrence Dol:

I have an internal HTTP server written in Java; the full source code is at my disposal. The HTTP server can be configured with any number of websites, each with a separate listening socket, which is created with the following command:

skt=SSLServerSocketFactory.getDefault().createServerSocket(prt,bcklog,adr);

Using the standard keystore created by Java keytools, I can't for the life of me figure out how to get the different certificates associated with the different listening sockets so that each configured website has its own certificate.

I'm in a pinch right now, so would appreciate some code samples that illustrate examples. However, I'd be happy with any good overview of how JSSE fits together anyway (I've searched Sun's JSSE doco until my brain hurts (literally, though probably caffeine withdrawal) caused).

edit

Isn't there an easy way to associate the server certificate in the keystore with the listening socket using an alias? so that:

  • The client has a keystore to manage all certificates, and
  • No need to fiddle with multiple keystores etc.

I got the impression (earlier this afternoon) that I could write a simple KeyManager that just chooseServerAlias(...)returns non-null, which is the name of the alias I want - does anyone have any ideas for this reasoning?

untie

The solution I used, built on slyvarking 's answer , was to create an ephemeral keystore and populate that ephemeral keystore with the required keys/certs pulled from a single external keystore. Anyone interested can use the following code (svrctfals is my "Server Certificate Alias" value):

    SSLServerSocketFactory              ssf;                                    // server socket factory
    SSLServerSocket                     skt;                                    // server socket

    // LOAD EXTERNAL KEY STORE
    KeyStore mstkst;
    try {
        String   kstfil=GlobalSettings.getString("javax.net.ssl.keyStore"        ,System.getProperty("javax.net.ssl.keyStore"        ,""));
        String   ksttyp=GlobalSettings.getString("javax.net.ssl.keyStoreType"    ,System.getProperty("javax.net.ssl.keyStoreType"    ,"jks"));
        char[]   kstpwd=GlobalSettings.getString("javax.net.ssl.keyStorePassword",System.getProperty("javax.net.ssl.keyStorePassword","")).toCharArray();

        mstkst=KeyStore.getInstance(ksttyp);
        mstkst.load(new FileInputStream(kstfil),kstpwd);
        }
    catch(java.security.GeneralSecurityException thr) {
        throw new IOException("Cannot load keystore ("+thr+")");
        }

    // CREATE EPHEMERAL KEYSTORE FOR THIS SOCKET USING DESIRED CERTIFICATE
    try {
        SSLContext        ctx=SSLContext.getInstance("TLS");
        KeyManagerFactory kmf=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        KeyStore          sktkst;
        char[]            blkpwd=new char[0];

        sktkst=KeyStore.getInstance("jks");
        sktkst.load(null,blkpwd);
        sktkst.setKeyEntry(svrctfals,mstkst.getKey(svrctfals,blkpwd),blkpwd,mstkst.getCertificateChain(svrctfals));
        kmf.init(sktkst,blkpwd);
        ctx.init(kmf.getKeyManagers(),null,null);
        ssf=ctx.getServerSocketFactory();
        }
    catch(java.security.GeneralSecurityException thr) {
        throw new IOException("Cannot create secure socket ("+thr+")");
        }

    // CREATE AND INITIALIZE SERVER SOCKET
    skt=(SSLServerSocket)ssf.createServerSocket(prt,bcklog,adr);
    ...
    return skt;
ZZ encoder:

The easiest way is to use a single certificate for all domains. Put all other site names into SAN (Subject Alternative Name).

If you want to use one certificate per domain name, you can write your own key manager and use an alias to identify the domain so that a single keystore can be used. In our system, we agree that the keystore alias is always equal to the CN in the certificate. So we can do something like this,

SSLContext sctx1 = SSLContext.getInstance("SSLv3");
sctx1.init(new X509KeyManager[] { 
    new MyKeyManager("/config/master.jks","changeme".toCharArray(),"site1.example.com")
    },null, null);
SSLServerSocketFactory ssf = (SSLServerSocketFactory) sctx1.getServerSocketFactory();
ServerSocket ss1 = ssf.createServerSocket(1234);

...

SSLContext sctx2 = SSLContext.getInstance("SSLv3");
sctx2.init(new X509KeyManager[] { 
    new MyKeyManager("/config/master.jks","changeme".toCharArray(),"site2.example.com") 
    },null, null);
ssf = (SSLServerSocketFactory) sctx2.getServerSocketFactory();
ServerSocket ss2 = ssf.createServerSocket(5678);

...

public static class MyKeyManager implements X509KeyManager {
    private KeyStore keyStore;
    private String alias;
    private char[] password;

    MyKeyManager(String keyStoreFile, char[] password, String alias)
        throws IOException, GeneralSecurityException
    {
        this.alias = alias;
        this.password = password;
        InputStream stream = new FileInputStream(keyStoreFile);
        keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(stream, password);
    }

    public PrivateKey getPrivateKey(String alias) {
        try {
            return (PrivateKey) keyStore.getKey(alias, password);
        } catch (Exception e) {
            return null;
        }
    }

    public X509Certificate[] getCertificateChain(String alias) {
        try {
            java.security.cert.Certificate[] certs = keyStore.getCertificateChain(alias);
            if (certs == null || certs.length == 0)
                return null;
            X509Certificate[] x509 = new X509Certificate[certs.length];
            for (int i = 0; i < certs.length; i++)
                x509[i] = (X509Certificate)certs[i];
            return x509;
        } catch (Exception e) {
            return null;
        }          
    }

    public String chooseServerAlias(String keyType, Principal[] issuers,
                                    Socket socket) {
        return alias;
    }

    public String[] getClientAliases(String parm1, Principal[] parm2) {
        throw new UnsupportedOperationException("Method getClientAliases() not yet implemented.");
    }

    public String chooseClientAlias(String keyTypes[], Principal[] issuers, Socket socket) {
        throw new UnsupportedOperationException("Method chooseClientAlias() not yet implemented.");
    }

    public String[] getServerAliases(String parm1, Principal[] parm2) {
        return new String[] { alias };
    }

    public String chooseServerAlias(String parm1, Principal[] parm2) {
        return alias;
    }
}

Related


How to have multiple SSL certificates for Java server

Lawrence Dol: I have an internal HTTP server written in Java; the full source code is at my disposal. The HTTP server can be configured with any number of websites, each with a separate listening socket, which is created with the following command: skt=SSLServ

How to have multiple SSL certificates for Java server

Lawrence Dol: I have an internal HTTP server written in Java; the full source code is at my disposal. The HTTP server can be configured with any number of websites, each with a separate listening socket, which is created with the following command: skt=SSLServ

How to load multiple SSL certificates in Java KeyStore?

Peter I have two SSL certificate files. The first is labeled "OU=Certificate Authority" and the second is labeled "OU=Root Certificate". Our C++ application loads both certificates for proper client/server handshake. Now, I need to use these certificates in my

How to load multiple SSL certificates in Java KeyStore?

Peter I have two SSL certificate files. The first is labeled "OU=Certificate Authority" and the second is labeled "OU=Root Certificate". Our C++ application loads both certificates for proper client/server handshake. Now, I need to use these certificates in my

How to load multiple SSL certificates in Java KeyStore?

Peter I have two SSL certificate files. The first is labeled "OU=Certificate Authority" and the second is labeled "OU=Root Certificate". Our C++ application loads both certificates for proper client/server handshake. Now, I need to use these certificates in my

Multiple SSL certificates on one server

Kyle O'Brien We will host both websites on a small but dedicated production server. Both sites require SSL authentication. So we set up virtual hosts for both of them. They all reference their own domain.key, domain.crt and domain.intermediate.crt files. Each

Multiple SSL certificates on one server

Kyle O'Brien We will host both websites on a small but dedicated production server. Both sites require SSL authentication. So we set up virtual hosts for both of them. They all reference their own domain.key, domain.crt and domain.intermediate.crt files. Each

Multiple SSL certificates on one server

Kyle O'Brien We will host both websites on a small but dedicated production server. Both sites require SSL authentication. So we set up virtual hosts for both of them. They all reference their own domain.key, domain.crt and domain.intermediate.crt files. Each

How to Use SSL Certificates in Java on Mac

beitseeb I found this question: Import Windows Certificates into Java , which gives the answer for Windows machines. I haven't been able to find a -Djavax.net.ssl.trustStoreType=WINDOWS-ROOTMacOS equivalent . beitseeb Jacob Blanton provided the solution in the

Java 7 - How SSL trusts all certificates

Uri Lukach I'm writing a Java proxy that uses SSL to communicate with other servers. With ServerSocketFactory and keystore and truststore populated by server certificate everything works perfectly. I was wondering, is there a way in Java 7 to disable authentic

Java 7 - How SSL trusts all certificates

Uri Lukach I'm writing a Java proxy that uses SSL to communicate with other servers. With ServerSocketFactory and keystore and truststore populated by server certificate everything works perfectly. I was wondering, is there a way in Java 7 to disable authentic

How to Use SSL Certificates in Java on Mac

beitseeb I found this question: Import Windows Certificates into Java , which gives the answer for Windows machines. I haven't been able to find a -Djavax.net.ssl.trustStoreType=WINDOWS-ROOTMacOS equivalent . beitseeb Jacob Blanton provided the solution in the

How to Use SSL Certificates in Java on Mac

beitseeb I found this question: Import Windows Certificates into Java , which gives the answer for Windows machines. I haven't been able to find a -Djavax.net.ssl.trustStoreType=WINDOWS-ROOTMacOS equivalent . beitseeb Jacob Blanton provided the solution in the

Java and SSL certificates

Andy: I'm trying to use Secure Sockets Layer (HTTPS) to connect to a PHP script in Java, but I've found that for maximum security/validity I have to import the SSL certificate used by the website into my application. ..I do not know what to do. If it helps, my

Java and SSL certificates

Andy: I'm trying to use Secure Sockets Layer (HTTPS) to connect to a PHP script in Java, but I've found that for maximum security/validity I have to import the SSL certificate used by the website into my application. ..I do not know what to do. If it helps, my

Java and SSL certificates

Andy: I'm trying to use Secure Sockets Layer (HTTPS) to connect to a PHP script in Java, but I've found that for maximum security/validity I have to import the SSL certificate used by the website into my application. ..I do not know what to do. If it helps, my

SSL sockets - Java and certificates?

bob I am trying to implement SSL sockets between an Android application and a Python API. The code below... SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault(); Socket s = ssf.createSocket("10.0.2.2", 5001); DataOutputStream myDataOut = new

Using multiple SSL client certificates with the same host in Java

cwick: In my Java application, I need to connect to the same host using SSL, but using a different certificate each time. The reason I need to use a different certificate is that the remote site uses the userid attribute embedded in the certificate to identify

Using multiple SSL client certificates with the same host in Java

cwick: In my Java application, I need to connect to the same host using SSL, but using a different certificate each time. The reason I need to use a different certificate is that the remote site uses the userid attribute embedded in the certificate to identify

Traefik kubernetes multiple SSL certificates

Winner I am using Traefik as a reverse proxy on a Kubernetes cluster and am looking for a way to use multiple SSL certificates. According to the doc , it is not possible to use multiple TLSStores, I have to use only the defaultstore. For example, I have two do

WildFly Multiple Domains and SSL Certificates

kefkaz I have two different domains example1.com example2.com Each domain has its own SSL certificate. What I want to do now is use both domains for the same WildFly instance, with SSL support. The WildFly documentation states that I can only reference a singl

Traefik kubernetes multiple SSL certificates

Winner I am using Traefik as a reverse proxy on a Kubernetes cluster and am looking for a way to use multiple SSL certificates. According to the doc , it is not possible to use multiple TLSStores, I have to use only the defaultstore. For example, I have two do

WildFly Multiple Domains and SSL Certificates

kefkaz I have two different domains example1.com example2.com Each domain has its own SSL certificate. What I want to do now is use both domains for the same WildFly instance, with SSL support. The WildFly documentation states that I can only reference a singl

Multiple SSL certificates in virtual host?

alavona I have a server running Ubuntu 12.04.3 LTS and two servers running Ubuntu 14.04.1 LTS with SSL certificates in them. All are bitnami stacks, so their apache2 config files are at: /opt/bitnami/apache2/conf/bitnami The requirement is to www.have a total