Old and tired?

Right now i’m at the #jaxcon in Munich. While sitting in a talk, this tweet by @cuchulin caught my attention:

I really don’t think that’s Java who’s old and tired, neither as a language nor an ecosystem. It’s the people, who not only are looking tired but who are. Well, at least, I am.

I’m a curious person and always eager to learn new stuff but the last 3, 4 years the learning process and the stream of new tools, techniques, frameworks and other stuff accelerated even more than it did in the transition from client/server development to multi-tier-architectures 10 years ago.

At each conference there are new tools. New tools to “get things done”, new paradigms to organize your work and new tools to create stuff. It’s getting real hard to choose and if you want to get your head around the full stack, you’ve plenty of stuff to try, read and experiment on.

The last 2 years saw the coming of so many new languages. Some will vanish, some will stay, but it’s for sure: Another field of learning.

Given that situation plus the stream of information we get the whole day now (tweets, g+, facebook and more) it’s a tiring situation. Most of the people in the talks sit in front of their laptops or have an iPad and are constantly checking twitter and the like. Who wouldn’t be tired?

I really appreciated Adam Beans Talk “Just developed” yesterday. We really need to focus more on the things we want to create and to some extend less on the tools and methodologies.

On a personal note: I am tired. Not because of my “hard” family life with a 2-year-old, absolutely no. I just can’t really turn of my head anymore. The boundaries between work, home and spare time are diminishing. Most of the time it’s a good thing because i can spend more time at home with my family but on the other hand i have all the stuff to think about, to read and to try out often for the late evening and then they are to stay in my head.

| Comments (4) »

09-Nov-11



Java and invalid SSL certificates (java-trustprovideragent)

It’s truly easy to generate a SSL certificate for example to use with tomcat (see here). This certificate is invalid as it is self-signed by you and it often doesn’t match the hostname. This is no problem when your access the project with a browser, with more or less jumps through hoops you accept the development certificate and you’re done.

If you access the site through java itself you’ll have problem with all tools that basically use an URLConnection. You’ll end up with an exception like this:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target

This is will hit you for example using HtmlUnit or my oembed client.

It isn’t enough to import the certificate in question using keytool (at least, it didn’t work for me).

I search and i found this post titled “SSL Trust Provider for Java”. Interesting stuff.

This works by providing a “java.security.Provider” through the Security API accepting all certificates. Nice tip, thanks!

I didn’t want to change my sources though so i wrote a very little java agent to instrument my development setup. I also added a “javax.net.ssl.HostnameVerifier” that accepts all host names, in case the certificates cn doesn’t match the development machines hostname. If i want my vm to trust all and everything, i just add “-javaagent:full/path/to/java-trustprovideragent-0.0.1-SNAPSHOT.jar”.

The code is on github java-trustprovideragent, please feel free to use it.

Thanks to the original authors on devcentral.f5.com.

| Comments (0) »

25-Jul-11


MySql compatible AES encryption / decryption in Java

MySQL has an aes_encrypt/aes_decrypt pair of functions (Encryption and Compression Functions) that enable encryption and decryption of data using the official AES algorithm.

The functions are easy to use (select AES_ENCRYPT(‘text’,’password’)) and the result is easy to store (insert into secrets values HEX(AES_ENCRYPT(‘text’,’password’))) as hex values.

I used this technique for a while but i wanted to have a more database agnostic version of this encryption and tried to build the same methods with java.

Although it was relatively easy to find the exact cipher mode (which is AES/ECB/PKCS5Padding), i had a real hard time figuring out how the key is calculated from the given password (the key must be 16bytes long, per default MySql uses AES-128). It turns out that the MySQL algorithm just or’s the bytes of a given passphrase against the previous bytes if the password is longer than 16 chars and just leaves them 0 when the password is shorter than 16 chars. So you can generate a secret key spec in Java for an aes_encrypt/decrypt compatible cipher like so:

import java.io.UnsupportedEncodingException;
 
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
 
