For all of our services (such as Haplogrep), we are using Restlet on server side. This blog entry summarizes the necessary steps to set up a working HTTPS Restlet Server with a valid certificate and a trusted connection. Check out the Github Repo for the source code!
Set up a Java Keystore
- In a first step, a new Java Keystore needs to be created using the
keytool
of JDK (use at least Java 7 for this):
keytool -genkey -alias <your-alias> -keyalg RSA -keysize 2048 -keypass <your-passwd> -storepass <your-passwd> -keystore <your-keystore.jks>
- Now, generate a new certificate signing request (CSR) and send it your certificate authority (CA). Alternatively, the CSR can also be self-signed.
keytool -keystore <your-keystore.jks> -certreq -alias <your-alias> -keyalg RSA -keysize 2048 -file <signing-request.csr>
- Import the received root / intermediate webserver certificate files (CRTs) from your CA like this (I received two files):
keytool -import -alias intermed -keystore <your-keystore.jks> -trustcacerts -file <intermed.crt>
keytool -import -alias <your-alias-from-the-csr> -file <received-file.crt> -trustcacerts -keystore <your-keystore.jks>
Create a Restlet Webapp (Updated on Nov 24)
Now it’s time to integrate your certificate into your Restlet App as described here. The running example can be found here.
public class SampleServer {
public static void main(String[] args) {
// Create a new Component.
Component component = new Component();
// Add a new HTTP server listening on port 8080
Server server = component.getServers().add(Protocol.HTTP, 8080);
// Add your HTTPS specifications
String file = "location-to-your-file";
String keystorePwd = "your-password";
String keyPwd = "your-password";
File keystoreFile = new File(file);
if (keystoreFile.exists()) {
component.getServers().add(Protocol.HTTPS, 4443);
Series<Parameter> parameters = server.getContext().getParameters();
parameters.add("sslContextFactory",
"org.restlet.engine.ssl.DefaultSslContextFactory");
component
.getContext()
.getParameters()
.add("enabledCipherSuites",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"
+ " TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
+ " TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
+ " TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
+ " TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
+ " TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
+ " TLS_RSA_WITH_AES_256_CBC_SHA"
+ " TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"
+ " TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
+ " TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"
+ " TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
+ " TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
parameters.add("keyStorePath", keystoreFile.getAbsolutePath());
parameters.add("keyStorePassword", keystorePwd);
parameters.add("keyPassword", keyPwd);
parameters.add("keyStoreType", "JKS");
parameters.add("allowRenegotiate", "false");
}
component.getDefaultHost().attach(new Application() {
@Override
public Restlet createInboundRoot() {
Router router = new Router();
router.attach("/", Index.class);
return router;
}
});
// Start the component.
component.start();
}
}
Important Note
Keep in mind that your service should use the latest version of Restlet (currently 2.3) and Java 8 to avoid errors like this on Firefox (result: no connection can be established!):
SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message. (Error code: ssl_error_weak_server_ephemeral_dh_key)
or this one on Chrome (result: connection can be established but with warnings):
Your connection is encrypted with obsolete cryptography.
The connection is encrypted using AES_256_CBC, with SHA1 for message authentication and DHE_RSA as the key exchange mechanism.
This short tutorial should give you an up and running Restlet server and avoid many mistakes I did in the past. Contact me if something is unclear!