Securing Your Android Keys & Secrets with Native C++ Code
This article will guide you on how to secure your API keys, Base URLs, and other sensitive data of your app. Often times for Android apps, you want to keep secrets away from hackers or from any person who wants to reverse-engineer the app through an APK file. In this article, you will see some ways used by the Android devs to be secure and safe for your data.
There is no perfect protection mechanism to perfectly secure your data, applications, and systems from a passionate, sharp-minded hacker. So the only thing you can do in such scenarios is you can increase the security and use the best ways to be more secure. This will increase the hurdles in the ways of intruders and will take more time to sabotage the system.
Almost every app now uses some web services API. This is mostly enabled through any APU key or token. This key lets the server know that requests are coming from authenticated users and devices. Now, if you don’t keep these API keys secure, then any hacker can get access to this data through reverse engineering the APK file. This intruder can now make a flood of fake requests, which can be costly and may lead to some other serious breach issues and can create a very bad impression on your users.
Let’s talk now about some of the ways that developers use to store these API keys and other sensitive data.
Storing Keys in strings.xml File
This is a very common method to store keys. Although strings.xml is not recommended to use for the sensitive data, but often developers use this a lot. This will not keep that data secure and can be easily seen after reverse-engineering the APK file.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--API Key-->
<string name="api_key">abcdefg2q4qsaf34rtyy421k</string>
</resources>
Storing Keys As Constants
Another common and bad way is to make a constant of your API key and put it in a Java/Kotlin file. This is easier to use in the code to access that key, but it will cost you a lot. Only keep the things in constants which are not sensitive.
object Constants {
const val API_KEY = "abcdefg2q4qsaf34rtyy421k"
}
Storing Keys in Gradle Files
Another way to store the API keys is putting them in Gradle files. This asks for the compiling of those keys and can be accessed only after a successful build. Developers often assume that this is a safe and secure way to hide secrets from intruders, but actually it’s not. It’s as much insecure as other methods like strings.xml
or constants
.
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.texturelabs.rosera.pop_movies"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
// THE API KEY FOR YOUR APP
buildConfigField("String", "API_KEY", "abcdefg2q4qsaf34rtyy421k")
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),↵
'proguard-rules.pro'
}
}
}
This can be accessed in your code through BuildConfig.API_KEY
.
Storing Keys Natively with C++
In Android Apps, you write code in Java or Kotlin, and it is easy to decompile
the code written in Java and Kotlin as compared to C/C++ native code. Thus, there is a way to hide your Keys using C/C++ which is secure and safer than the previous ways.
Let’s look at the way to hide the API key by a code example. First, you have to install NDK (Native Development Kit) which allows C/C++ code to work with Android Studio and CMake to build your C/C++ code.
Now, make a folder name cpp
in App’s src > main >
and create a C++ file in it with the name native-lib.cpp
. Put this code snippet in that cpp
file.
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstringJNICALL
Java_com_package_name_YourKeys_apiKey(JNIEnv *env, jobject object) {
std::string api_key = "your_api_key";
return env->NewStringUTF(api_key.c_str());
}
Here com_package_name
is the actual package name of your app. Note that instead of the dots, here are the underscores. So, com.package.name
becomes com_package_name
.
Then _YourKeys
is the name of .kt
file which allows you to access the API key in Java/Kotlin files from C++ code.
Next to it, _apiKey
is the name of the function which will return you the actual API key to make it accessible throughout your App.
This is enough for C++ code, now you have to create that YourKeys.kt
file, and write the following code;
object YourKeys {
init {
System.loadLibrary("native-lib")
}
external fun apiKey(): String
}
The code is used to access the keys throughout the application. Note that the apiKey
method doesn’t have any method definition. The external
modifier makes sure that this method’s definition is brought from the native C++ code through the native-lib.cpp
file.
You can add more keys and sensitive data by creating more methods in both YourKeys.kt
and native-lib.cpp
files following the convention explained about of placing package_name_File_Name_method_name
etc.
In the end, wherever you want to access the API key either while making some retrofit instance or whatever you need forl, you just have to write YourKeys.apiKey()
.
And that’s it. Now you can remain confident that your API keys and secrets are safe and sound and can not be easily viewed through reverse engineering the APK file.
At the end, please Subscribe to my newsletter #Time with Wajahat to learn learn about the life experiences, lessons, career advices, technology & programming tips manually handcrafted and curated by Wajahat Karim.