-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Storing Secret Keys in Android
Often your app will have secret credentials or API keys that you need to have in your app to function but you'd rather not have easily extracted from your app. The following common strategies exist for storing secrets in your source code:
- Embedded in resource file
- Hidden as constants in source code
- Hidden in BuildConfigs
- Obfuscating with Proguard
- Disguised or Encrypted Strings
- Hidden in Native Libraries with NDK
However, none of these strategies will ensure the protection of your keys and your secrets aren't safe. The best way to protect secrets is to never reveal them in the code in the first place. Compartmentalizing sensitive information and operations on your own backend server/service should always be your first choice. If you do have to consider a hiding scheme, you should do so with the realization that you can only make the reverse engineering process harder and may add significant complication to the development, testing, and maintenance of your app in doing so.
The simplest and most straightforward approach is outlined below which is to store your secrets within a resource file. Keep in mind that most of the other more complex approaches above are at best only marginally more secure.
The simplest approach for storing secrets in to keep them as resource files that are simply not checked into source control. Start by creating a resource file for your secrets called res/values/secrets.xml
with:
<!-- Inside of `res/values/secrets.xml` -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="parse_application_id">xxxxxx</string>
<string name="parse_client_secret">yyyyyy</string>
<string name="google_maps_api_key">zzzzzz</string>
</resources>
Once these keys are in the file, Android will automatically merge it into your resources, where you can access them exactly as you would your normal strings. You can access the secret values with:
Parse.initialize(
this,
getString(R.string.parse_application_id),
getString(R.string.parse_client_secret)
);
If you need your keys in another XML file such as in AndroidManifest.xml
, you can just use the XML notation for accessing string resources:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="@string/google_maps_api_key"/>
Since your secrets are now in an individual file, they're simple to ignore in your source control system (for example, in Git, you would add this to the '.gitignore' file in your repository):
echo "**/*/res/values/configuration.xml" > .gitignore
This process is not bulletproof. As resources, they are somewhat more vulnerable to decompilation of your application package, and so they are discoverable if somebody really wants to know them. This solution does, however, prevent your secrets just sitting in plaintext in source control waiting for someone to use, and also has the advantage of being simple to use, leveraging Android's resource management system, and requiring no extra libraries.
Created by CodePath with much help from the community. Contributed content licensed under cc-wiki with attribution required. You are free to remix and reuse, as long as you attribute and use a similar license.
Finding these guides helpful?
We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.
Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.