Encryption / Decryption in Android with RSA

Note: due to being a new member here on stackoverflow and link reputation limitations, I will have to post large snippets of code here.

EDIT: I've since posted this update to both my Genymotion device and my SDKs and so far I've managed to get a decrypted byte array but with a bunch of leading zeros. For this, I have not touched a single line of code. Something definitely seems strange about the environment in which I run the application.

I am trying to encrypt and decrypt a randomly generated AES key (along with its IV) using RSA, which I then use when encrypting data transmitted between the server and the android device. I have tested my code with a Genymotion device and I have run into these issues so far.

The code was tested and worked previously on customizing the desktop and the problem only occurred when copying my Android project to Android Studio. I have used these encryption and decryption methods on desktop with no problem.

I think I managed to localize the problem as being in my RSA encryption by encrypting some text and not getting the same bytes after decryption, although I cannot completely rule out additional errors:

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

      

In the constructor, I just added this piece of code to test these two methods.

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
}

      

And the methods that are used to get the KeyPair:

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() && 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;
}

      

Logs I get from running the app:

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 
&vK6   %M  , 9wg  !um7   t 9 w+ LGh 0ڼ{ s]   ̅     _͵b ͸-0  >   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 

      

As you can see, the test result has almost no decrypted text, which most likely caused problems for me when testing all the functions. I am at a loss as to how to solve this as most of the code previously worked flawlessly in a desktop environment. Help would be much appreciated.

Edit: the new conclusion I mentioned earlier:

10-18 20:45:44.969    1301-1314/edu.chalmers.sikkr I/ServerInterface﹕ Test result:                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Decryption successful

      

Edit: This last issue was also resolved by changing to PKCS1Padding from NoPadding.

+3


source to share


1 answer


In your generateKeyPair function, you have:

saveByteDataToFile(privateKeyFile, key.getPublic().getEncoded());

      



where it should have been:

saveByteDataToFile(privateKeyFile, key.getPrivate().getEncoded());

      

0


source







All Articles