Handling Java Crypto Exceptions

Handling Java crypto exceptions

You indicated the following exceptions:

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException

Now all of these are GeneralSecurityException's, so it would be easy to catch them all. But looking at the use case, you probably don't want to do that.


If you look at the cause of the exceptions then you will find that any of these exceptions - except for the last two - are only thrown when generating an implementation of an algorithm or a key. I think it is reasonable that once you have tested your application that these values remain more or less static. Hence it would be logical to throw - for instance - an IllegalStateException. IllegalStateException is a runtime exception which you are not required to throw (in the method signature) or catch. Of course, you should include the security exception as being the cause of the exception.


Now the last two exceptions, BadPaddingException and IllegalBlockSizeException are different. They depend on the actual ciphertext, so they are dependent on the input of the algorithm. Now normally you should always verify the integrity of the input before you feed it into your Cipher instance, initiated for decryption, for instance by first validating a HMAC checksum). So in that sense you could still get away with a runtime exception. If you don't perform a separate check for integrity then you should do should not convert to a RuntimeException. Instead you could either let the user handle the exception, or re-throw it as a use case specific exception.

If you handle the BadPaddingException by (re-)throwing it then should understand about plaintext oracle attacks such as padding oracle attacks. For padding oracle attacks in CBC mode: if an adversary can try and let you decrypt ciphertext multiple times and receive an indication that decryption failed (or not) then they can retrieve the plaintext of the message without breaking the cipher. For this reason an authenticated mode such as GCM mode should be preferred in situations that can handle the 16 additional bytes for the authentication tag.


It is probably best to use separate try/catch blocks for the construction and initialization of the Cipher and the decryption itself. You could also catch the exceptions BadPaddingException and IllegalBlockSizeException before handling the GeneralSecurityException. Starting with Java 7 you may use multi-catch statements as well (e.g. catch(final BadPaddingException | IllegalBlockSizeException e)).


Finally some notes:

  • BadPaddingException and IllegalBlockSizeException may be thrown by Cipher because the data was not completely received, but it may also be because of an attacker messing with the data;
  • BadPaddingException may also be thrown if the key is incorrect.
  • Beware that an exception may be thrown for AES key sizes 192 bit and 256 bit if the unlimited crypto files are not being installed (check the Oracle JavaSE site for more info); you should check if the key size is permitted when the application is started (this is mainly true for old / deprecated versions of Java). Newer versions of Java do not require these unlimited crypto files.

Java Cryptography throwing Exception while initializing Cipher: java.security.InvalidKeyException: Illegal key size

java.security.InvalidKeyException: Illegal key size indicates that you have not installed the JCE (Java Cryptography Extension). It is needed for AES256

For Java 8 you can download it here:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

Java decryption throws an exception

As exception stack says, length must be multiple of 8.

So, length of 8, 16, 24,... are valid for key bytes.

Try with length of 8 (12345678)

byte key_bytes[] = "12345678".getBytes();

If error persists, you can follow this answer

Updated

If you want to use URLDecoder, try with this code in your decrypt method,

String decryptd = URLDecoder.decode(value, "UTF-8");
byte[] dec = new Base64().decode(decryptd);
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8, "UTF-8");

Request processing failed; nested exception is javax.crypto.BadPaddingException: Decryption error

My problem is solved by doing this.
I have made the Ciphers static and initialized them in static blocks.
Then I am using the same ciphers in both controller methods.

private static Cipher AESCipher = null;
private static Cipher RSACipher = null;

static {
try {
AESCipher = Cipher.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}

static {
try {
RSACipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}


Related Topics



Leave a reply



Submit