Thursday, September 15, 2016

How-To Diffie-Hellman key exchange in Java

Public key exchange is an interesting topic in the field of cryptography nowadays. Many sites and web services offer Perfect Forward Secrecy, protecting their users against future compromise of long-term keys. This protection is possible thanks to algorithms such as Diffie-Hellman (DH) and Elliptic Curve Diffie-Hellman (ECDH).

Implementing these techniques in your Java application is not the most straightforward thing to do. Luckily, the library that I used in my past article How-To encrypt a file in Java has convenient classes that greatly simplify the job. A shared secret can therefore be exchanged using Diffie-Hellman in just a few lines of code:
// Tip: You don't need to regenerate p; Use a fixed value in your application
int bits = 2048;
BigInteger p = BigInteger.probablePrime(bits, new SecureRandom());
BigInteger g = new BigInteger("2");

// Create two peers
KeyAgreementPeer peerA = new DHPeer(p, g);
KeyAgreementPeer peerB = new DHPeer(p, g);

// Exchange public keys and compute shared secret
byte[] sharedSecretA = peerA.computeSharedSecret(peerB.getPublicKey());
byte[] sharedSecretB = peerB.computeSharedSecret(peerA.getPublicKey());

Note: The p and g values here are not necessarily representative for production use. Use precomputed primes in order to be safe. A good starting point would be https://tools.ietf.org/html/rfc3526.

Performing a public key exchange using the Elliptic Curve Diffie-Hellman (ECDH) algorithm is done slightly different:
String algorithm = "brainpoolp512r1";

// Create two peers
KeyAgreementPeer peerA = new ECDHPeer(algorithm);
KeyAgreementPeer peerB = new ECDHPeer(algorithm);
 
// Exchange public keys and compute shared secret
byte[] sharedSecretA = peerA.computeSharedSecret(peerB.getPublicKey());
byte[] sharedSecretB = peerB.computeSharedSecret(peerA.getPublicKey());
The ECDH peer class requires Bouncy Castle in order to work. Luckily this is already an import in the Encryptor4j project's build.gradle file.

Find out which elliptic curves are supported by Bouncy Castle here.

Sunday, September 11, 2016

How-To serialize and deserialize Java objects to and from XML

Serialization is a powerful feature included in the Java framework. It allows for transporting and storing objects with great ease and flexibility. One drawback however is that the objects are serialized into a binary format and thus are hard to read or alter. That's where XML serialization comes in.

There are many XML serialization libraries available but many do not support popular Java classes out-of-the-box. One exception however, is XMLSerializer4j. It can serialize collections and most frequently used classes without requiring you to write your own serialization logic.

Serializing any object to an XML file is easy:
XMLSerializer xmlSerializer = new XMLSerializer();
xmlSerializer.serialize(myObject, "MySerializedObject.xml");

Deserialize the XML back to an object like this:
XMLSerializer xmlSerializer = new XMLSerializer("MySerializedObject.xml");
Object myObject = xmlSerializer.deserialize();

By default the output will be stripped of unnecessary whitespace and line-breaks to save space. If however a human readable output is desired with line-breaks and indentation do this:
xmlSerializer.setTransformer(XMLSerializer.HUMAN_READABLE_TRANSFORMER);

Check out the documentation at the project's webpage for further explanation.

Thursday, September 8, 2016

How-To encrypt a file in Java

Encrypting files in Java is easy! Typically it would require loads of boilerplate that only increases the chance of doing something wrong, thus breaking security. Luckily there are safe and sound libraries that can help us perform the task at hand with relative ease.

One of these is Encryptor4j. Download and include it in your project before the next step.

Encrypting a file would be as simple as this:
// We use a password based key here.
// Other options are available too: check the documentation
File srcFile = new File("original.zip");
File destFile = new File("original.zip.encrypted");
String password = "mysupersecretpassword";
FileEncryptor fe = new FileEncryptor(password);
fe.encrypt(srcFile, destFile);
By default, this would encrypt the file using AES with 128-bit keys using CTR mode. If however Unlimited Strength Jurisdiction Policy files are installed it would be encrypted with the maximum key length of 256-bits.

The key is generated from the password using 65536 salted hashing iterations. If you need to regenerate the key from the password in another language check out the KeyFactory implementation used internally by the FileEncryptor class.

Decrypting the file is easy too (it's almost identical to encrypting):
File srcFile = new File("original.zip.encrypted");
File destFile = new File("decrypted.zip");
String password = "mysupersecretpassword";
FileEncryptor fe = new FileEncryptor(password);
fe.decrypt(srcFile, destFile);
This about sums it up. Why reinvent the wheel if an existing library can choose the right block mode, key length and generates and prepends IVs transparently for your convenience.

Monday, May 30, 2016

XMLSerializer4j

A while ago I was working on an application that required me to simply dump a Java object tree to an XML file and make a snapshot of the application's state. After having tried a couple of solutions such as JAXB, Castor, XStream and SimpleXML I found that all of them were lacking in one way or another.

That's why I rolled my own XML serializer library that is currently available on GitHub: XMLSerializer4j

In one sentence: It just works. All popular Java classes are supported out-of-the-box with easy extensibility just around the corner. It has good performance, supports circular references and even serializes static references and restores static final objects to their former state.

Having overshot my earlier requirements, it can be used as a complete serialization/deserialization solution in any Java application.

No more having to write boilerplate code to serialize and deserialize maps, collections, dates, URLs and what have you :)