InvalidKeyException

java.security.InvalidKeyException – How to solve InvalidKeyException

In this example we are going to talk about java.security.InvalidKeyException. It is probably the most common exception you will stumble upon when handling encryption in your Java application. java.security.InvalidKeyException is a subclass of java.security.KeyException which in turn is a subclass of java.security.GeneralSecurityException.

As the name suggests, InvalidKeyException emerges when there is something wrong with the encryption key you are trying to use in one of your encryption algorithms. Most common problems with encryption keys include wrong length of the key, invalid encoding, and of course wrong initialization of the key (probably the key is NULL…).

To demonstrate this Exception we are going to create a simple application with a utility class that is able of performing AES encryption.

1. A simple Encryption/Decryption Application

The purpose of this example is not to dive deep in the AES encryption standard, nor to the implementation of this algorithm in Java. Nevertheless here is a simple utility class that can encrypt and decrypt a Java String, considered as the plaintext.

AESUtils.java:

package com.javacodegeeks.core.security;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
public class AESUtils {
	
  static String INITIALIZATIO_VECTOR = "AODVNUASDNVVAOVF";
  
  public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
    return cipher.doFinal(plainText.getBytes("UTF-8"));
  }
 
  public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
    return new String(cipher.doFinal(cipherText),"UTF-8");
  }
}

This class has to static utility methods :

  • encrypt: Takes the plain text and the encryprion key as input and produces the cipher text with UTF-8 encoding.
  • decrypt: Takes the cipher text and the encryprion key as input and produces the plain text with UTF-8 encoding.
package com.javacodegeeks.core.security;

public class InvalidKeyExceptionExample {

	static String PLAIN_TEXT = "Java Code Geeks Rock!\0\0\0\0\0\0\0\0\0\0\0";
	static String ENCRYPTION_KEY = "0123456789abcdef";

	public static void main(String [] args) {
		try {

			System.out.println("Plain text:" + PLAIN_TEXT);

			byte[] cipherText = AESUtils.encrypt(PLAIN_TEXT, ENCRYPTION_KEY);

			System.out.print("Cipher Text:  ");
			for (int i=0; i<cipherText.length; i++)
				System.out.print( String.format("%02X ",cipherText[i]));

			System.out.println("");

			String decrypted = AESUtils.decrypt(cipherText, ENCRYPTION_KEY);

			System.out.println("Decrypted Text: " + decrypted);

		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}

The above class uses the AESUtils in order to encrypt and decrypt a String. Here is the output when you run it:

Plain text  :Java Code Geeks Rock!
Cipher Text:  22 01 BF DB 8E F5 CD 85 99 42 CE 3C 25 4F 05 54 7B EB FC 3C 2F F4 7C 36 AC 7F F4 DC 3E A7 A5 55 
Decrypted Text  : Java Code Geeks Rock!

2. A simple example of InvalidKeyException

Now, by default JDK 1.7, can use AES 128-bit encryption, which means that the key has to be 128 bits long. Additionally the plain text has to be a multiple of 16 – that is why you see some null padding at the end of PLAIN_TEXT . So now, Let’s try to double the size of the encryption key to 256 bits. You can quickly do that :

Change

static String ENCRYPTION_KEY = "0123456789abcdef";

to

static String ENCRYPTION_KEY = "0123456789abcdef0123456789abcdef";

Here is the output when you run it:

Plain text  :Java Code Geeks Rock!
java.security.InvalidKeyException: Illegal key size
	at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1024)
	at javax.crypto.Cipher.init(Cipher.java:1345)
	at javax.crypto.Cipher.init(Cipher.java:1282)
	at com.javacodegeeks.core.security.AESUtils.encrypt(AESUtils.java:14)
	at com.javacodegeeks.core.security.InvalidKeyExceptionExample.main(InvalidKeyExceptionExample.java:13)

So by default the key size is not supported. This is the most common case of InvalidKeyException.

Another common case as well is when the encryption key is not a power of 2 (in most modern implementation the key should be at least 56 bits). For example:

Change

static String ENCRYPTION_KEY = "0123456789abcdef0123456789abcdef";

to

static String ENCRYPTION_KEY = "0123456789abcde";

Here is the output when you run it:

Plain text  :Java Code Geeks Rock!
java.security.InvalidKeyException: Invalid AES key length: 15 bytes
	at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:372)
	at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)
	at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1023)
	at javax.crypto.Cipher.init(Cipher.java:1345)
	at javax.crypto.Cipher.init(Cipher.java:1282)
	at com.javacodegeeks.core.security.AESUtils.encrypt(AESUtils.java:14)
	at com.javacodegeeks.core.security.InvalidKeyExceptionExample.main(InvalidKeyExceptionExample.java:13)

3. How to solve InvalidKeyException

The first thing you should do when you come up with this exception, is check if your encryption key is correctly initialized (not NULL). Then make sure that its length in bits is a power of two. If you want to use a String as your encryption key you should check its length in bytes and multiply by 8 to find the length in bits. The safest way  to do that is first to convert the String in a byte array and then check the array’s length. You should keep in mind that in most JVM 64-bit implementation each character in the String takes up 2 bytes.

After checking all the above you should make sure that your encryption engine supports key of that length. If you have to use 256-AES or more here is what you should do:

  1. Visit Oracle’s website and put ‘Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files’ on the search box. Here is the quick link with the results I’ve got : http://tinyurl.com/m65q5ax
  2. Then follow the link ‘Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7 Download’
  3. Download UnlimitedJCEPolicyJDK7.zip
  4. Extract the folder. Inside you will find local_policy.jar and US_export_policy.jar.
  5. Go to your Java installation directory (aka JAVA_HOME) and find : JAVA_HOME/jre{version_number}/lib/security. Paste these two files. Files with the same names will most probably be there already. You need to replace them with the new files.

That’s it. You can now restart your project and use 256-AES, 512-AES and so on.

Download the Source Code

This was an example on java.security.InvalidKeyException and How to solve InvalidKeyException.

Download
You can download the full source code of this example here : InvalidKeyExceptionExample.zip

Nikos Maravitsas

Nikos has graduated from the Department of Informatics and Telecommunications of The National and Kapodistrian University of Athens. During his studies he discovered his interests about software development and he has successfully completed numerous assignments in a variety of fields. Currently, his main interests are system’s security, parallel systems, artificial intelligence, operating systems, system programming, telecommunications, web applications, human – machine interaction and mobile development.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button