3

I'm trying to get a very basic Grizzly server up and running to allow for one-way SSL (HTTPS) connections to access jax-rs REST services. Eventually I want two-way SSL security.

I've gone through many of the examples and I just can't get anything to work. I keep running into a SSL Handshake error. Clearly I must be doing something stupid. Any help is appreciated.

Here is my code to start my embedded Grizzly server using the Jersey wrapper classes:

public static HttpServer startHttpsServer(URI listenerURI) throws IOException  {
  ResourceConfig resourceConfig = new ResourceConfig().packages("ws.argo.experiment.ssl");

  // First I tried this configuration using the certs from the Jersey sample code
  // Grizzly ssl configuration
  SSLContextConfigurator sslContext = new SSLContextConfigurator();

  // set up security context
  sslContext.setKeyStoreFile("./src/main/resources/keystore_server"); // contains server keypair
  sslContext.setKeyStorePass("asdfgh");
  sslContext.setTrustStoreFile("./src/main/resources/truststore_server"); // contains client certificate
  sslContext.setTrustStorePass("asdfgh");

  // Then I tried just using a default config - didn't work either
  //    sslContext = SSLContextConfigurator.DEFAULT_CONFIG;


  if (!sslContext.validateConfiguration(true)) {
    LOGGER.severe("Context is not valid");

  }

  LOGGER.finer("Starting Jersey-Grizzly2 JAX-RS secure server...");
  HttpServer httpServer; //=   GrizzlyHttpServerFactory.createHttpServer(listenerURI, resourceConfig, false);


  httpServer= GrizzlyHttpServerFactory.createHttpServer(
      listenerURI,
      resourceConfig,
      true,
      new   SSLEngineConfigurator(sslContext).setClientMode(false).setNeedClientAuth(false)
      );



  httpServer.getServerConfiguration().setName("Test HTTPS Server");
  httpServer.start();
  LOGGER.info("Started Jersey-Grizzly2 JAX-RS secure server.");

  return httpServer;
}

I also tried replaced SSLEngineConfigurator(sslContext).setClientMode(false).setNeedClientAuth(false) with null to see if that would help. Nope.

I always get the following error:

grizzly-nio-kernel(3) SelectorRunner, fatal error: 40: no cipher suites in common
javax.net.ssl.SSLHandshakeException: no cipher suites in common
%% Invalidated:  [Session-2, SSL_NULL_WITH_NULL_NULL]
grizzly-nio-kernel(3) SelectorRunner, SEND TLSv1.2 ALERT:  fatal, description = handshake_failure
grizzly-nio-kernel(3) SelectorRunner, WRITE: TLSv1.2 Alert, length = 2
grizzly-nio-kernel(3) SelectorRunner, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: no cipher suites in common
jmsimpson68
  • 233
  • 3
  • 10
  • You only need the client cert in the server trust store for mutual (two way) ssl. If the server cert is self signed, what you will need to do is add the server cert to the client trust store – Paul Samsotha Nov 20 '15 at 16:56
  • 1
    Take a look at [this example](https://github.com/jersey/jersey/tree/master/examples/https-clientserver-grizzly) – Paul Samsotha Nov 20 '15 at 17:07
  • @peetskillet - that is the example I started with. The only difference is that I'm not using the jersey-container-grizzly2-servlet setup. Just using the regular jersey-container-grizzly2-http version as a dependency. I don't think that would make any difference. – jmsimpson68 Nov 20 '15 at 17:45
  • Are you using the Jersey client or a different client? Did you follow the instructions to create the stores and imports? The example as is works for me (also create new stores from the instructions). You can see the Jersey client set up in the test case. I don't think changing from the servlet to http config should make a different, though I didn't test – Paul Samsotha Nov 20 '15 at 17:51
  • Right now I'm just using a web browser (Safari, Firefox, Chrome) to attempt to access the resource. No luck with them. It should be setup to allow simple 1-way SSL with a browser. I'm not using a special client. – jmsimpson68 Nov 20 '15 at 18:02
  • Does it at least show you something asking if you want to trust the cert when testing in the browser? – Paul Samsotha Nov 20 '15 at 18:05
  • Unfortunately, no. That was what I was expecting (the "get me out of here" dialog). It just fails in the handshake before it gets there and the browser tell me that the connection was unsecure and interrupted. – jmsimpson68 Nov 20 '15 at 18:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/95735/discussion-between-jms-and-peeskillet). – jmsimpson68 Nov 20 '15 at 18:37
  • I sure would have loved to been in on that chat, I am having the same issue with my configuration. Just hangs waiting for the certs. – Steve Owens Mar 06 '18 at 20:09
  • Similar question: https://stackoverflow.com/q/21098105/873282 – koppor Apr 10 '23 at 10:37

3 Answers3

4

To add on top of JMS comment, his answer solve my problem too . Here is the command i used to generate the RSA certificate .

keytool -genkey -keystore ./keystore_client -alias clientKey -keyalg RSA -keypass changeit -storepass changeit -dname "CN=Client, OU=Jersey, O=changeit, L=KL, ST=SEL, C=MY"
keytool -export -alias clientKey -storepass changeit -keystore ./keystore_client -file ./client.cert
keytool -import -alias clientCert -file ./client.cert -storepass changeit -keystore ./truststore_server


keytool -genkey -keystore ./keystore_server -alias serverKey -keyalg RSA -keyalg RSA -keypass changeit -storepass changeit -dname "CN=changeit, OU=Jersey, O=changeit, L=KL, ST=SEL, C=MY"
keytool -export -alias serverKey -storepass changeit -keystore ./keystore_server -file ./server.cert
keytool -import -alias serverCert -file ./server.cert -storepass changeit -keystore ./truststore_client
Steve Low
  • 59
  • 2
  • Note that this misses `AltName`, thus it won't work in newest Chrome: https://stackoverflow.com/a/42917227/873282. – koppor Apr 10 '23 at 10:39
3

I have seen this type of handshake issue come up in other posts while trying to run this issue to ground. In all of these handshake posts, the server key algorithm was never discussed - I wish it had been. It would have saved me a couple of hours. The issue that caused the above errors stemmed from assuming that the keystores that were created as part of the Jersey sample project would work. The server key was the problem.

The sample server certs are generated using the DSA algorithm. Apparently this is an issue.

I recreated the server keys using a RSA algorithm and 2048 bit strength. I restarted the server and the everything started to work like one would expect.

The error was that I assumed that the "sample" keys would work. Oops.

jmsimpson68
  • 233
  • 3
  • 10
0

The SSL certificate needs an AltName. See https://stackoverflow.com/a/42917227/873282 for details.

Use mkcert to generate a valid SSL certificate (based on https://stackoverflow.com/a/57511038/873282)

  1. As admin choco install mkcert
  2. As admin: mkcert -install
  3. cd \temp
  4. mkcert -pkcs12 app localhost 127.0.0.1 ::1
  5. Rename the file to server.p12

In Java, you can use that file as keystore:

        SSLContextConfigurator sslContextConfig = new SSLContextConfigurator();
        sslContextConfig.setKeyStoreFile(Path.of("c:\\temp\\server.p12").toString());
        sslContextConfig.setKeyStorePass("changeit");
        sslContextConfig.createSSLContext();
koppor
  • 19,079
  • 15
  • 119
  • 161