2017-02-15 20 views
2

ディアーズ、Androidの暗号化RSA例外:InvalidKeyException

私はdecryptStringが働くと、「java.security.InvalidKeyException:ニードRSAプライベートまたはパブリックキー」をスローしない理由を理解するのに役立つ必要があります。暗号化メソッドを呼び出すとき、私は秘密鍵/証明書によって公開鍵を使用します。

ありがとうございました!

public class KeysHandler { 

    /*** 
    * Generate and store in AndroidKeyStore a security KeyPair keys. 
    * @param alias - Alias to create the key. 
    * @return KeyPair object with: private and public key. 
    */ 
    public static KeyPair generateKeyPair(String alias) { 
     KeyPair kp = null; 
     if (alias != null) { 
      try { 

       KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); 
       kpg.initialize(new KeyGenParameterSpec.Builder(alias, 
         KeyProperties.PURPOSE_SIGN | 
         KeyProperties.PURPOSE_VERIFY | 
         KeyProperties.PURPOSE_ENCRYPT | 
         KeyProperties.PURPOSE_DECRYPT) 
         .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 
         .build()); 

       kp = kpg.generateKeyPair(); 

      } catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException ex) { 
       kp = null; 
      } 
     } 
     return kp; 
    } 

    public static String encryptString(String alias, String textToEncrypt) { 
     String cipheredText = null; 

     try { 
      KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 
      keyStore.load(null); 

      KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null); 

      // Encrypt the text 
      if(textToEncrypt != null && textToEncrypt.length() > 0) { 

       Cipher input = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
       input.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey()); 

       ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
       CipherOutputStream cipherOutputStream = new CipherOutputStream(
         outputStream, input); 
       cipherOutputStream.write(textToEncrypt.getBytes("UTF-8")); 
       cipherOutputStream.close(); 

       byte[] vals = outputStream.toByteArray(); 
       cipheredText = Base64.encodeToString(vals, Base64.DEFAULT); 
      } 
     } catch (Exception e) { 
      cipheredText = null; 
     } 

     return cipheredText; 
    } 


    public static String decryptString(String alias, String cipheredText) { 

     String clearText = null; 
     try { 
      KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 
      keyStore.load(null); 

      KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null); 

      Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); 
      output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey()); 

      CipherInputStream cipherInputStream = new CipherInputStream(
        new ByteArrayInputStream(Base64.decode(cipheredText, Base64.DEFAULT)), output); 
      ArrayList<Byte> values = new ArrayList<>(); 
      int nextByte; 
      while ((nextByte = cipherInputStream.read()) != -1) { 
       values.add((byte)nextByte); 
      } 

      byte[] bytes = new byte[values.size()]; 
      for(int i = 0; i < bytes.length; i++) { 
       bytes[i] = values.get(i).byteValue(); 
      } 

      clearText = new String(bytes, 0, bytes.length, "UTF-8"); 

     } catch (Exception e) { 
      clearText = null; 
     } 

     return clearText; 
    } 
} 

答えて

3

暗号プロバイダを省略してみてください。

Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 

第二に、あなたは作品が、その後、2番目の引数はいずれかになります第二引数としてCipher.getInstance().にそれを一緒に渡すことを確認する最初のプロバイダのインスタンスを作成することができますString(プロバイダ名)またはProvider(オブジェクト)。 2番目のコードを使用するとデバッグが簡単になる可能性があります。

+1

@FrederikHV本当にありがとう、 "AndroidOpenSSL"を省略すると魅力的でした。あなたに良い一週間を! – Mateus

+0

どこを省略しましたか?暗号化と復号化では両方の場所が省略されていますか?ありがとう。 – sandeepmaaram

+1

@sandeepmaaramどこでもCipher.getInstance – FrederikVH