How to Protect Your Android App with Obfuscation and Encryption

4.6 / 5.0
Article rating

A security breach can kill your app and your reputation. This is why it’s extremely important to make sure your app is secure, especially if you collect sensitive information from your users. In this article, I’ll talk about the main security techniques and best practices that will help you avoid hacker attacks and protect your mobile application before release.

How to protect Android applications from hackers

Security in mobile applications is non-negotiable. You can have a great set of features, a convenient user experience, and a beautiful interface, but if your Android app’s protection from hackers is weak, you’ll lose trust at best and be guilty of theft of sensitive user information at worst. This can cost you millions.

When a security breach occurs, it causes a scandal. People are concerned about privacy and security issues. According to Statista, the fear of exposing personal information is the biggest concern among those who make mobile payments.

payment gateway security concerns
When it comes to finances, people are most worried about how secure it is to transfer money via payment gateways

This is true not only for payments but for other types of apps as well.
Any app that requires information about users, whether it’s an email address or payment information, needs to be secure.

Ecommerce, healthcare, insurance, social media, and even fitness apps that track users’ location and health information all need to be thoroughly protected from hackers.

Let’s talk about methods you can use to protect Android apps from hackers.

Authentication and password management

It’s a bad idea to store passwords in a mobile app. No matter how well an app is protected, it’s still possible to steal a password. If lots of people use your app and they find out about a breach, you’ll be in trouble.

My advice is to use authentication tokens with limited lifetimes and store them in encrypted storage. Also, after a user enters a password, verification code from an SMS, or any other important information like a user ID for the first time, you should reset the variables and remove them from RAM. This will prevent a data leak.

Code obfuscation

When you release your app to an app market like Google Play or the App Store, you give public access to all the code to anyone. If someone gets the .apk file of your application, they’ll be able to decompile it and get the source code. After this, a hacker can do anything with it: install a virus, install a miner, or crack your app. Then, if someone installs this altered app from an unreliable source, the hacker will have a chance to access the user’s sensitive data or even get remote control over your app.

If you want an advanced obfuscator, be ready to pay a pretty penny. The cost will depend on how famous the program is, and it will not only obfuscate you code but also optimize it to shrink the .apk file size

To prevent such a scenario, I recommend using code obfuscation for Android. In this tutorial, I’ll show some android code obfuscation examples and explain how to protect Android apps from hacking using obfuscation tools.

Android obfuscation tools

Obfuscation is a mechanism that renames all classes and their members that aren’t entry points. Android has a default obfuscation utility called ProGuard. Turn it on by adding minifyEnabled true to your gradle file and appoint the file that will store all the rules of obfuscation, for example proguardFiles getDefaultProguardFile( ‘proguard-android.txt’ ), ‘proguard-rules.pro’.

ProGuard isn’t the best obfuscation tool for android, at least, it isn’t the most advanced one, but it’s an out-of-the-box solution for your security strategy and is rather easy to use. If you want a more upgraded obfuscator in comparison with ProGuard, be ready to pay a pretty penny. The cost will depend on how famous the program is. Most paid obfuscators will not only obfuscate your code but also optimize it, deleting code that isn’t used. This will help to shrink the size of the final .apk file.

Note that sometimes this can cause bugs in your app, though. If this risk exists for your app, skip this step. So, how to secure Android app from hackers using code obfuscation in android studio?

The initial obfuscation settings can look like this:

-dontwarn **CompatHoneycomb
-dontwarn **CompatHoneycombMR2
-dontwarn **CompatCreatorHoneycombMR2

-keepclasseswithmembernames class * {
    native ;
}
-keepclasseswithmembers class * {
    public  (android.content.Context, android.util.AttributrSet);
}

-keepclassmembers class * {
    public (android.content.Context);
 }
-keepattributes *Annotation*

