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

Kri*_*hna 1 java encryption multithreading cryptography illegalstateexception

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

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;
    }
Run Code Online (Sandbox Code Playgroud)

线程“pool-5-thread-3”中的异常java.lang.IllegalStateException:密码未在javax.crypto.Cipher.doFinal(Cipher.java:2156)处的javax.crypto.Cipher.checkCipherState(Cipher.java:1749)处初始化)

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

Maa*_*wes 7

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

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

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