2015-12-14 16 views
6

Androidアプリケーションで文字列を暗号化および復号化しようとしていますが、InvalidKeyExceptionエラーが発生します。ここでAndroid Decryption Error

は私のコードです:

//キー方式//テスト

public void generateKeys() { 
    Calendar cal = Calendar.getInstance(); 
    Date now = cal.getTime(); 
    cal.add(Calendar.YEAR, 25); 
    Date end = cal.getTime(); 

    KeyPairGenerator kpg = null; 
    try { 
     kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (NoSuchProviderException e) { 
     e.printStackTrace(); 
    } 
    try { 
     kpg.initialize(new KeyPairGeneratorSpec.Builder(context) 
       .setAlias(KEY_ALIAS) 
       .setStartDate(now) 
       .setEndDate(end) 
       .setSerialNumber(BigInteger.valueOf(1)) 
       .setSubject(new X500Principal("CN=" + KEY_ALIAS)) 
       .build()); 
    } catch (InvalidAlgorithmParameterException e) { 
     e.printStackTrace(); 
    } 

    KeyPair kp = kpg.generateKeyPair(); 

    KeyStore ks = null; 
    try { 
     ks = KeyStore.getInstance("AndroidKeyStore"); 
     ks.load(null); 
     Enumeration<String> aliases = ks.aliases(); 
    } catch (KeyStoreException e) { 
     e.printStackTrace(); 
    } catch (CertificateException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    KeyStore.Entry entry = null; 
    try { 
     entry = ks.getEntry(KEY_ALIAS, null); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (UnrecoverableEntryException e) { 
     e.printStackTrace(); 
    } catch (KeyStoreException e) { 
     e.printStackTrace(); 
    } 
    if (!(entry instanceof KeyStore.PrivateKeyEntry)) { 
     Log.e(LOG_TAG, "Not an instance of PrivateKeyEntry."); 
    } 
    else{ 
     privKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); 
     pubKey = ((KeyStore.PrivateKeyEntry) entry).getCertificate().getPublicKey(); 
    } 

} 

//暗号化方式

private String encryptString(String value){ 
    byte[] encodedBytes = null; 
    try { 
     Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
     cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
     encodedBytes = cipher.doFinal(value.getBytes()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return Base64.encodeToString(encodedBytes, Base64.DEFAULT); 
} 

//復号化方法

private String decryptString(String value){ 
    byte[] decodedBytes = null; 
    try { 
     Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
     c.init(Cipher.DECRYPT_MODE, privKey); 
     decodedBytes = c.doFinal(Base64.decode(value, Base64.DEFAULT)); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     Log.e("Error", "Error = " + e); 
     return "SECURE_FAILURE"; 
    } 

    return new String(decodedBytes); 
} 

を生成しますコード

generateKeys(); 
    String encrypted = encryptString("Hello World"); 
    Log.e("Encrypt", "encrypted = " + encrypted); 
    String decrypted = decryptString(encrypted); 
    Log.e("Decrypt", "decrypted = " + decrypted); 

それはこのようなものプリントアウトすると暗号化はOK働くように見えます:

java.security.InvalidKeyException: Need RSA private or public key

私ができる:

encrypted = SbA2iWWKQbDL7NTA9xvtjD/viYDdpx9fLRYTSZ8UQzdBy3QLqzkswBY21ErH7FPza3vZys4E4PZw uxaGkRz0aC0FLqsYlbpcJernGm5+D5lRcBOaZmgkNY9pMf0YP75cBbcJdcmb1rDaH40nCRDnEoXv rGESJRqT6p0NMzlZqdd9KO3tqfExwgservAWxPNtRDBbMgE4I/09418jM5Ock5eayfOuv/STwEy6 Ecd56UjFH63h+gP6ed2aMDhBVeExMxvdloY+VnsAxS5Dkoc2GdaljtjRuPK48HQASoJK8EwAMNpz

をしかし、私は、私は次のエラーを取得する解読しようとすると、なぜこの例外が発生するのかわからないのですか?誰も助けることができますか?

+0

運がいいですか? Android Marshmallowで同じ例外が発生しています。 – Luis

+0

私は別のプロバイダを使用してそれを修正しました...下の私の答えを参照してください。 – Luis

+1

非対称暗号化(RSA)公開/秘密鍵が必要な理由がない限り、AESなどの対称暗号化を使用するだけです。対称暗号化はデータ暗号化の一般的な選択です。非対称暗号化データの長さは鍵のサイズに制限されており、実際には遅く、安全ではありません。 – zaph

答えて

9

はこのように、別のプロバイダを使用してみてください:

Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidKeyStoreBCWorkaround"); 
+2

私のために働きますが、いくつかの説明は素晴らしいでしょう。 – Waboodoo

8

を、これは私の仕事:

private Cipher getCipher() { 
    try { 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // below android m 
      return Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); // error in android 6: InvalidKeyException: Need RSA private or public key 
     } 
     else { // android m and above 
      return Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidKeyStoreBCWorkaround"); // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround 
     } 
    } catch(Exception exception) { 
     throw new RuntimeException("getCipher: Failed to get an instance of Cipher", exception); 
    } 
} 
2

プロバイダが私の仕事の削除:Java docsから

Cipher.getInstance("RSA/ECB/PKCS1Padding") 

: "このメソッドは、最も優先度の高いProviderから始めて、登録されたセキュリティプロバイダのリストをトラバースします。新しいCi指定されたアルゴリズムをサポートする最初のプロバイダからCipherSpi実装をカプセル化したpherオブジェクトが返されます。