Using a symmetric encryption system has a couple of drawbacks. Since only one key can decrypt a message, you must send it with the message, introducing the risk that someone could intercept the key. In addition, every recipient must have a different key, so you have to deal with key management.

Asymmetric encryption gets around these problems by requiring both a public and private key. Using your public key, anyone can encrypt a message that can be deciphered only with your private key. Although you must guard your private key, your public key can be given away freely or placed in a central repository for anyone to access. In this article, I will explain how to use the Java Cryptography Extension (JCE) to take advantage of asymmetric cryptography. Before getting started, download the complete example code.

Background reading

The first two articles of this series dealt with symmetrical ciphers:

Using JCE
JCE provides an API to utilize asymmetric cryptography. The first step is to generate a public and private key pair, as shown in this code snippet:
KeyPairGenerator kpg = null;
kpg = KeyPairGenerator.getInstance(“RSA”, “BC”);
kpg.initialize(1024, new SecureRandom());
KeyPair kp = kpg.generateKeyPair();
PrivateKey priKey = kp.getPrivate();
PublicKey pubKey = kp.getPublic();

Here, the getInstance method of KeyPairGenerator accepts two parameters—the implementation and the provider. All examples in this article use the Bouncy Castle (BC) provider. After getting an instance of a KeyPairGenerator, you must initialize it, indicating the level of security you want. In this case, you are writing a 1024-bit key. Next, you create a KeyPair. From the KeyPair object, you access the public and private keys. In our example code, these keys are stored on the file system for future use.

Watch out for this gotcha
Once you have access to the keys, encrypting data is simple. But you must be careful to not overrun the block size when encrypting and decrypting data. Let’s take a look at a code snippet from the method crypt in our example code:
cipher.init(type, key);
out = new ByteArrayOutputStream();
int s = cipher.getBlockSize();
int r = 0;
for (int t = 0; t < text.length; t += s) {
if (text.length – t <= s) {
r = text.length – t;
} else {
r = s;
out.write(cipher.doFinal(text, t, r));

After initializing the cipher, you set up a new ByteArrayOutputStream to write the encrypted/decrypted data to. Then, using the block size, you loop over your target text and encrypt/decrypt chunks that are less than or equal to our cipher’s block size. If you attempt to encrypt/decrypt data that is larger than the block size, the action will fail and an exception will be thrown.

Better security
If you encrypt with a symmetric system, you run the risk that someone will intercept the key and read encrypted messages. With an asymmetric approach, messages are safeguarded through the use of both a public and private key. As the example code shows, with just a few helper methods to read and write keys, it is easy to implement this more secure way of exchanging data.

Another cup of Joe

Has JCE worked for you? Post a comment below and describe your experiences.