java.lang.IllegalStateException:未初始化密码

我在Android应用程序中实现了加密/解密。

我添加了一个已经成为Singleton类的Encryption类。

部分代码如下:

public class Encryption { private SecretKeySpec mKey = null; private Cipher mCipher = null; private byte[] mKeyBytes = null; private AlgorithmParameterSpec mParamSpec = null; private static Encryption sInstance; public Encryption() { byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; mParamSpec = new IvParameterSpec(iv); mKeyBytes = getMD5(MD5_KEY.getBytes(); mKey = new SecretKeySpec(mKeyBytes, AES_TAG); try { mCipher = Cipher.getInstance(TRANSFORMATION_STR); } catch (NoSuchAlgorithmException e) { } catch (NoSuchPaddingException e) { } } public static synchronized Encryption getInstance() { if (sInstance == null) { sInstance = new Encryption(); } return sInstance; } public String encryptString(String strPwd) { String strToEncripted = null; strToEncripted = strPwd; String result = null; byte[] input = null; byte[] cipherText = null; int ctLength = 0; try { input = strToEncripted.getBytes(UTF8_STR); mCipher.init(Cipher.ENCRYPT_MODE, mKey, mParamSpec); cipherText = new byte[mCipher.getOutputSize(input.length)]; ctLength = mCipher.update(input, 0, input.length, cipherText, 0); ctLength += mCipher.doFinal(cipherText, ctLength); result = Base64.encodeToString(cipherText, Base64.DEFAULT) .replace(NEWLINE_CHAR, EMPTY_CHAR).trim(); } catch (InvalidKeyException e) { } catch (UnsupportedEncodingException e) { } catch (InvalidAlgorithmParameterException e) { } catch (ShortBufferException e) { } catch (IllegalBlockSizeException e) { } catch (BadPaddingException e) { } catch (IllegalStateException e) { } return result; } public String decryptstring(byte[] encripted) { String textDecrypt = ""; byte[] encriptedByteDecode64 = Base64.decode(encripted, Base64.DEFAULT); byte[] plainText = new byte[mCipher.getOutputSize(encriptedByteDecode64.length)]; int ptLength = 0; try { mCipher.init(Cipher.DECRYPT_MODE, mKey, mParamSpec); ptLength = mCipher.update(encriptedByteDecode64, 0, encriptedByteDecode64.length, plainText, 0); ptLength += mCipher.doFinal(plainText, ptLength); textDecrypt = (new String(plainText)).trim(); } catch (InvalidKeyException e) { } catch (InvalidAlgorithmParameterException e) { } catch (ShortBufferException e) { } catch (IllegalBlockSizeException e) { } catch (BadPaddingException e) { } return textDecrypt; } private String getMD5(String strKey) { String key = strKey; String result = null; try { MessageDigest algorithm = MessageDigest.getInstance(MD5_TAG); algorithm.reset(); algorithm.update(key.getBytes(UTF8_STR)); byte messageDigest[] = algorithm.digest(); StringBuilder hexString = new StringBuilder(); for (int count = 0; count < messageDigest.length; count++) { String hexaDecimal = Integer.toHexString(0xFF & messageDigest[count]); while (hexaDecimal.length() < 2) hexaDecimal = new StringBuilder(ZERO_STR).append(hexaDecimal).toString(); hexString.append(hexaDecimal); } result = hexString.toString(); } catch (NoSuchAlgorithmException e) { } catch (UnsupportedEncodingException e) { } return result; } } 

使用单例实例,字符串的加密和解密被实现并且它们主要工作。

有时候,虽然密码已经初始化,但它仍然抛出exception: java.lang.IllegalStateException: Cipher not initialized

该场景主要是在经过一段时间间隔(30分钟)后,执行字符串解密。

可能是由于Singleton实例的错误使用?

而不是Singleton类,我试图使用new运算符加密字符串创建Encryption类的实例,但问题是我需要相同的对象进行解密,否则抛出java.lang.IllegalStateException: Cipher not initialized

欢迎任何建议/提示。

这个问题肯定会发生在multithreading环境中,就像我遇到的那样。 问题是mCipher.init()和mCipher.doFinal()方法之间的冲突。

以下是Cipher类中的相关方法:

 public final void init(int opmode, Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { init(opmode, key, params, JceSecurity.RANDOM); } public final void init(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { initialized = false; checkOpmode(opmode); if (spi != null) { checkCryptoPerm(spi, key, params); spi.engineInit(opmode, key, params, random); } else { chooseProvider(I_PARAMSPEC, opmode, key, params, null, random); } initialized = true; this.opmode = opmode; } public final int doFinal(byte[] output, int outputOffset) throws IllegalBlockSizeException, ShortBufferException, BadPaddingException { checkCipherState(); // Input sanity check if ((output == null) || (outputOffset < 0)) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); return spi.engineDoFinal(null, 0, 0, output, outputOffset); } private void checkCipherState() { if (!(this instanceof NullCipher)) { if (!initialized) { throw new IllegalStateException("Cipher not initialized"); } if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.DECRYPT_MODE)) { throw new IllegalStateException("Cipher not initialized " + "for encryption/decryption"); } } } 

在multithreading环境中查看initialized变量的行为,其中两个线程执行init()和doFinal()。 返回的Exception与未实际初始化的对象无关,但initialized变量设置为false

我通过同步我的encryptString()和decryptString()方法解决了我的问题。 希望您可以通过Cipher代码获得一些见解。

在您的decryptstring方法中,您可以调用

 byte[] plainText = new byte[mCipher.getOutputSize(encriptedByteDecode64.length)]; 

在你打电话之前几行

 mCipher.init(Cipher.DECRYPT_MODE, mKey, mParamSpec); 

由于当您在其上调用getOutputSize时,密码尚未初始化,因此您将获得exception。 重新排序这些行应该修复它。 (它对我有用。)

我遇到了同样的问题( Cipher not initialized )。 我使用的是高加密技术,对我来说,解决方案是使用无限强度版本替换jre/lib/security的常规策略jar。