java.lang.IllegalStateException:密码未初始化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10356137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.IllegalStateException: Cipher not initialized
提问by chiranjib
I have implemented Encryption / Decryption in Android application.
我已经在 Android 应用程序中实现了加密/解密。
I have added an Encryption class which has been made a Singleton class.
我添加了一个 Encryption 类,该类已成为 Singleton 类。
Part of the code as follows:
部分代码如下:
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;
}
}
Using the singleton instance , encryption & decryption of string are implemented & they are working mostly.
使用单例实例,实现了字符串的加密和解密,并且它们大部分都在工作。
Sometimes , though the cipher has been initialised , still its throwing an Exception: java.lang.IllegalStateException: Cipher not initialized
有时,虽然密码已被初始化,但仍会抛出异常: java.lang.IllegalStateException: Cipher not initialized
The scenario is mostly when after some time-interval (30 mins), a decryption of string is performed.
该场景主要是在一段时间间隔(30 分钟)后执行字符串解密。
Can it be due to the incorrect use of Singleton instance?
会不会是因为错误使用了 Singleton 实例?
Instead of Singleton class , I have tried to encrypt string creating an instance of Encryption class using the new operator , but the problem is I need the same object for decryption , else the java.lang.IllegalStateException: Cipher not initialized
is thrown.
我尝试使用 new 运算符来加密字符串,而不是 Singleton 类,以创建 Encryption 类的实例,但问题是我需要相同的对象进行解密,否则java.lang.IllegalStateException: Cipher not initialized
会抛出。
Any suggestions / hints are welcome.
欢迎任何建议/提示。
回答by AStyle1
This problem is bound to occur in a multi threaded environment, as it happened to me. The issue is a clash between mCipher.init() and mCipher.doFinal() methods.
这个问题在多线程环境下肯定会出现,我就遇到过。问题是 mCipher.init() 和 mCipher.doFinal() 方法之间的冲突。
Following are the related methods in Cipher class:
以下是 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");
}
}
}
See the behavior of the initialized
variable in a multi threaded environment with two threads executing init() and doFinal(). The Exception returned is not related to the object not being actually initialized but the initialized
variable being set to false
.
查看initialized
变量在多线程环境中的行为,其中有两个线程执行 init() 和 doFinal()。返回的异常与未实际初始化的对象无关,但与initialized
变量设置为无关false
。
I solved my issue by synchronizing my encryptString() and decryptString() methods. Hope you can get some insight by going through the Cipher code.
我通过同步我的 encryptString() 和decryptString() 方法解决了我的问题。希望您可以通过阅读密码代码获得一些见解。
回答by Trenton
In your decryptstring
method, you call
在你的decryptstring
方法中,你调用
byte[] plainText = new byte[mCipher.getOutputSize(encriptedByteDecode64.length)];
a few lines before you call
在你打电话之前几行
mCipher.init(Cipher.DECRYPT_MODE, mKey, mParamSpec);
Since the cipher is not yet initialized when you call getOutputSize on it, you get the exception. Reordering these lines should fix it. (It did for me.)
由于当您对其调用 getOutputSize 时密码尚未初始化,因此您会收到异常。重新排序这些行应该可以解决它。(它对我有用。)
回答by Kushal Bhandari
Make sure you call Cipher.getInstance()
in your encrypt and decrypt methods.
确保您调用Cipher.getInstance()
了加密和解密方法。
cipher = Cipher.getInstance(TRANSFORMATION_STR);
cipher.init(Cipher.ENCRYPT_MODE, mKey, mParamSpec);
// encrypt code here
getInstance()
method grabs a cipher instance for the current thread to avoid race conditions like the exception you just posted.
getInstance()
方法获取当前线程的密码实例以避免竞争条件,例如您刚刚发布的异常。
回答by mrcrag
I had the same issue (Cipher not initialized
). I was using high-encryption and, for me, the solution was replacing the normal policy jars in jre/lib/security
with the unlimited strength versions.
我有同样的问题(Cipher not initialized
)。我正在使用高加密,对我来说,解决方案是用jre/lib/security
无限强度版本替换正常的策略罐。