You also need to include all entity classes that use sterilization (e.g. @SerializedName for parsing the answer for a request). Some third-party libraries can also require adding some settings in the configuration file of ProGuard. Usually you can find these settings in the library’s GitHub profile to setup obfuscation for a library.

For example, here are the settings for the Retrofit library:

retrofit library obfuscation settings
Each library has its settings for obfuscation. This is an example of such settings for Retrofit

In addition, I advise disabling the debugging mode in your app by adding debuggable false and making sure that logging in to your app is turned on. Otherwise, hackers will have a chance to get sensitive data just because you accidentally left a log.

Data storage and protection

User data is a very important part of your application, and you should pay extra attention to protecting it. My rule of thumb is this: the least user data is stored on a smartphone, the better, and everything that is stored must be encrypted. A mobile phone can be exposed to malware, or it can simply be stolen or lost.

To encrypt data in Android, you can use RSA and AES algorithms. AES is available only with Android API 23 and higher. For earlier API versions, you’ll need to use RSA.

Some people recommend authenticating a user each time the app is launched, either with a password or with biometric scanners like Touch ID. This surely increases the app’s security, but it’s not convenient for users. I usually seek a compromise, but in either case, data stored in databases or in SharedPreferences should be encrypted.

To encrypt data in Android, you can use RSA and AES algorithms. AES is available only with Android API 23 and higher. For earlier API versions, you’ll need to use RSA. The main issue with RSA encryption is that it can’t encrypt a massive amount of data. I prefer to use it only for encrypting small bits of data in SharedPreferences.

You can also use third-party libraries that present their own encrypted data storages, for example, com.github.hussainderry:secure-preferences.

Beginning with API 18, Android presented a key storage called AndroidKeyStore. As soon as the key appears in storage, it can be used for encryption but it can’t be exported. Only the app that created the key can use it.

This storage is very secure, and it can be implemented at the hardware level. AndroidKeyStore provides ways to manage key lifetimes and can request user authentication or use the key only in special encryption modes.

I use these functions to create keys:

  • For API 23 and higher
static void createKeysM(String alias) {
   try {
       KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
               KeyProperties.KEY_ALGORITHM_RSA, KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
       keyPairGenerator.initialize(
               new KeyGenParameterSpec.Builder(
                       alias,
                       KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                       .setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(4096, F4))
                       .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                       .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                       .setDigests(KeyProperties.DIGEST_SHA256,
                               KeyProperties.DIGEST_SHA384,
                               KeyProperties.DIGEST_SHA512)
                       // Only permit the private key to be used if the user has authenticated
                       // within the last five minutes.
                       .setUserAuthenticationRequired(false)
                       .build());
       KeyPair keyPair = keyPairGenerator.generateKeyPair();
       Log.d(TAG, "Public Key is: " + keyPair.getPublic().toString());

   } catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
       throw new RuntimeException(e);
   }
}
  • For APIs below 23
static void createKeysJBMR2(Context context, String alias) throws NoSuchProviderException,
       NoSuchAlgorithmException, InvalidAlgorithmParameterException {

   Calendar start = new GregorianCalendar();
   Calendar end = new GregorianCalendar();
   end.add(Calendar.YEAR, 30);

   KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
           // You'll use the alias later to retrieve the key. It's a key
           // for the key!
           .setAlias(alias)
           .setSubject(new X500Principal("CN=" + alias))
           .setSerialNumber(BigInteger.valueOf(Math.abs(alias.hashCode())))
           // Date range of validity for the generated pair.
           .setStartDate(start.getTime()).setEndDate(end.getTime())
           .build();

   KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
   kpGenerator.initialize(spec);
   KeyPair kp = kpGenerator.generateKeyPair();
   Log.d(TAG, "Public Key is: " + kp.getPublic().toString());

}

To get the key, I use this code:

public static String getSigningKey(String alias) {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
       Certificate cert = getPrivateKeyEntry(alias).getCertificate();
       if (cert == null) {
           return null;
       }
       try {
           return Base64.encodeToString(cert.getEncoded(), Base64.NO_WRAP);
       } catch (CertificateEncodingException e) {
           return null;
       }
   } else {
       return null;
   }
}

