Secret management in android

Kartik Mittal
4 min readApr 4, 2021

When it comes to the android app, then you may find that it is very easy to reverse engineer an Android app to a greater extent. There are many tools available to do so. Some of them are:-
1. ApkTool
2. Dex2jar
3. JD-GUI

So, it becomes very important to protect your secret keys so that they cannot be misused by another person. Example: a key for Google Maps, Facebook, Crashlytics, or some other third-party library keys. Generally, when it comes to storing these keys, a developer's first choice will be placing them in strings.xml and accessing them all over the app. But it can be dangerous to place them in strings.xml as anyone can decompile your apk and easily get that file and thus access all secret keys and misuse them.

So, the question is, can we completely prevent someone to get the secret keys by reverse engineering stored in the app? So, the answer is NO.

It is not possible to protect our secret keys 100% but we can make it as harder as possible to extract the keys. So, basically, there are some approaches that can be used by you to do so: —

1. If you do not want to store your secret keys in the app then you can place them on your server and get the same at runtime. But still, some hackers can use MITM attacks or any other attacks to get them from your server.
2. You can encrypt the keys using some algorithms and place them somewhere else in the app other than strings.xml and can decrypt them at runtime when there is a need to use them.
For this, you can use the following approaches to place your encrypted keys:-

a. Using app-level build.gradle fileYou can store the encrypted secret keys in app-level Gradle file as following-

android {
//...
buildTypes {
//...
release {
buildConfigField "String", "MY_SECRET_KEY", "\"ENCRYPTED_SECRET_KEY_DEBUG_VALUE\""
}
debug {
buildConfigField
"String", "MY_SECRET_KEY", "\"ENCRYPTED_SECRET_KEY_RELEASE_VALUE\""
}
}
}

After compiling the code you can access them in the code as follows -

BuildConfig.MY_SECRET_KEY

But still generated BuildConfig file can be extracted from the apk easily and hackers can get the encrypted stored keys and can possibly decrypt them to get the original keys.

b. Using NDK (Native Development Kit) in android — It allows us to write code in C/C++ in our app which is a lot more difficult to decompile and get the stored keys from it. Although, as I previously said that it is impossible to completely prevent the hacker to steal the keys from our app but we can make it as harder as possible. So, let’s get started-

STEPS-
1.
First install the following components from SDK manager in android studio to get started with NDK.

  • The Android Native Development Kit (NDK): a set of tools that allows you to use C and C++ code with Android.
  • CMake: an external build tool that works alongside Gradle to build your native library. You do not need this component if you only plan to use ndk-build.
  • LLDB: the debugger Android Studio uses to debug native code. By default, LLDB will be installed alongside Android Studio.

Note- By default LLDB will be installed with the android studio so, you may or may not get that option in SDK manager to install.

2. Specify the CMake path and NDK version in your app-level Gradle file.

android {
//...

ndkVersion "23.0.7196353"
externalNativeBuild {
cmake {
// Provides a relative path to your CMake build script.
path "CMakeLists.txt"
}
}
//...
}

You can get the NDK version from the SDK manager by selecting the Show Package Details checkbox as shown in the below image —

3. Let’s start coding…

  • Create a new project or use an existing one.
  • Create a folder named ‘cpp’ under src/main.
  • Now create a C/C++ file under the above-created cpp folder named ‘native-lib.cpp’ and write the following code to it-

In the above code Java_com_package_name_MainActivity_getEncryptedKey represents the package name com.package.name and MainActivity is the activity in which key needs to be accessed and getEncryptedKey is the static method that is used in the specified activity to access the key. So, basically, the combination will be — {Java}_{Package Name (. replaced with underscores)}_{Activity Name}_{Method Name}

  • Now create a CMake script named CMakeLists.txt under the app folder and the following content to it —
  • Now to access the encrypted key in your activity you have to add a static block and make a function as follows-

If you are using java then —

static {
System.loadLibrary(“native-lib”);
}
public native String getEncryptedKey();

If you are using kotlin then —

companion object {
init {
System.loadLibrary(“native-lib”)
}
}
external fun getEncryptedKey(): String

Now you can call this function and voila, you will get the encrypted key, and then you can decrypt that using the same algorithm that you have used to encrypt it.
Thanks for reading the article. You can connect with me on LinkedIn and Facebook.

--

--