article
Protect Secrets in your app - Introduction - Part 1
Nothing shipped within an app is ever fully protected. If it is in the app it can be reverse engineered. You can do the best to make it harder and more time consuming to retrieve and extract secrets.
Many applications out there depend on features provided from SDKs, which are usually protected with a SDK Key and SDK Secret which are required during configuration.
Sadly most SDK guides stop after describing on how to initialize their SDK with static strings, and do not go into detail regarding security concerns.
Let's have a look at two minimalistic usecases. Once defining the key and secret via source and once from resources.
// source
FunSdk.init("amazing-key", "super-secure-secret")
// resources
FunSdk.init(getString(R.string.key), getString(R.string.secret))
This sadly leaves the key and secret exposed and allows for easy extraction from the published application.
You wonder how simple it is to retrieve those?
Let's have a look. Luckily Android Studio ships with a built in APK Analyzer which makes it simple to look into a compiled app.
Dragging the APK onto Android Studio will grant you with a nice overview of the APK. Beside highlighting
- APK Size (Raw size of the APK)
- Download Size (if downloaded from Google Play store)
- Contents and their size of the APK
- dex files
- ressources
As the app will most likely exceed the 64k method limit (jetpack, ...) the app will include multiple dex files.

An attacker will most likely start with the AndroidManifest.xml
to find the package name or for example the specification of a Application
class, which in many cases is the place sdks get initialized.
In this sample case:
android:name="com.mikepenz.credsshowcase.CustomApplication"
The next step is to find the .dex
file including this class. Clicking on such a file will show its contents (You can toggle "Show defined methods and fields" to speed this up). classes.dex
and classes2.dex
don't include it in this case, but classes3.dex
is a success.

Another great features of the APK analyzer is the possibility to check out the bytecode. Right click on the CustomAppliation
and click "Show bytecode".
And there it is already. key
and secret
in clear text.

Similar to the source the analyzer also has a feature to look into the resources of an app. Click on the resources.arsc
for this. Let's look into string
s. This will give a great list of all strings in the app. Including our key
and secret
.

If you have looked closely you may say now: 'Oh well that was only the debug app, the release version will be a lot harder as it has obfuscation and minification via R8.'

Nice try, but it actually got even easier, as R8 was doing a great job by combining all sources into a single .dex
file. The resources stayed the same as those won't be modified by release builds.
Android apps use Kotlin (or Java) which is compiled into Java bytecode. From the perspective of protecting the app code, and keys and secrets this makes it very easy to reverse engineer.
R8 which obfuscates the app was designed to minify the code and not to protect it. There are paid solutions out there, like DexGuard or other product offerings which will try to make it even harder to reverse engineer an app, splitting strings and putting them into different locations.
Paid products are not a solution for most of us, but there's an alternative which can still help to enhance protection of keys and secrets. Native code.
Thanks to improvements of the Android tooling and full support of native code this is rather simple to achieve.