# Certificates # ## CA and trust keystore keytool -genkeypair -keyalg RSA -keysize 2048 -validity 365 -alias ca -dname "CN=ca,O=HMS,S=SE" -keystore ca.jks -storepass password keytool -exportcert -rfc -alias ca -keystore ca.jks -storepass password > ca.pem cat ca.pem | keytool -importcert -alias ca -noprompt -keystore trust.jks -storepass password ## server cert Notice that the CN must be equal to the DNS hostname! keytool -genkeypair -keyalg RSA -keysize 2048 -validity 365 -alias server -dname "CN=localhost.com,O=HMS,S=SE" -keystore server.jks -storepass password keytool -certreq -alias server -storepass password -keystore server.jks | keytool -gencert -alias ca -rfc -keystore ca.jks -storepass password > server.pem cat ca.pem | keytool -importcert -alias ca -noprompt -keystore server.jks -storepass password cat ca.pem server.pem | keytool -importcert -alias server -keystore server.jks -storepass password ## client cert The username of the client is the value of CN! keytool -genkeypair -keyalg RSA -keysize 2048 -validity 365 -alias client -dname "CN=client,O=HMS,S=SE" -keystore client.jks -storepass password keytool -certreq -alias client -keystore client.jks -storepass password | keytool -gencert -alias ca -rfc -keystore ca.jks -storepass password> client.pem cat ca.pem | keytool -importcert -alias ca -noprompt -keystore client.jks -storepass password cat ca.pem client.pem | keytool -importcert -alias client -keystore client.jks -storepass password # Server authentication and authorization # Tomcat and Jetty authenticates the client if the certificate if signed by a trusted CA. However, standard Java Web security is a mess to configure and I decided to use Spring Security to provide authorization. ## tomcat In server.xml: ## Jetty SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStoreInputStream(new FileInputStream("server.jks")); sslContextFactory.setKeyStorePassword("password"); sslContextFactory.setKeyManagerPassword("password"); sslContextFactory.setTrustStoreInputStream(new FileInputStream("trust.jks")); sslContextFactory.setTrustStorePassword("password"); sslContextFactory.setWantClientAuth(true); _connector = new SslSelectChannelConnector(sslContextFactory); ## Spring Security - authorization optionally user-service-ref="userDetailsService" # Client code # ## HttpClient final KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType()); truststore.load(new FileInputStream("trust.jks"), "password".toCharArray()); final KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(new FileInputStream("client.jks"), "password".toCharArray()); Scheme httpsScheme = new Scheme("https", 443, new SSLSocketFactory(keystore, "password", truststore)); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(httpsScheme); ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry); return new DefaultHttpClient(cm); # Jetty WebSocketClient factory.getSslContextFactory().setTrustAll(false); factory.getSslContextFactory().setTrustStore(truststore); factory.getSslContextFactory().setKeyStore(keystore); factory.getSslContextFactory().setKeyManagerPassword("password");