private static KeyStore.PrivateKeyEntry getPrivateKeyEntry(String alias) {
   try {
       KeyStore ks = KeyStore.getInstance(KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
       ks.load(null);
       KeyStore.Entry entry = ks.getEntry(alias, null);

       if (entry == null) {
           Log.w(TAG, "No key found under alias: " + alias);
           Log.w(TAG, "Exiting signData()...");
           return null;
       }

       if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
           Log.w(TAG, "Not an instance of a PrivateKeyEntry");
           Log.w(TAG, "Exiting signData()...");
           return null;
       }
       return (KeyStore.PrivateKeyEntry) entry;
   } catch (Exception e) {
       Log.e(TAG, e.getMessage(), e);
       return null;
   }
}

Remember that you shouldn’t store important data and encryption keys in RAM because it’s very easy to steal them from it. The best practice is to request the key from AndroidKeyStore each time. If some data has to be available for a short period of time, it should be encrypted.

Don’t store app data on external storage like a memory card because a hacker can take it out and get all the data off of it.

You also need to think through how you’re going to handle permissions. Don’t add unnecessary permissions because hackers can use them for extracting data as well. You should ask for permission to access certain data only if you need it for your app to achieve its goal.

Use of third-party libraries/code

If you use third-party libraries, you should choose them carefully. A library’s vulnerabilities will easily become your app’s vulnerabilities, which is why you should make sure a library is reliable and well-protected.

android library security
Choose only reliable libraries for your app, as a library’s vulnerability can easily become your own

You should also make sure that a library doesn’t transfer data to third parties — for example, to advertisers — and doesn’t have backdoors. Remember to update libraries as soon as you can because often developers get rid of security vulnerabilities in new versions.

Server controls

If your mobile app is more complex than a calculator, it’s probably connected to a backend. And this server part of your app also needs attention when it comes to security.

Just like for libraries, you need to update the operating system on your server. You also need to configure the server in such a way as to prevent SQL injection or SQL code from being transferred through GET and POST requests.

Ideally, the server should store logs. This will help you investigate what exactly has happened if you detect some abnormal activities. To prevent DDoS attacks, you need to identify each user, and if there are too many requests coming from a user, you need to limit the response speed or block requests altogether.

server security
It is very important to protect your server from hackers as it stores all the valuable data: use HTTPS and SSL pinning to prevent attacks

I probably don’t even need to mention that you should use HTTPS and not HTTP for communicating with the server. To add another layer of security, you can use SSL pinning. This operation prevents man-in-the-middle attacks by comparing the certificate from the server to the original.

Mobile application provisioning/distribution/testing

After your app is finally ready for release, you need to publish it. The Google Play Store and the Apple App Store are the two most popular app markets. They each have their own security system and allow publication only if an app has no malware. On app markets you can and must deactivate old versions of your app that have vulnerabilities – this is one of the ways to protect an Android app from hacking.

If your application stores lots of user data and has a large user base, the best option for you is to work with a reliable cybersecurity company.

Conclusion

We discussed how to avoid Android app hacking and mentioned all the security tips you need to make your application’s custom code hard to get. Nowadays, data security is one of the biggest issues in the tech world, and people are becoming more concerned about how companies handle their data.

With this, many users still don’t treat it seriously enough to install antivirus software on their devices, so you should take care of your code security yourself.

If you treat security seriously, you’ll not only avoid scandals and massive fines in case of a data breach but also gain a reputation as a reliable service that cares about users’ sensitive data.

If you have any questions about making your app secure, be sure to contact us. We’ve worked on large ecommerce and social media projects and we know how to protect user data from attackers.

Security development services
Do you want to protect your code from hackers?

Rate the article!

🌕 Cool!
🌖 Good
🌗 So-so
🌘 Meh
🌑 …