title: Bouncy Castle works differently on Android and Console program. How to encrypt using public key in PEM file
body: <p>I am encrypting using Bouncy Castle. I am using RSA and public key is stored in PEM file. I am finding that when I run the code in simple console project (not Android project) everything works fine - meaning the encrypted string can be decrypted using the private key. However, when I run the same code in Android app, the encrypted byte array is different for the same public key and is not recognized as valid encryption for the given key pair.</p>
  
  <p><strong>Details</strong>:
  Here is the code that encrypts string using Bouncy Castle and taken out of the console project. This one works fine and produces the encrypted string which is valid encryption for the key pair and can be decrypted.</p>
  
  <pre><code>private static void encrypt() {
      try {
          //This example uses the Bouncy Castle library
          Security.addProvider(new BouncyCastleProvider());
  
          String plainText = "This needs to be encrypted";
          String public_key_file = "PublicKey.pem";
  
          //Load public key
          PEMParser parser = new PEMParser(new FileReader(public_key_file));
          Object key = parser.readObject();
          parser.close();
          PublicKey pubKey = null;
  
          if (key instanceof SubjectPublicKeyInfo) {
              SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) key;
              pubKey = KeyFactory.getInstance("RSA").generatePublic
                      (new X509EncodedKeySpec(spki.getEncoded()));
          }
  
          //Encrypt the plain text
          Cipher cipher = Cipher.getInstance("RSA");
          cipher.init(Cipher.ENCRYPT_MODE, pubKey);
          byte[] encrypted_data = cipher.doFinal(plainText.getBytes());
          String encoded_data = new String(Base64.encode(encrypted_data));
  
          System.out.println("Encrypted Value:");
          System.out.println(encoded_data);
      } catch (Exception ex) {
          System.out.println(ex.getMessage());
      }
  }
  </code></pre>
  
  <p>Now here is the code taken out of the Android app. The only important difference is that the key file is read from Assets folder. This code also produces encrypted string but it is not valid for the key pair and can't be decrypted.</p>
  
  <pre><code>public void encrypt(Context context) {
  
      try {
  
          //This example uses the Bouncy Castle library
          Security.addProvider(new BouncyCastleProvider());
  
          String plainText = "This needs to be encrypted";
          String public_key_file = "PublicKey.pem";
  
          //Load public key
          InputStream inputStream = context.getAssets().open(public_key_file);
          InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
          // read from the input stream reader
          PEMParser parser = new PEMParser(inputStreamReader);
  
          Object key = parser.readObject();
          parser.close();
          PublicKey pubKey = null;
  
          if (key instanceof SubjectPublicKeyInfo) {
              SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) key;
              pubKey = KeyFactory.getInstance("RSA").generatePublic
                      (new X509EncodedKeySpec(spki.getEncoded()));
          }
  
          //Encrypt the plain text
          Cipher cipher = Cipher.getInstance("RSA");
          cipher.init(Cipher.ENCRYPT_MODE, pubKey);
          byte[] encrypted_data = cipher.doFinal(plainText.getBytes());
          String encoded_data =
                  new String(Base64.encode(encrypted_data));
  
          Log.d("MyApp", "Encrypted Value:");
          Log.d("MyApp", encoded_data);
  
      } catch (Exception ex) {
          Log.d("MyApp", ex.getMessage());
      }
  
  }
  </code></pre>
  
  <p>In both the cases, following things are same:</p>
  
  <ol>
  <li>Public Key </li>
  <li>Actual code written (with difference of reading from Assets folder and logging to Logcat)</li>
  <li>JDK version (1.7) </li>
  <li>Bouncy Castle libraries (bcpkix-jdk15on-152.jar and bcprov-jdk15on-152.jar)</li>
  </ol>
  
  <p>What's different: The environment. One is console program and the other is Android App.</p>
  
  <p><strong>On further investigation while debugging</strong>
  I observed that when running the console program the KeyFactory returns instance of "sun.security.rsa.RSAPublicKeyImpl". However when running android app, the KeyFactory returns instance of "com.android.org.conscrypt.OpenSSLRSAPublicKey". Not sure if that's the problem. The encrypted byte array is different for same plain text and public key.</p>
  
  <p>Any help is greatly appreciated. </p>
  
  <p>Thanks in Advance,
  Sandeep</p>