title: Encryption/Decryption in Android with RSA
body: <p>Note: due to being a new member here at stackoverflow and reputation restrictions on links, I will have to post <strong>large</strong> chunks of code here.</p>
  
  <p>EDIT: I have since I posted this updated both my Genymotion device and my SDKs, and so far I have managed to get the decrypted byte array, but with a bunch of leading zeroes. To accomplish this I have not touched a single line of code though. Something definitely seems to be strange with the environment I am running the app on.</p>
  
  <p>I have been trying to encrypt and decrypt a randomly generated AES key (along with its IV) using RSA which I then use when encrypting data transferred between a server and an android device. I have been testing my code using a Genymotion device, and that is where I have been encountering these problems so far.</p>
  
  <p>The code has been tested and has worked on a desktop setup before, and the problem only started appearing when I copied over to my android project in Android Studio. I have used these encrypt and decrypt methods on a desktop setup without problems.</p>
  
  <p>I think I did manage to localise the problem as being in my RSA encryption by encrypting some text and not getting the same bytes after decryption, although I can not completely rule out additional errors:</p>
  
  <pre><code>private byte[] decrypt(byte[] bytes) throws Exception {
      Cipher cipher = Cipher.getInstance("RSA/None/NoPadding");
      cipher.init(Cipher.DECRYPT_MODE, PRIVATE_KEY);
      return cipher.doFinal(bytes);
  }
  
  private byte[] encrypt(byte[] bytes) throws Exception {
      Cipher cipher = Cipher.getInstance("RSA/None/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, SERVER_KEY);
      return cipher.doFinal(bytes);
  }
  
  //Made this method to test my own keys, and whether or not encryption works
  private byte[] encryptMyOwnKey(byte[] bytes) throws Exception {
      Cipher cipher = Cipher.getInstance("RSA/None/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, PUBLIC_KEY);
      return cipher.doFinal(bytes);
  }
  </code></pre>
  
  <p>In the constructor I have just added this piece of code, to test those two methods.</p>
  
  <pre><code>private ServerInterface(Context context) throws IOException {
      //Some not so interesting code goes here
      final KeyPair key = getKeyPair(context);
      PRIVATE_KEY = (RSAPrivateKey) key.getPrivate();
      PUBLIC_KEY = (RSAPublicKey) key.getPublic();
      try {
          //Some dummy text for testing
          byte[] test = decrypt(encryptMyOwnKey("Decryption successful".getBytes()));
          Log.i("ServerInterface", "Test result: "+new String(test));
      } catch (Exception e) {
          e.printStackTrace();
      }
      //More code that isn't interesting
  }
  </code></pre>
  
  <p>And the methods that are used to get the KeyPair are:</p>
  
  <pre><code>private static KeyPair getKeyPair(Context context) {
      final File keyFileDirectory = new File(context.getFilesDir(), "rsa/");
      final File publicKeyFile = new File(keyFileDirectory, "sikkr_pub_key");
      final File privateKeyFile = new File(keyFileDirectory, "sikkr_priv_key");
      KeyPair key;
  
      if (publicKeyFile.exists() &amp;&amp; privateKeyFile.exists()) {
          try {
              key = getKeyPairFromFile(publicKeyFile, privateKeyFile);
          } catch (Exception e) {
              key = generateKeyPair(publicKeyFile, privateKeyFile);
          }
      } else {
          key = generateKeyPair(publicKeyFile, privateKeyFile);
      }
      return key;
  }
  
  private static KeyPair getKeyPairFromFile(File publicKeyFile, File privateKeyFile) throws Exception {
      Log.d("ServerInterface", "Getting the key pair from file");
      byte[] publicKey = readByteDataFromFile(publicKeyFile);
      byte[] privateKey = readByteDataFromFile(privateKeyFile);
  
      KeyFactory kf = KeyFactory.getInstance("RSA");
      RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(publicKey));
      RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
      return new KeyPair(pubKey, privKey);
  }
  
  private static KeyPair generateKeyPair(File publicKeyFile, File privateKeyFile) {
      Log.d("ServerInterface", "Generating a key pair");
      KeyPairGenerator keyGen;
      KeyPair key = null;
  
      if (publicKeyFile.exists()) {
          publicKeyFile.delete();
      }
  
      if (privateKeyFile.exists()) {
          privateKeyFile.delete();
      }
  
      try {
          keyGen = KeyPairGenerator.getInstance("RSA");
          keyGen.initialize(2048);
          key = keyGen.genKeyPair();
  
          if (!publicKeyFile.getParentFile().exists()) {
              publicKeyFile.getParentFile().mkdirs();
          }
  
          publicKeyFile.createNewFile();
          privateKeyFile.createNewFile();
          saveByteDataToFile(publicKeyFile, key.getPublic().getEncoded());
          saveByteDataToFile(privateKeyFile, key.getPrivate().getEncoded());
      } catch (NoSuchAlgorithmException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      }
  }
  
  private static void saveByteDataToFile(File file, byte[] data) throws IOException {
      DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
      dos.write(data);
      dos.flush();
      dos.close();
  }
  
  private static void readByteDataFromFile(File file) throws IOException {
      DataInputStream dis = new DataInputStream(new FileInputStream(file));
      byte[] read = new byte[dis.available()];
      dis.readFully(read);
      dis.close();
      return read;
  }
  </code></pre>
  
  <p>The logs that I get from running the app are:</p>
  
  <pre><code>10-18 13:55:16.472    1251-1265/edu.chalmers.sikkr I/ServerInterface﹕ Setting up an interface to the server
  10-18 13:55:16.528    1251-1265/edu.chalmers.sikkr D/ServerInterface﹕ Generating a key pair
  10-18 13:55:17.004    1251-1265/edu.chalmers.sikkr I/ServerInterface﹕ Test result: JNk9���N+!N^9__ `D�)̊#O�K��\���Q�eD�(���M�
  &amp;vK6���%M��,�9wg��!um7���t�9�w+�LGh�0ڼ{�s]���̅�����_͵b�͸-0��&gt; ��fk@m}��Wx|�g�_��P8;��t��:��5��8��o�͐w�Ơ����o$��2��jS2�Z��j̪����j�l_HZ�k���~�����7�b��N�fޒ�Ի*)I.IE�
  </code></pre>
  
  <p>As you can see, the test result is nowhere near decrypted text, which is most likely what has caused problems for me when testing all of the functions. I am lost as to how to solve this, since most of the code has previously worked flawlessly on a desktop environment. Help would be much appreciated.</p>
  
  <p>Edit: The new output I was talking about previously:</p>
  
  <pre><code>10-18 20:45:44.969    1301-1314/edu.chalmers.sikkr I/ServerInterface﹕ Test result: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Decryption successful
  </code></pre>
  
  <p>Edit: This last problem was also solved, by changing to PKCS1Padding from NoPadding.</p>