Skip to content

zplesac/secure-storage-android

 
 

Repository files navigation

Secure Device Storage - Android

Storing Credentials Securely on Android Devices

Build Status Download Android Arsenal Close

Introduction

Storing Credentials securely on a Device is a must. To make that possible we have combined the Android Keystore for generating Cryptographic keys, and storing them securely and using those keys we encrypt the credentials and save them in the SharedPreferences.

The cool thing about that is that those generated keys are never exposed to the kernel when the device is equipped with a “Trusted Execution Environment”. A so called TEE is a secure area inside the main processor of a smartphone which runs code isolated from other processes. That means even if the device gets compromised or hacked those keys can’t be easily extracted. Already 80–90% of all modern Android phones out there are equipped with a TEE (mostly because it’s often used to play DRM protected material) and it even is a requirement for Google’s Android Nougat certification — so every new phone running Android Nougat will come with a TEE installed.

We also use specific SharedPrefences only for the Secure Device Storage module, so as not to have conflicts with other possible SharedPreferences instances. This also means that the content of the SharedPreferences can only be read from the app where the module is implemented and not from other apps.

Even if the credentials where to be gotten somehow, they would be in an encrypted form which is nearly-impposible to decrypt without having the Cryptographic key used to encrypt it, which as was stated earlier is pretty secure itself sitting in the TEE.

Supported API's

Symmetric key generation and storage in the Android KeyStore is supported from Android 6.0 (API Level 23) onwards. Asymmetric key generation and storage in the Android KeyStore is supported from Android 4.3 (API Level 18) onwards.

To support more devices we have used the Assymetric key generation, which in the case of storing simple credentials is very secure and the potential lack of speed in contrast to symmetric key generation, is not noticeable.

Usage

Add the module to your apps build.gradle:

compile 'de.adorsys.android:securestoragelibrary:0.0.3'

To store a string value in our SecurePreferences you have to call:

SecurePreferences.setValue(context, "KEY", "PLAIN_MESSAGE");

This works for every other primitive data type. So for storing a boolean value:

SecurePreferences.setValue(context, "KEY", true/false);

for int

SecurePreferences.setValue(context, "KEY", 100);

for float and long

SecurePreferences.setValue(context, "KEY", 100.12345);

To retrieve a string value:

SecurePreferences.getStringValue(context, "KEY");

And respectively for the other types

SecurePreferences.getBooleanValue(context, "KEY");
SecurePreferences.getIntValue(context, "KEY");
SecurePreferences.getFloatValue(context, "KEY");
SecurePreferences.getLongValue(context, "KEY");

You can also remove an entry from the SecurePreferences

SecurePreferences.removeValue(context, "KEY");

There also is a method for clearing the SecurePreferences and deleting the KeyPair. To do that call:

SecurePreferences.clearAllValues(context);

Everything about the cryptographic keys such as generating, maintaining and usage is handled internally by the module, so you do not need to worry about it.

Error handling

The library throws for everything a SecureStorageException. Within the SecureStorageException you can find a exception type. You can handle the error which occurred with the help of this type as follows:

try {
    SecurePreferences.setValue(context, KEY, "Secret")
    // or
    val decryptedMessage = SecurePreferences.getStringValue(context, KEY, "")
} catch (e: SecureStorageException) {
    handleException(e)
}
//
private fun handleException(e: SecureStorageException) {
    Log.e(TAG, e.message)
    when (e.type) {
        KEYSTORE_NOT_SUPPORTED_EXCEPTION -> Toast.makeText(this, "Oh", Toast.LENGTH_LONG).show()
        KEYSTORE_EXCEPTION -> Toast.makeText(this, "Fatal - YARK", Toast.LENGTH_LONG).show()
        CRYPTO_EXCEPTION -> Toast.makeText(this, "2h&$==0j", Toast.LENGTH_LONG).show()
        INTERNAL_LIBRARY_EXCEPTION -> Toast.makeText(this, "Blame it all on us", Toast.LENGTH_LONG).show()
        else -> return
    }
}

Contributors:

@drilonreqica

@itsmortoncornelius

Want to know more:

These links cover security aspect of the android keystore:
https://developer.android.com/training/articles/keystore.html#SecurityFeatures
https://source.android.com/security/keystore/
https://codingquestion.blogspot.de/2016/09/how-to-use-android-keystore-api-with.html
http://nelenkov.blogspot.de/2012/05/storing-application-secrets-in-androids.html
http://nelenkov.blogspot.de/2015/06/keystore-redesign-in-android-m.html
http://www.androidauthority.com/use-android-keystore-store-passwords-sensitive-information-623779/

This link covers security aspect of the android storage:
https://developer.android.com/guide/topics/data/data-storage.html
http://stackoverflow.com/a/26077852/3392276

About

Android Secure Storage Component

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 78.6%
  • Kotlin 20.1%
  • Shell 1.3%