When working with Android applications, sometimes we need to handle sensitive information or perform specific tasks that require a lower-level approach. Using a Native Library built with JNI (Java Native Interface) can be a great way to manage such needs, especially when you want to keep data secure and out of reach of typical Android decompilers. Let’s dive into how to build your own native library, store sensitive information securely, and use it within your Android project.

If you’re not familiar with mobile app architecture before, read my guide to mobile app architecture .

Why Use a Native Library for Sensitive Data?

Android applications often face security challenges, and when it comes to sensitive data (such as API keys or encryption logic), you want to ensure that your data isn’t easily accessible. Native libraries, written in C or C++, can add an extra layer of security because they’re harder to decompile than Java/Kotlin code. Although not entirely foolproof, it’s a step forward in securing critical data.

Note: Native libraries provide an added security layer but don’t fully protect data from reverse engineering. It’s crucial to combine native libraries with other security measures for optimal protection.

Set Up Your Native Library

Create a C/C++ File with Sensitive Data

First, create a C/C++ file (src/main/cpp/NativeLib.c) for your sensitive data. For example, let’s say we have a secret API key. We’ll store this in a C file and then create functions to retrieve it.


#include <jni.h>

JNIEXPORT jstring JNICALL
Java_com_example_securelibrary_NativeLib_getApiKey(JNIEnv *env, jobject obj) {
    return (*env)->NewStringUTF(env, "YourSensitiveApiKey");
}

Integrate the Native Library in Your Android Project

In your Android project’s build.gradle file, make sure to specify CMake or NDK to build native code. Here’s how you can enable native support:


android {
    ...
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
        }
    }
}

Set Up CMakeLists.txt

In your C++ directory (e.g., src/main/cpp), create a CMakeLists.txt file to build the library:


cmake_minimum_required(VERSION 3.4.1)

add_library(securelib SHARED src/main/cpp/NativeLib.c)

find_library(log-lib log)

target_link_libraries(securelib ${log-lib})

Load and Use the Native Library in Kotlin

With our native library in place, let’s integrate it into the Android project. In your Kotlin or Java code, load the library and call the native function.


object NativeLib {
    init {
        System.loadLibrary("securelib")
    }

    external fun getApiKey(): String
}

Using the API Key in Your App

You can now use the NativeLib.getApiKey() function in your app to retrieve the API key:


val apiKey = NativeLib.getApiKey()
println("Retrieved API Key: $apiKey")

Warning: Avoid displaying sensitive data in logs or UI for additional security.

Testing and Verifying Security

Testing a native library in Android involves verifying the function outputs while ensuring the data is safely hidden. To unit test JNI code, consider mocking the JNI environment to simulate library outputs.

Example Unit Test

Here’s an example of how to test the function output:


class NativeLibTest {

    @Test
    fun `test API key retrieval`() {
        val apiKey = NativeLib.getApiKey()
        assertEquals("YourSensitiveApiKey", apiKey)
    }
}

Following these steps will allow you to create a native library that securely handles sensitive data in your Android application, enhancing both the performance and security of your app.

Did you like this article?
You can subscribe to my newsletter below and get updates about my new articles.

Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *