2012-04-27 62 views
4

私はAndroidアプリケーションで暗号化/復号化を実装しました。java.lang.IllegalStateException:暗号化が初期化されていません

シングルトンクラスになっている暗号化クラスを追加しました。コードの

一部を次のようにシングルトンインスタンスを使用して

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

は、文字列の暗号化&復号化は、彼らが主に取り組んでいる&を実現しています。時には

、暗号はその例外をスローまだ初期化されているものの:java.lang.IllegalStateException: Cipher not initialized

いくつかの時間間隔(30分)の後に、列の復号化が行われた場合のシナリオがほとんどです。

Singletonインスタンスを誤って使用している可能性がありますか?代わりにシングルトンクラスの

、私は、new演算子を使用して暗号化クラスのインスタンスを作成した文字列を暗号化しようとしましたが、問題は、私は他の復号化に同じオブジェクト、java.lang.IllegalStateException: Cipher not initializedがスローされる必要があります。

提案/ヒントを歓迎します。

+0

あなたは 'Encryption.getInstance()。encryptString(" 123 ");'のように使います。複数のスレッドから、または1から? – zapl

+0

そのスレッドから – chiranjib

+0

この問題を解決できましたか?私は同じ問題 - 定数使用の数分後にIllegalStateExceptionsに苦しんでいる。すべての使用の前にinit()を呼び出すことさえできます(常に変化するIVのため)。問題が見つかった場合は、解決策を使って自分の質問に答えてください。 :) – Tustin2121

答えて

6

この問題は、私に起こったように、マルチスレッド環境で発生するようになります。この問題は、mCipher.init()メソッドとmCipher.doFinal()メソッドの間の衝突です。

暗号クラスの関連する方法は次のとおり

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

は、INIT()とのdoFinal()を実行する二つのスレッドを有するマルチスレッド環境でinitialized変数の挙動を見ます。返されたExceptionは、実際に初期化されていないオブジェクトに関連していませんが、に設定されたinitialized変数です。

私はencryptString()とdecryptString()メソッドを同期させて問題を解決しました。あなたはCipherコードを調べることでいくつかの洞察を得ることができることを願っています。

1

私は同じ問題(Cipher not initialized)を持っていました。私は高い暗号化を使用していました。私にとって、このソリューションは、jre/lib/securityの通常のポリシージャーを無制限の強さのバージョンに置き換えていました。あなたのdecryptstring方法で

0

あなたは、あなたがそれにgetOutputSizeを呼び出す際に暗号がまだ初期化されていないので、あなたが例外を取得

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

を呼び出す前に、あなたは数行

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

を呼び出します。これらの行を並べ替えて修正する必要があります。 (それは私のためでした)

関連する問題