Security with Android

Hacı Kanal
5 min readFeb 20, 2022

Important things for some or maybe not. You can know by reading it.

I am not an expert on this topic particularly and not very likely to be an expert since Security means vastness, however this is not an obstacle to learn basic concepts of Android Security.

As an experienced android developer for many years, I have worked with variety of projects that require at least a few security precautions. Most of the time we got help from experts but what if you’re on your own? Learning it by yourself, or understanding the basics would help.

So I created a module for anyone who wants to be interested in:

Before scrolling down, I’d like to remind that nothing is 100 percent safe, we are just mitigating the possibilities by creating a layered architecture for security.

Friendly Reminder: These are just prototypes that I have created, you can freely use it but not pentested yet also this can be changed for your requirements. So do not rely on this completely, make your own tests and copy the codebase and update accordingly.

Starting with ProGuard

R8(D8)

I still call it ProGuard because it is easy to say, and I used to it but it is now officially R8 (advanced D8).

What these tools are doing is optimizing, obfuscating and shrinking the code also the resources. These tools are very easy to use and very effective. Android team has great document here, have a read. https://developer.android.com/studio/build/shrink-code

Avoiding SSL Exploits

Security Provider

TLS/SSL is a concept that provides secure communication between host and client.

One important thing here is, the older android versions or devices you have, more risks you get. Here is the list of my android devices for sale on my market. Nope, just kidding!

At first step, we are going to check whether our Security Provider is up to date.

https://developer.android.com/training/articles/security-gms-provider

You can choose to implement your one by considering the android article above or the one I created that provides abstraction and easy implementation. (Check the github repo shared in the first block of reading.)

val playSecurity = AdessoSecurityProvider.getDefaultSecurityProvider(context)

playSecurity.update()

playSecurity.updateAsync(callback)

SSL Pinning

Since there are many articles and good documentation about this particular case, I will not try to elaborate.

1-The network security config method which is explained very well in here.

https://developer.android.com/training/articles/security-config

2- Programatic Way (Assuming that we are using mainly OkHttp but you can use trust store for Volley)

Using PublicKey

publicKeyPinner

.add( “*.adesso.de”, CertificateUtility.fromAssets(this)[0], PublicKeyPinner.Algorithm.SHA_1 )

.add(“**.adesso.de”, CertificateUtility.fromAssets(this)[0])

.add(“www.adesso.de”, CertificateUtility.fromAssets(this)[0])

.pin()

Using Certificate & Trust Store

trustStore

.trust( “alias”, CertificateUtility.fromFile( filesDir.path, “app_certificate”, CertificateUtility.Extension.DER ) )

AdessoSecurityProvider

.getOkHttpCertPinner()

.pin(okhttpClientBuilder, socketProvider.getFactory(), trustStore.getTrustManagers()[0])

Data Security

Encryption, Integrity, Persistency

We have to take care of our important data in a more diligent way. The best way to keep data safe is never ever store it in the android devices, do not directly expose to backend or decide what data you should send/share to host/backend/3rd parties.

As we read above, TLS/SSL connections and SSL Pinning created us a secure tunnel and all the data encrypted by default, but this tunnel can be redirected to insecure tunnels by SSL Exploits and this can lead to our data can be seen as plain text. So what we should do is creating another layer for sensitive data.

That being said, there are not many options left us but Encryption.

Asymmetric and Symmetric Encryption

Briefly, Symmetric encryption is a key data (private key) used for encryption and decryption. This is relatively secure but highly dependent on the algorithm you choose and whether you are exposing key data or not. If you are not sure what you are doing, consider getting professional support, this is very important.

On the other hand, Asymmetric Encryption is considered way safer than Symmetric encryption. With this approach, you have 2 encryption keys called Public and Private keys.

As obvious public key can be shared freely(just because you can share it, you don’t mean to share it) because it will only be used for Encryption and your private key will be used for Decryption. So who holds the private key can decrypt the data and private key shouldn’t be transferred over network or stored. If you need to store it, you can store it with master key, paid obfuscation tools etc.

Public and Private keys are differs from each, however they are mathematically identical to each other, so you won’t be able to use random public key for this purpose. You have to generate both by using 3rd party security libs or java cryptography extensions.

Data Security with AES Symmetric algorithm

val encrypted = aesEncrypt(“text”) { specs = AesAlgorithmSpecs.GcmSpecs()}

val encrypted = aesEncrypt(“text”) { specs = AesAlgorithmSpecs.CbcSpecs()}

Data integrity (Digital Signature)

The data sent over network or DB is still valid, consistent or accurate? If the data is not validated correctly, there is a possibility that someone changed or manipulated the data. That can lead your program to could not function properly. This concept is widely used for documents, files, messages.

Data Integrity with RSA(Asymmetric) algorithm

rsaSign(textToSign) { pair, signValue ->

keyPair = pair

signedText = signValue

}

rsaVerify(textToSign, signedText, keyPair.public)

Data integrity (Secure Hashing)

Unlike encryption, hashing is one way. Which means once you get hash of the data you have, there is no way that you can find the original data or plain text from hash. So what is it used for? These are mostly used for authentication systems but I have used MD5 Hash(which is not considered safe anymore) for only local cache systems a few times, since hash of a data never changes, it will give you the same result every time.

val secureHash =

sha(SecureHash.Algorithm.SHA2_512) { “text” }

val secureHash=

sha(SecureHash.Algorithm.SHA3_512, EncodingType.HEX) { “text” }

Data Persistency

Of course, when you dive into more technical stuff you will realize that nothing is perfect. Every concept, every algorithm has pros and cons, so what are they?

Algorithms, concepts by created android jetpack, keystore etc.. sometimes can be specific to android versions, java versions(other languages too!) or even the device manufacturers.

Considering these important things, this is how we safely persist data on the device.

Android KeyStore system for Cryptography keys, details explained here.

https://developer.android.com/training/articles/keystore

https://developer.android.com/topic/security/data

https://developer.android.com/reference/androidx/security/crypto/MasterKey

Conclusion

I want to take a note to myself because all these readings, developments and experiences has shown me security is an enjoying part of the development but if you do a mistake it will turn into something you don’t want to see.

Always read from 3 to 5 different sources. In every article you can see different points.

Don’t try to create your custom encryption implementation if it is very sensitive app or data, get an expert opinion or use known algorithms

Always follow up to date security standarts, one of the easiest ways is updating your software.

Consider every possible edge cases.

Thank you for reading.

--

--

Hacı Kanal

Android Developer currently at Adesso Turkey, Retired Indie Game Developer, Amateur endurance cyclist