线程 java.lang.IllegalStateException中的异常:密码未初始化



在运行时,在解密密文时获取java.lang.IllegalStateException with Cipher not initialized message 我的代码如下:

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;
}

线程"pool-5-thread-3"java.lang 中的异常。非法状态异常:密码未初始化 at javax.crypto.Cipher.checkCipherState(Cipher.java:1749( at javax.crypto.Cipher.doFinal(Cipher.java:2156(

这是间歇性问题,一段时间后它会解密 cipheText 并按预期工作。

Cipher实例是有状态的,本质上不是线程安全的。您根本不应该在线程之间共享它们。也没有必要,因为它们是相对轻巧的物体;使它们线程安全可能会比简单地重新创建对象实例更慢地减慢应用程序的速度。如果需要重用密钥,最好将密钥放入字段中并共享。然后只需调用getInstance("AES/OFB/NoPadding")并将Cipher实例分配给局部变量

旁注:代码似乎包含两个问题:cipher是一个字段(第一个问题(,但每次都在decrypt内初始化(第二个问题(。这意味着init调用实际上可能会从另一个线程中替换CipherSpiSecurity.Service的对象实例(即密码的实现(,从而导致您现在得到的错误。

与多线程一样,在特定情况下您很可能不会遇到错误:但是程序是错误的,以后可能会崩溃。

最新更新