import org.apache.commons.codec.binary.Hex;
 
public class Demo {
	public static SecretKeySpec generateMySQLAESKey(final String key, final String encoding) {
		try {
			final byte[] finalKey = new byte[16];
			int i = 0;
			for(byte b : key.getBytes(encoding))
				finalKey[i++%16] ^= b;			
			return new SecretKeySpec(finalKey, "AES");
		} catch(UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
 
	public static void main(String... args) throws Exception {
		// Decrypt
		final Cipher decryptCipher = Cipher.getInstance("AES");	        				
		decryptCipher.init(Cipher.DECRYPT_MODE, generateMySQLAESKey("your super secret passphrase", "UTF-8"));
		System.out.println(new String(decryptCipher.doFinal(Hex.decodeHex("56A34D7AB6225616799F6559AA388F07C2C9E53983111BDD5F49F36461AAD789".toCharArray()))));
 
		// Encrypt
		final Cipher encryptCipher = Cipher.getInstance("AES");	        				
		encryptCipher.init(Cipher.ENCRYPT_MODE, generateMySQLAESKey("your super secret passphrase", "UTF-8"));		
		System.out.println(String.format("Select aes_decrypt(unhex('%s'), 'your super secret passphrase');", new String(Hex.encodeHex(encryptCipher.doFinal("Hallo nach Aachen".getBytes("UTF-8")))))); 
	}
}

You need Commons Codec to run these.

This isn’t probably the most secure solution from a cryptographic point of view but it just replicates the built-in MySql function for other databases or just for interoperability. I hope to save someone else time with this as i spent about days about those view lines.

| Comments (14) »

18-Jul-11


Apache httpd, Tomcat und sendfile

I used to use mod_xsendfile by Nils Maier, who’s Homepage doesn’t seem to exist anymore, to send files from Ruby proxied by Apache respectively powered by modrails. Those files shouldn’t be in any public www directory as authorization needs to be checked, but are accessed very often so that streaming them is not an option.

To use this technique you need mod_xsendfile, which is attached to this post.

I just have rewritten my application from Ruby on Rails to Java and it’s easy to add the necessary headers in a HttpServletResponse:

response.setHeader("X-Sendfile", file.getAbsolutePath());
response.flushBuffer();

You may add other headers like Content-Type and the like but you must not modify the body, hence the flushBuffer.

This works quite well… As long as had my Apache httpd running with mpm-prefork.

Switching to Apache mpm-worker caused some problems. I cannot say with a final conclusion that mod_xsendfile was causing troubles but i started to see the wrong files (images in this case) delivered or not delivered at all.

My alternate solution was streaming the files using Channels from java.nio but CPU usage went nuts.

The solution now employed is the using Apache Tomcats asynchronous writes that are available since Tomcat 6. Their documentation is rather short but so is implementing them:

/*
HttpServletRequest request = ...
HttpServletResponse response = ...
*/
 
if(request != null && Boolean.TRUE.equals(request.getAttribute("org.apache.tomcat.sendfile.support"))) {		
  long l = file.length();
  request.setAttribute("org.apache.tomcat.sendfile.filename", absolutePath);
  request.setAttribute("org.apache.tomcat.sendfile.start", 0l);
  request.setAttribute("org.apache.tomcat.sendfile.end", l);
  response.setHeader("Content-Length", Long.toString(l));
  response.flushBuffer();
} else if(use_xsendfile) {
  // see above
} else {
  // stream files
}

What i got wrong at first was setting those attributes in the response. That didn’t work. The must be set in the request and you must take care setting all of those and with the correct type (String respectively long). And that’s it.

The request attribute org.apache.tomcat.sendfile.support will be true when the connector is configured to either use the APR connector (org.apache.coyote.http11.Http11AprProtocol) or the non blocking Java connector (org.apache.coyote.http11.Http11NioProtocol) (the later one being easier to deploy as it has no external dependencies).

CPU usage for sending those files is now nearly 0.

| Comments (0) »

28-Jun-11