Исключение в потоке java .lang.IllegalStateException: шифр не инициализирован - PullRequest
0 голосов
/ 17 июня 2020

Во время выполнения, получение java .lang.IllegalStateException с сообщением, не инициализированным Cipher при расшифровке зашифрованного текста, мой код выглядит следующим образом:

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.IllegalStateException: шифр не инициализирован в javax.crypto.Cipher.checkCipherState (Cipher. java: 1749) в javax.crypto.Cipher.doFinal (Cipher. java: 2156)

и это периодически возникающая проблема, через некоторое время он расшифровывает зашифрованный текст и работает должным образом.

1 Ответ

4 голосов
/ 17 июня 2020
Экземпляры

Cipher с отслеживанием состояния и по своей сути небезопасны для потоков. Вы вообще не должны делиться ими между потоками. И в этом нет необходимости, поскольку они относительно легкие; делая их потокобезопасными, вероятно, замедлит работу приложения больше, чем просто воссоздание экземпляра объекта. Гораздо лучше поместить ключ в поле и поделиться им, если вам нужно повторно использовать ключ. Затем просто вызовите getInstance("AES/OFB/NoPadding") и назначьте его локальной переменной .

Боковое примечание: вы, кажется, делаете две ошибки: cipher - это поле (первое error), но поскольку он инициализируется каждый раз в пределах decrypt (вторая ошибка), вы можете фактически заменить экземпляр объекта, используемый в другом потоке, что приведет к ошибке, которую вы получаете сейчас. То, что вы не получите ошибку позже, просто означает, что вам повезло: программа ошибочна и может впоследствии взломать sh.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...