[android] Best practice for storing and protecting private API keys in applications

This example has a number of different aspects to it. I will mention a couple of points that I don't think have been explicitly covered elsewhere.

Protecting the secret in transit

The first thing to note is that accessing the dropbox API using their app authentication mechanism requires you to transmit your key and secret. The connection is HTTPS which means that you can't intercept the traffic without knowing the TLS certificate. This is to prevent a person intercepting and reading the packets on their journey from the mobile device to the server. For normal users it is a really good way of ensuring the privacy of their traffic.

What it is not good at, is preventing a malicious person downloading the app and inspecting the traffic. It is really easy to use a man-in-the-middle proxy for all traffic into and out of a mobile device. It would require no disassembly or reverse engineering of code to extract the app key and secret in this case due to the nature of the Dropbox API.

You could do pinning which checks that the TLS certificate you receive from the server is the one you expect. This adds a check to the client and makes it more difficult to intercept the traffic. This would make it harder to inspect the traffic in flight, but the pinning check happens in the client, so it would likely still be possible to disable the pinning test. It does make it harder though.

Protecting the secret at rest

As a first step, using something like proguard will help to make it less obvious where any secrets are held. You could also use the NDK to store the key and secret and send requests directly, which would greatly reduce the number of people with the appropriate skills to extract the information. Further obfuscation can be achieved by not storing the values directly in memory for any length of time, you can encrypt them and decrypt them just before use as suggested by another answer.

More advanced options

If you are now paranoid about putting the secret anywhere in your app, and you have time and money to invest in more comprehensive solutions, then you might consider storing the credentials on your servers (presuming you have any). This would increase the latency of any calls to the API, as it will have to communicate via your server, and might increase the costs of running your service due to increased data throughput.

You then have to decide how best to communicate with your servers to ensure they are protected. This is important to prevent all of the same problems coming up again with your internal API. The best rule of thumb I can give is to not transmit any secret directly because of the man-in-the-middle threat. Instead you can sign the traffic using your secret and verify the integrity of any requests that come to your server. One standard way of doing this is to compute an HMAC of the message keyed on a secret. I work at a company that has a security product that also operates in this field which is why this sort of stuff interests me. In fact, here is a blog article from one of my colleagues that goes over most of this.

How much should I do?

With any security advice like this you need to make a cost/benefit decision about how hard you want to make it for someone to break in. If you are a bank protecting millions of customers your budget is totally different to someone supporting an app in their spare time. It is virtually impossible to prevent someone from breaking your security, but in practice few people need all of the bells and whistles and with some basic precautions you can get a long way.

Examples related to android

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How to implement a simple scenario the OO way My eclipse won't open, i download the bundle pack it keeps saying error log getting " (1) no such column: _id10 " error java doesn't run if structure inside of onclick listener Cannot retrieve string(s) from preferences (settings) strange error in my Animation Drawable how to put image in a bundle and pass it to another activity FragmentActivity to Fragment A failure occurred while executing com.android.build.gradle.internal.tasks

Examples related to reverse-engineering

Sniffing/logging your own Android Bluetooth traffic What is the iBeacon Bluetooth Profile JNZ & CMP Assembly Instructions Best practice for storing and protecting private API keys in applications How to avoid reverse engineering of an APK file? Generate UML Class Diagram from Java Project How do you extract classes' source code from a dll file? Generate ER Diagram from existing MySQL database, created for CakePHP decompiling DEX into Java sourcecode List of all index & index columns in SQL Server DB

Examples related to proguard

Could not determine the dependencies of task ':app:crashlyticsStoreDeobsDebug' if I enable the proguard How to use the ProGuard in Android Studio? Best practice for storing and protecting private API keys in applications How to avoid reverse engineering of an APK file? How to remove all debug logging calls before building the release version of an Android app?

Examples related to api-key

Adding an .env file to React Project Googlemaps API Key for Localhost Best practice for storing and protecting private API keys in applications Place API key in Headers or URL What is an API key?