I am trying to provide my client/server communication the option of using WebSockets. I have some experience using Vert.x and chose to use this as a framework for this (note: I'm not stuck to this!).
The two way communication is working, this is not the problem.
I am trying to use TLS to secure the connection. The problem occurs when I try to load the keystore I'm using successfully for my TCP connections into Vert.x. When calling listen()
on the web socket I'm getting the following exception and stack trace:
io.vertx.core.VertxException: java.io.IOException: Invalid keystore format
at io.vertx.core.net.impl.SSLHelper.createContext(SSLHelper.java:297)
at io.vertx.core.net.impl.SSLHelper.getContext(SSLHelper.java:457)
at io.vertx.core.net.impl.SSLHelper.validate(SSLHelper.java:482)
at io.vertx.core.http.impl.HttpServerImpl.listen(HttpServerImpl.java:243)
at io.vertx.core.http.impl.HttpServerImpl.listen(HttpServerImpl.java:211)
at example.VertxSslTest.testServerSocket(VertxSslTest.java:50)
<22 internal calls>
Caused by: java.io.IOException: Invalid keystore format
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:658)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
at java.security.KeyStore.load(KeyStore.java:1445)
at io.vertx.core.net.impl.KeyStoreHelper.loadJKSOrPKCS12(KeyStoreHelper.java:269)
at io.vertx.core.net.impl.KeyStoreHelper.create(KeyStoreHelper.java:83)
at io.vertx.core.net.KeyCertOptions.getKeyManagerFactory(KeyCertOptions.java:43)
at io.vertx.core.net.impl.SSLHelper.getKeyMgrFactory(SSLHelper.java:302)
at io.vertx.core.net.impl.SSLHelper.createContext(SSLHelper.java:255)
... 27 more
My simple test setup, just trying to open a socket:
public void testServerSocket() throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL url = cl.getResource("keystore.ks");
Path path = Paths.get(url.toURI());
byte[] keystoreBytes = Files.readAllBytes(path);
Buffer buffer = Buffer.buffer(keystoreBytes);
HttpServerOptions options = new HttpServerOptions()
.setSsl(true)
.setKeyStoreOptions(new JksOptions()
.setValue(buffer)
.setPassword("password"));
Vertx vertx = Vertx.vertx();
vertx.createHttpServer(options)
.websocketHandler(this::connected)
.listen(8080);
}
I can't find anything on how Vert.x expects the keystore to be structured, what it assumes, etc. And cannot figure out why this keystore is not accepted.
Also, on a side note, why doesn't Vert.x allow a KeyStore
object to be passed.
I've found the issue. Thought I'd leave the solution here for the future.
In a wild guess I tried setting up the socket using a PKCS12 keystore, and that worked! Even though the documentation suggests that both should work, only PKCS12 does. Or I'm still missing something...
Side-Note: I'm still having issues with the socket, because I'm using aliases in my keystore that don't correspond to the server I'll be running it on, because my setup won't know that information when it is set up. But I'll open up a separate issue for that.