Writing secure android applications – storing data
In this article I’m going to talk through options for storing files securely on device, on android. We will need to consider a number of factors before storing any files, including;
- Does this file need to be shared with other applications?
- Does this file need to be stored on the sdcard?
- Does your app have a Pin / password / fingerprint in order to enter the app?
- Is the data synchronised to the server?
- Is two factor authentication a practical solution for your application?
Some other considerations are the type of data you’re trying to store, some obvious examples are
- Room or some other sql backed database
- Shared preferences
- Files on disk
When your data is stored, on disk you need to consider the location. Broadly speaking, we have two main places to store data. On the shared, external storage or in private internal storage. The default response should usually be to store it on your internal, private storage. To do this, use the directory or subdirectory:
Using this as the base directory for your files means that without some kind of comprise or you introducing another mechanism for sharing the file, the file cannot be read.
For our other two main types of data storage, a database using sqlite, sqldelight or room the defaults will store files in our private directory.
val db = Room.databaseBuilder(
In this example the default directory is used — e.g. a private one. Again, this means in effect that there is no way for an attacker to access the database without some other vulnerability.
Finally, the most common way of storing key value pairs is shared preferences, which are again, by default stored in your private file storage.
val sharedPref = activity?.getSharedPreferences(
Moving on now to the storing data in a public location, there are three things to note about storing things in a public place;
- Placing your files in a public place does not allow you to control — through permissions or otherwise — who is able to access the files.
- There are ways of sharing files with other apps which are less permissive
- Little or no protection is provided for externally stored files with removable media when a phone is lost or stolen.
Depending on the type of data you want to store externally, you are advised to use either https://developer.android.com/training/data-storage/shared/media or https://developer.android.com/training/data-storage/shared/documents-files depending on if you’re storing media (videos, pictures, audio) or documents.
There is also the option of replacing previous usages of
to make your files accessible from the SDCard.
Rule of thumb: If you don’t need files to be accessible to other applications like file managers — store things in a private directory.
Sharing data with other applications
Depending on the type of data you want to share with other applications, it is recommended to use:
Sharing simple data | Android Developers
One of the great things about Android apps is their ability to communicate and integrate with each other. Why reinvent…
For sharing small amounts of data, or else
Sharing files | Android Developers
Apps often have a need to offer one or more of their files to another app. For example, an image gallery may want to…
for sharing files.
Content providers | Android Developers
Content providers can help an application manage access to data stored by itself, stored by other apps, and provide a…
for sharing data stored in a database or for sharing other structure content.
Security considerations when sharing data
When sharing data with other applications, you need to consider the following things:
- Is it appropriate for the application to request a permission before being able access your apps data
- Is a user able to modify any data stored in my database? Are they able to modify files? Are they able to replace or delete files?
- Is it clear to the user which application is getting access to their data, and is it clear which bits of data they can access?
- Can your mechanism for sharing one file be abused to give access to another file?
Rule of thumb: provide the least access needed for other applications to do their job
In our next article we’ll conver in depth how to encrypt shared preferences, files and databases but for now let’s discuss the benefits of encrypting files.
In short, an encrypted file cannot be read without the decryption key, and a file cannot be modified without the encryption key (or else it will be corrupted / destroyed). One thing to note is that a file that is encrypted with no other protection can be deleted or re-encrypted for example by ransom ware. This is an important distinction between encrypting your file on the sdcard, or storing it in a private location.
Another key differentiation between private storage and encryption in a public place is the ability to decrypt it. As we’ll discuss in a moment, there are two main ways of generating an encryption key securely — either using secure random and storing it in the android keystore or a password based key derivation algorithm. The weakness of the former is that the implementation of the keystore may vary from device to device, on newer devices it’s likely to be backed by hardware encryption whereas the latter has the same vulnerabilities as is usual with user generated passwords e.g. they can be lost, forgotten, too short or written down. That said, encrypting your files that need to be protected is an incredibly effective security measure, and there are two things to consider when doing so:
- Which algorithm will be used for encryption
- How will you be generating the key.
The algorithm suggested by Google is `MasterKeys.AES256_GCM_SPEC` which is an industry standard for encryption. There are other perfectly good algorithms for symmetric encryption, but there isn’t often a need to use any but aes
There are two ways I’m going to describe to generate keys, these are the best recommendations for generating encryption keys on Android; there is however a situation where you need to encrypt files that are used by the server — we will cover this another time.
- When a file only ever needs to be encrypted and decrypted on the same phone, and the user does not have to enter a pin or password
- When a user does need to enter a password and the file can either be decrypted on or off the device
On device, no password
The first method is provided for us in the android security library
keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
In this case, encryption is done using the android keystore, on newer phones it is done using a specific piece of hardware used for security and is therefore not vulnerable to more common android vulnerabilities. Finally, the way it works is by handling the encryption and decryption for you which means there’s no storage of the master key anywhere that it might be leaked (easily).
On device, password
The specific implementation of a password based encryption we’ll cover later but for now we’ll cover the general idea of using a password for encryption.
Don’t just use the password as a key
There is a debate about the algorithm best used on Android for password based key derivation, but we would recommend PBKDF2 which is an algorithm taking a user password and providing a key. There are some security issues with this which are addressed by other algorithms such as bcrypt, however without native support for bcrypt we would suggest PBKDF2.
The flow for encryption is as follows:
- Capture user passwords
- Ensure it meets criteria of length, uppercase and lowercase, numbers and special characters
- Pass the password into the PBKDF2 algorithm
- Use the output to encrypt your data
For maximising security, you should
- Store data in a private location within your application sandbox
- Encrypt the file with either the keystore or a password (or both)
- Share the file using the appropriate API for the task, ensure your user is aware of how the file is being shared and