2

I'm using Parse.com in my Android App. I'm very concern about revealing secret keys. If the keys are revealed, someone can access our resources on Parse.com freely.

The keys are saved in a Java Class which extended Application Class.

I really want to know how to hide the keys. What is the best practice nowadays. Easy and low cost solution is appreciated..

Thanks.

zono
  • 8,366
  • 21
  • 75
  • 113
  • 1
    Possible duplicate of [Best Practice for storing private API keys in Android](http://stackoverflow.com/questions/14570989/best-practice-for-storing-private-api-keys-in-android). – jww Dec 01 '14 at 05:03

4 Answers4

4

I really want to know how to hide the keys...

Generally you try to move sensitive material outside an attackers control. Usually that means moving as much sensitive code and data to a server (and out of a client).

If possible, run the Parse.com code on the server so that the client does not need the API keys to begin with. There's little risk the keys will be leaked because they won't be on available to an attacker on the client.

If you authenticate the user, then keep the API key on your server. Provide it to the application once the user authenticates. There's still risk the key will be leaked, but it won't be hard coded into the app and easily found with an analysis tool like APKTool.

There are other steps you can take too. Proguard and encryption of the API keys come to mind. On Android 4.0 and above, you should also store them in the Keychain. It will stop the unmotivated attacker, and slow down a motivated one. Most of these are covered at Best Practice for storing private API keys in Android.

You can also encrypt the binary for distribution, but I understand this is more a DRM control from Google Play (and less a application/data security control). See, for example, Questions about Google Play application assets encryption.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • Thanks. Your answer is the greatest and perfect. I'm thinking about what measures you mentioned should I choose. Storing the keys in remote is great but I do not want to have another server. OK, I will try to do Proguard and encryption at first. And also I didn't know about Keychain of Android. I will check it out. Thanks alot. – zono Dec 01 '14 at 05:18
  • Thanks again. I believed that Android was less secure than iOS. However it maybe be getting better on the recent Android version. All right I will see the assets encryption in detail. – zono Dec 01 '14 at 05:30
1

while you are using the parse.com you can use the key by calling the restful api or by storing the parse key in the local database if the key is stored in the database and the application is decoded then local database cannot be accessed of the application so your parse key will be save

Fatti Khan
  • 1,543
  • 1
  • 11
  • 19
  • Thanks. I'm a newbie in Parse.com so I have some questions. My "Application ID" and "Client Key" are written in a java class. Do you mean that even though the two keys are revealed, my stored resources in Parse.com will be safe? – zono Dec 01 '14 at 04:52
  • 1
    the local database is not secured for a rooted device: http://stackoverflow.com/questions/19947664/protect-and-secure-the-local-user-data-in-android-even-if-the-device-is-rooted – Chris Jan 27 '15 at 08:32
1

jww answer is definitely the best here. The other answers will provide no security as per my comments on them. The only problem with jww's answer is that, as far as I know (and feel free to correct me), is that you wont be able to call the Parse server in the first place if you dont have the keys to start with. This will then force you to have a seperate server from which to obtain the keys.

The good news I have for you is this:

The Parse keys you use in your app is not secret! So dont stress. I quote the Parse security documentation:

"...These are not secret and by themselves they do not secure an app..."

You should instead make use of Access Control Lists or ACL's to secure your backend. Have a read through the official documentation with regards to security to see how you can secure your backend:

Parse.com Security

Also see this link for some more info:

Parse

Chris
  • 4,593
  • 1
  • 33
  • 37
0
/**
 * Encrypt data
 * 
 * @param secretKey
 *            - a secret key used for encryption
 * @param data
 *            - data to encrypt
 * @return Encrypted data
 * @throws Exception
 */
public String cipher(String secretKey, String data) throws Exception {
    SecretKeyFactory factory = SecretKeyFactory
            .getInstance("PBKDF2WithHmacSHA1");
    KeySpec spec = new PBEKeySpec(secretKey.toCharArray(),
            secretKey.getBytes(), 128, 256);
    SecretKey tmp = factory.generateSecret(spec);
    SecretKey key = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);
    Cipher cipher = Cipher.getInstance(ALGORITHM);
    cipher.init(Cipher.ENCRYPT_MODE, key);
    return toHex(cipher.doFinal(data.getBytes()));
}

/**
 * Decrypt data
 * 
 * @param secretKey
 *            - a secret key used for decryption
 * @param data
 *            - data to decrypt
 * @return Decrypted data
 * @throws Exception
 */
public String decipher(String secretKey, String data) throws Exception {
    SecretKeyFactory factory = SecretKeyFactory
            .getInstance("PBKDF2WithHmacSHA1");
    KeySpec spec = new PBEKeySpec(secretKey.toCharArray(),
            secretKey.getBytes(), 128, 256);
    SecretKey tmp = factory.generateSecret(spec);
    SecretKey key = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);
    Cipher cipher = Cipher.getInstance(ALGORITHM);
    cipher.init(Cipher.DECRYPT_MODE, key);
    return new String(cipher.doFinal(toByte(data)));
}

// Helper methods

private byte[] toByte(String hexString) {
    int len = hexString.length() / 2;
    byte[] result = new byte[len];
    for (int i = 0; i < len; i++)
        result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                16).byteValue();
    return result;
}

public String toHex(byte[] stringBytes) {
    StringBuffer result = new StringBuffer(2 * stringBytes.length);
    for (int i = 0; i < stringBytes.length; i++) {
        result.append(HEX.charAt((stringBytes[i] >> 4) & 0x0f)).append(
                HEX.charAt(stringBytes[i] & 0x0f));
    }
    return result.toString();
}

private final static String HEX = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

Use above code to encrypt & decrypt your parse key.

Karan Maru
  • 991
  • 6
  • 17
  • Thanks! Can I ask a stupid question. Where should I store the secret Key. I think that both using your great code and using Proguard are a good way so that attackers will be hesitated to hack. – zono Dec 01 '14 at 05:39
  • what happens when someone decompiles your APK? Then they will be able to very easy decipher the key in anyways – Chris Jan 27 '15 at 08:30