Reputation: 83
At runtime, getting java.lang.IllegalStateException with Cipher not initialized message while decypting ciphertext my code is as below:
public String decrypt(String cipherText) throws SecurityException {
String clearText = null;
try {
cipher = Cipher.getInstance("AES/OFB/NoPadding");
byte[] cipherTextBytes = Base64.decodeBase64(cipherText.getBytes());
byte[] iv = ArrayUtils.subarray(cipherTextBytes, 0, INIT_VECTOR_LENGTH);
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] decryptedBytes = cipher
.doFinal(ArrayUtils.subarray(cipherTextBytes, INIT_VECTOR_LENGTH, cipherTextBytes.length));
clearText = new String(decryptedBytes, CHARACTER_ENCODING).trim();
} catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException
| NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException e) {
throw new SecurityException(e);
}
return clearText;
}
Exception in thread "pool-5-thread-3" java.lang.IllegalStateException: Cipher not initialized at javax.crypto.Cipher.checkCipherState(Cipher.java:1749) at javax.crypto.Cipher.doFinal(Cipher.java:2156)
and this is intermittent issue, after some time it decrypts ciphetext and works as expected.
Upvotes: 1
Views: 2308
Reputation: 93958
Cipher
instances are a stateful and inherently not thread safe. You should not share them between threads at all. And there is no need either, as they are relatively lightweight objects; making them thread safe would probably slow down the application more than simply recreating the object instance. It is much better to put the key into a field and share that if you need key reuse. Then simply call getInstance("AES/OFB/NoPadding")
and assign the Cipher
instance to a local variable.
Side note: the code seems to contain two issues: cipher
is a field (first issue), but as it is initialized each time within decrypt
(second issue). That means that the the init
call may actually replace the object instance for CipherSpi
or Security.Service
(i.e. the implementation of the cipher) from within another thread, leading to the error you are getting now.
As always with multi-threading, it may well be that you don't get an error in specific circumstances: the program is however erroneous and may crash later on.
Upvotes: 9