PEMParser update

In my last post I talked about using PEMParser to load private keys from OpenSSL PEM files. After further testing I discovered I needed to refine the code a little.

There appears to be a couple of different ways the private key can be encoded in the file. I discovered this after generating some new test keys only to find they didn’t work with my existing code.

Object privatekey = parser.readObject();

if (privatekey instanceof PEMEncryptedKeyPair) {
     try {
	privatekey = ((PEMEncryptedKeyPair)privatekey).decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(passphrase));
     } catch (Exception e) {
	throw new InvalidPassphraseException(e);
     }
} else if(privatekey instanceof PKCS8EncryptedPrivateKeyInfo) {
     try {
	privatekey = converter.getPrivateKey(((PKCS8EncryptedPrivateKeyInfo)privatekey).decryptPrivateKeyInfo(new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase)));
     } catch (Exception e) {
	throw new InvalidPassphraseException(e);
     }
}

if (privatekey instanceof PEMKeyPair) {
	return loadKeyPair((PEMKeyPair)privatekey);
} else if(privatekey instanceof RSAPrivateCrtKey){
	return loadKeyPair((RSAPrivateCrtKey)privatekey);
} else {
	throw new FileFormatException("The file doesn't seem to have any supported key types obj=" + privatekey);
}

Loading PEM keys & certificates from Java

I’ve worked for years with Java and SSL sockets and I’ve always struggled with support issues when it comes to SSL certificates. The problem is that most non-developer folks use Apache style PEM certificates and have come pretty use to them. When you present them with a different format and require they configure your application with a Java KeyStore your bound to get problems. The only solution is to allow your end users to configure your solution with the formats they know and love.

Thats why I decided to go with a more flexible approach for configuring Hypersocket with SSL certificates. I want end users to be able to upload their existing PEM keys and certificates and have this work out-of-the-box with no conversion, no formatting changes. Just use the files as they come. Luckily there are tools available at the Bouncycastle project that now make this possible.

First of all I’ve installed the Bouncycastle JCE provider 1.48 in the security providers list.

Security.addProvider(new BouncyCastleProvider());

I’m now going to load the private key from a PEM file, if the file is encrypted we will decrypt the key. I’m using PEMParser from the Bouncycastle PKIX/CMS/EAC/PKCS/TSP/OPENSSL package. Some checks and balances have been removed from the following code:

PEMParser parser = new PEMParser(new InputStreamReader(keyfile));

// Load the key object
Object privatekey = parser.readObject();

// Check to see if the object returned is an encrypted key pair
if (privatekey instanceof PEMEncryptedKeyPair) {
    privatekey = ((PEMEncryptedKeyPair)privatekey).decryptKeyPair(new JcePEMDecryptorProviderBuilder().build("xxxxxxxx".toCharArray()));
} 

// Cast to a PEMKeyPair
PEMKeyPair pair = (PEMKeyPair) privatekey;

// Get the encoded objects ready for conversion to Java objects
byte[] encodedPublicKey = pair.getPublicKeyInfo().getEncoded();
byte[] encodedPrivateKey = pair.getPrivateKeyInfo().getEncoded();

// Now convert to Java objects
KeyFactory keyFactory = KeyFactory.getInstance( "RSA");
			
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

KeyPair pair = new KeyPair(publicKey, privateKey);

We now have a KeyPair loaded into memory, but before we can initialize an SSL context we need to get the certificate from the .crt file. We can use the same APi to load the certificate:

PEMParser parser = new PEMParser(new InputStreamReader(certfile));

X509CertificateHolder obj = (X509CertificateHolder) parser.readObject();
Certificate cert = JcaX509CertificateConverter().setProvider("BC").getCertificate(obj);

Now the only thing left to do is to place these into a KeyStore object so we can initialize SSL context.

KeyStore store = KeyStore.getInstance("JKS");
store.load(null);

store.setKeyEntry(alias, pair.getPrivate(), passphrase,	new java.security.cert.Certificate[] { cert });

SpringMVC with Netty

I’m using Spring/Hibernate to provide the Hypersocket REST API on a Netty based HTTP server. Why? well Hypersocket’s main function is a tunnelling server so the first priority is a high performance socket framework. The user interface implementation had to come second to this requirement; I certainly did not want to burden the server with an overweight server-side UI framework so I was looking for something that was lightweight. I also wanted support for Spring/Hibernate since it makes creating my domain model a breeze. So a Javascript based UI accessing REST services provided by SpringMVC controllers sounded ideal.

The problem I faced is that SpringMVC is run in a servlet container and there is no servlet implementation for Netty because the servlet API relies on the standard IO model of using InputStream/OutputStream. I decided to try and implement a lightweight servlet container for Netty so that I could plugin the Spring servlet. Here is a run down of how I managed to get this working.

I created implementations of the following servlet container interfaces. I’ll be posting a fully working example soon so I won’t go into the actual implementations here.

ServletConfig
ServletContext
HttpServletRequest
HttpServletResponse
HttpSession

Now I could start configuring my Spring environment so my domain objects are created in the usual way with a Spring ApplicationContext. Loading any application context files I’ve placed in the classpath:

ApplicationContext applicationContext = 
          new ClassPathXmlApplicationContext(
                 "classpath*:/META-INF/applicationContext.xml");

