Security should be a thing. An important thing actually. But I, as many other app developers, only know some basics. More common sense that real expertise. But that doesn’t mean that I’m not worry about the security of the app I work on, and that’s why I come here to write a bit about my tries hiding some API keys from others. I tell you my case.
What I want
My app is going public. Everybody can us it. That means that once it is shipped, I have no control of what the people do with the file.
Because I don’t want any one else than me having access to the API keys, I should hide them as well as possible in the project.
I should also be careful to don’t upload any file with the keys to any repository, private or public.
So, in brief, a list with the premises to have the goal clear:
- The keys should not be in the repository
- The keys should be hidden in case of reverse engineering
- To contact the server is needed at least one or two keys, so store in the server is not a real solution (in my case)
What I don’t want
It’s not the first time I’m facing this problem and I know exactly what I don’t want.
In an old project I tried with a suggested method explained in this post: https://blog.squareboat.com/securing-api-keys-inside-android-apps-using-android-ndk-be2e7e29dfd3
I don’t gonna discuss if it’s more or less effective. If I don’t want to use this method is just because in the past I had some bad experiences when debugging while using this method. So this time I will try to stay away of it.
What doesn’t work
So I started to try things I was having in mind or finding online. Here a list of what didn’t work for me.
- Write the keys in a separated string xml file and add this file to the gitignore file.
With this method I would only accomplish 2 of the 3 premises. It’s separated and in the gitignore file, so it will never reach the repositories and they are not in the server. But, unfortunately, simply using apktool to make reverse engineering of the released apk will show all the strings of the app, including the keys. So, thank you, next…
- Write the keys in a separated gradle properties file, use them as resValue in the app gradle file and add this file to the gitignore file.
This method apparently is different than the last one, but not at all. This method just create the strings differently, but at the end they end in the strings.xml file. Next…
- Write the keys in a separated gradle properties file, use them as buildConfigField in the app gradle file and add this file to the gitignore file.
At first tried it didn’t work because there are some <metadata> fields to fill in the Manifest and I could not inject this buildconfig values into the Manifest file. But then I found a trick in Android development that I didn’t know. Actually it’s possible to inject values in the Manifest through the app gradle file.
Here more information: https://developer.android.com/studio/build/manifest-build-variables
But anyway this means that the final result, after apply Apktool on it, will be the manifest file showing in plain text the data I want to hide. So, 🤷🏻♂️ Thank u, next…
At this point a was a bit desperate. So I found this article from 2015: https://rammic.github.io/2015/07/28/hiding-secrets-in-android-apps/
What I did finally
At the end I thought that the problem was coming from the Manifest file, that was “leaking” all the data when using the reverse engineering tool. So I just tried to remove all that information from the Manifest and put it in the files where proguard makes its job. I removed the <metadata> tags with the information and I placed it in the initialisation of the libraries in the Application file. And it worked as I wanted. There were no trace of api keys in the repositories nor in the Apktooled files.
So finally the code ends like this:
- All the keys are in a gradle.properties file
- The gradle.properties file is in gitignore, so it’s not committed to the repo
- The keys are called and transformed into BuildConfigFields in the app gradle file.
- Using “BuildConfig.nameOfTheKey” in the code I can get the key value.
- Proguard do its job with the code, so everything is obfuscated.
I’m pretty sure that there are other ways to get the hidden API keys from my app’s file, but at least I can sleep a bit better every night because they are not that easy to reach.
Now I would like to know, what do you do? Do you have another method to hide the keys?
Maybe you can help me a bit, can you do the same in iOS? Do you know any article that explains how to do it? Please, share it with me in the comments. I would like to learn.