Hiding AES decryption key in android app

Asked

Viewed 199 times

0

How can I not only hide AES keys but also encrypt and decrypt using predefined keys/commands in a native library(Encounter.), so that I can compile and include it in my android app.

That is, calling the native functions in the library to obtain the operations encrypt(String text) and decrypt(String text).

I currently use the code below.

public class encode {

    private String iv = "00000000000000iv"; //Dummy iv
    private String SecretKey = "0000000secretkey"; //Dummy secretKey

    private IvParameterSpec ivspec;
    private SecretKeySpec keyspec;
    private Cipher cipher;


    public encode()
    {
        ivspec = new IvParameterSpec(iv.getBytes());
        keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");

        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    public byte[] encrypt(String text) throws Exception
    {
        if(text == null || text.length() == 0) {
            throw new Exception("Empty string");
        }
        byte[] encrypted = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            encrypted = cipher.doFinal(text.getBytes("UTF-8"));
        }
        catch (Exception e) {
            throw new Exception("[encrypt] " + e.getMessage());
        }
        return encrypted;
    }

    public byte[] decrypt(String code) throws Exception
    {
        if(code == null || code.length() == 0) {
            throw new Exception("Empty string");
        }
        byte[] decrypted = null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            decrypted = cipher.doFinal(hexToBytes(code));
        }
        catch (Exception e) {
            throw new Exception("[decrypt] " + e.getMessage());
        }
        return decrypted;
    }

    public static String bytesToHex(byte[] data)
    {
        if (data==null) {
            return null;
        }
        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16) {
                str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
            }
            else {
                str = str + java.lang.Integer.toHexString(data[i]&0xFF);
            }
        }
        return str;
    }

    public static byte[] hexToBytes(String str) {
        if (str==null) {
            return null;
        }
        else if (str.length() < 2) {
            return null;
        }
        else {
            int len = str.length() / 2;
            byte[] buffer = new byte[len];
            for (int i=0; i<len; i++) {
                buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
            }
            return buffer;
        }
    }

}
  • How could I make a compiled version of the above function?

Example of web AES encryption in C, who knows helps to get an idea of the desired operation, but do not know how to call this function(natively) or if she needs adjustments.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 * MCrypt API available online:
 * http://linux.die.net/man/3/mcrypt
 */
#include <mcrypt.h>

#include <math.h>
#include <stdint.h>
#include <stdlib.h>

int encrypt(
    void* buffer,
    int buffer_len, /* Because the plaintext could include null bytes*/
    char* IV, 
    char* key,
    int key_len 
){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 ){return 1;}

  mcrypt_generic_init(td, key, key_len, IV);
  mcrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

int decrypt(
    void* buffer,
    int buffer_len,
    char* IV, 
    char* key,
    int key_len 
){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 ){return 1;}

  mcrypt_generic_init(td, key, key_len, IV);
  mdecrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

void display(char* ciphertext, int len){
  int v;
  for (v=0; v<len; v++){
    printf("%d ", ciphertext[v]);
  }
  printf("\n");
}

int main()
{
  MCRYPT td, td2;
  char * plaintext = "test text 123";
  char* IV = "AAAAAAAAAAAAAAAA";
  char *key = "0123456789abcdef";
  int keysize = 16; /* 128 bits */
  char* buffer;
  int buffer_len = 16;

  buffer = calloc(1, buffer_len);
  strncpy(buffer, plaintext, buffer_len);

  printf("==C==\n");
  printf("plain:   %s\n", plaintext);
  encrypt(buffer, buffer_len, IV, key, keysize); 
  printf("cipher:  "); display(buffer , buffer_len);
  decrypt(buffer, buffer_len, IV, key, keysize);
  printf("decrypt: %s\n", buffer);

  return 0;
}
  • Who are the communication pairs? In fact, the correct place for keys is in a configuration file, not in the sources, and IV is chosen randomly to encrypt and saved along with the cipher to be able to decipher. The bigger problem is how to put that key there... The app could generate it automatically during the installation, but then everything encrypted by it can only be deciphered by itself. Is that what you want? Because if it’s not, you’d need a way to share the key between the app and the other pair of communication, and that can be very difficult in practice. What is your goal?

  • The app receives the encrypted data, along with IV, which can be changed from time to time on the server. The app only has one of two Keys required for decoding, which is also encoded with aes but stay in the app itself. The output data is not encrypted because it does not have the same degree of sensitive information that enters, I said, all traffic is under SSL encryption. I have a custom function to shuffle and mix all the information and encrypted Keys.

  • This example would also serve for me to take as a basis and include more non-sensitive data in the library. I just wanted to store the decryption function outside the app, and also to be able to use an external key already included in the library. My app is hybrid, all pages are remote, IE, via webview, what really is passed is the data of paramount importance, the non-hybridized part and that processes and runs/displays the information to the user. @mgibsonbr I hope you understand better.

1 answer

0

Great question and the solution is simpler than it looks. In many examples you find on the Internet, Ivs and keys are in constant. This is a problem as you observed and if you still obfuscate the code, it will be available.

An effective solution for this is to get the key, vary the iv to each network operation.

Or, if your software has no interaction with the Web, get that key do it in your build tool, Maven, Gradle etc.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.