I had to code the configuration of the SpringMVC context because I don’t have a complete servlet container to configure from a web.xml file. I’ve literally just implemented the basic servlet API that will get the servlet working. So I created a AnnotationConfigWebApplicationContext (as I’m exclusively using annotations) and set my main ApplicationContext as parent:

AnnotationConfigWebApplicationContext webappContext
         = new AnnotationConfigWebApplicationContext();

// Use my main ApplicationContext as parent so it can discover my domain entities.
webappContext.setParent(applicationContext);

Next I register a DelegatingWebMvcConfiguration because I want to add a custom intercept handler for an annotation I will be creating. This will look for @Components that extend the WebMvcConfigurer interface. Even if you don’t want to add your own interceptors you should add this although you can use WebMvcConfigurationSupport instead.

webappContext.register(DelegatingWebMvcConfiguration.class);

Now setup the packages to scan for @Controller annotations:

webappContext.scan("com.hypersocket.example.web.**");

We can now setup our ServletConfig on the AnnotationConfigWebApplicationContext:

servletConfig = new HypersocketServletConfig("default", "/hypersocket");

// Set the servlet config on our AnnotationConfigWebApplicationContext
webappContext.setServletConfig(servletConfig);

Finally we can create the Spring DispatcherServlet:

dispatcherServlet = new DispatcherServlet(webappContext);

dispatcherServlet.init(servletConfig);

And there we have it, a configured DispatcherServlet that is ready to accept requests. The only thing left for us to do is to translate HTTP requests/responses from Netty into HttpServletRequest/HttpServletResponse. Here is my ChannelPipeline which uses Netty’s built-in HTTP encoder/decoder:

public ChannelPipeline getPipeline() throws Exception {
        // Create a default pipeline implementation.
        ChannelPipeline pipeline = pipeline();
        pipeline.addLast("decoder", new HttpRequestDecoder());
        pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
        pipeline.addLast("encoder", new HttpResponseEncoder());
        pipeline.addLast("handler", new HttpRequestDispatcherHandler(server));
        return pipeline;
}

This means when my HttpRequestDispatcherHandler receives a HTTP request all it has do is to translate this into a HttpServletRequest and pass this into the DispatcherServlet along with a HttpServletResponse. Upon return I then translate this back into Netty’s HttpResponse and the request is complete.

There are a number of improvements I could make, one would be to have Netty decode directly into a HttpServletRequest but that would tie the server to the servlet API and might not be appropriate for the tunneling services I’m adding but it may be appropriate for you. Another is the HttpSession support, presently its just a simple factory and some work is needed to ensure sessions are cleaned up after expiry.

I’ve only tested SpringMVC with @Controller classes that are sending/receiving entity objects with the @RequestBody, @ResponseBody annotations. I’ve not tried to use any other feature of SpringMVC so would welcome feedback if others are able to go further.

Prettify plugin issues

I’ve been trying to use the Sunburst Code Prettify plugin but it simply doesn’t render quotes in code correctly….

[prettify class=”java”]String test = “12345657890”;[/prettify]

Eventually i’ve answered my own question… It appears you have to wrap the prettify short code tags in <code> tags. This was not apparent from the installation or documentation of the plugin.

[prettify class="java"]String test = "12345657890";[/prettify]

This example is using Prettify for WordPress plugin.. Just wrap the code snippet in <pre class=”prettyprint”> tag. I’ve decided to go with this one.

String test = "1234567890";

jQuery multiple dialog problem solved

I’ve been creating a dynamic jQuery user interface for Hypersocket and came across a problem with the jQuery dialog. My user interface has a core that dynamically loads ‘modules’ from the menu. This will allow us to plugin new functionality in the future without hard coding menu options. The basic function is for each menu option a html fragment is loaded into a div.

When a user clicks on a new menu option I empty the main content div:

$('#mainContent').empty();

Then load the new modules content:

$('#mainContent').load('modules/content' + name + '.html', function() {
    hideBusy();	
});

The problem I had is that when the page fragment is loaded it was creating a dialog with one of the divs in the fragment, nothing unusual except that JQuery was placing this dialog element in the body of the DOM. This meant it was moved outside of my main content div, so subsequent loads of the modules content would see additional dialog divs being created in the document. This caused problems with my dialogs as some select tags that were loaded based on their id would see multiple versions of the data.

I found the solution here. Simply move the dialog back into the main content div once it has been created.

$('#addRealmForm').dialog({ .. });
$('#addRealmForm').parent().appendTo('#mainContent');

This way when my main content div is emptied, the dialog is removed too. There is only one problem with this, the dialog is constrained to the parent div so if you drag it around the browser it will disappear when its bounds go outside the parent.

This can be resolved with a little more code before we open the dialog:

$('#addRealmForm').parent().appendTo('body');

And when we close the dialog we put it back where we want it in the main div:

$('#addRealmForm').parent().appendTo('#mainContent');

Dropping GWT for jQuery

I’ve been playing around with GWT for a few days and have come to the conclusion its too bloated for my needs. I want Hypersocket to be as lightweight as possible and the GWT UI just doesn’t feel right. I would also have to get over the issues of not being able to run server-side code within GWT itself (because Netty is providing the HTTP layer) and was looking at having to proxy my REST API calls during development.

Using JQuery makes things simpler, and I can get rid of that GWT Eclipse plugin that seems to have slowed down my development environment since it as installed.