Is it possible to change keystore at runtime? Currently I am setting up SSL before I do a server.start() -
sslContextFactory.setTrustStore(ks);
sslContextFactor
It seems there are two issues here: generating the certificate on the dynamically ("What I would like to do is create a certificate at runtime and use it.") and setting it up without restarting ("Is it possible to change keystore at runtime?").
To generate a certificate dynamically, you can use BouncyCastle and its X509V3CertificateGenerator class.
First, generate a self-signed CA (with the CA basic constraint set), using keytool for example (look at the -ext
option for details). This will be your custom CA.
Export the certificate from that keystore (only the CA certificate, not its private key) and import it into the clients you're going to use.
In your application, using that private key for signing with the X509V3CertificateGenerator
, and make sure the Issuer DN you use matches the Subject DN of the CA cert you've generated above.
Then, you'll need to configure the certificate generate with a Subject DN (or Subject Alternative Name) that matches the host name your client intended to contact. This may be the tricky bit if you intend to do this automatically as some sort of transparent proxy. (As far as I know, current versions of Java can't read the name coming from the SNI extension, at least not in advance or without doing more manual processing.) The easier way would certainly be to have this host name as a configurable option in your tool.
To set it up without restarting the server, you could implement your own X509KeyManager
that stays in place in the SSLContext
you're using, but for which you keep a reference and custom accessors to re-configure the certificate later on. It's certainly not necessarily something "clean", and I haven't tried it, but it should work in principle. (You should certainly make sure the concurrency aspects are handled properly.)
This might allow you not to have to shut down the listening socket, reconfigure the SSLContext
and restart the socket. Considering that you might need to interact with your application anyway (to reconfigure the host name), this might be overkill.