Android provides a simple framework for app developers to persistently store key-value pairs of primitive datatypes. This recipe illustrates a practical use of a pseudorandomly generated secret key and demonstrates the use of Secure-Preferences . It is an open source library that wraps the default Android SharedPreferences to encrypt the key-value pairs for protecting them against attackers. Secure-Preferences is compatible with Android 2.1+, and is licensed with Apache 2.0; hence, it is suitable for commercial development.
I should add that I'm the co-creator and maintainer of the Secure-Preferences library. A good alternative to Secure-Preferences is a library called Cwac-prefs that is backed by SQLCipher (covered in a later recipe).
Let's add the Secure-Preferences library.
The Secure-Preferences repository contains an Android library project and a sample project.
Let's get started.
SecurePreferences
object with Android context
:SharedPreferences prefs = SecurePreferences(context); Editor edit = prefs.edit(); edit.putString("pref_fav_book", "androidsecuritycookbook"); edit.apply();
private SharedPreferences mPrefs; public final SharedPreferences getSharedPrefs() { if (null == mPrefs) { mPrefs = new SecurePreferences(YourApplication.this); } return mPrefs; }
Here, YourApplication.this
is a reference to your application object.
BaseActivity
, BaseFragment
, or BaseService
, you can include the following to retrieve an instance of the (secure) preferences object:private SharedPreferences mPrefs; protected final SharedPreferences getSharedPrefs() { if (null == mPrefs) { mPrefs = YourApplication.getInstance().getSharedPrefs(); } return mPrefs; }
The Secure-Preferences library implements the SharedPreferences
interface; therefore, no code changes are needed to interact with it in comparison to the default SharedPreferences.
Standard SharedPreferences keys and values are stored in a simple XML file and Secure-Preferences uses the same storage mechanism; except that the keys and values are transparently encrypted using an AES symmetric key. The cipher text of keys and values are encoded with base64 encoding before writing to the file.
If you examine the following SharedPreference XML file; it shows without and with the Secure-Preferences library. You'll see the file from the Secure-Preferences library is a collection of seemingly random entries that give no clue to their purpose.
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <int name="timeout " value="500" /> <boolean name="is_logged_in" value="true" /> <string name="pref_fav_book">androidsecuritycookbook</string> </map>
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="MIIEpQIBAAKCAQEAyb6BkBms39I7imXMO0UW1EDJsbGNs"> HhiXTk3JRgAMuK0wosHLLfaVvRUuT3ICK </string> <string name="TuwbBU0IrAyL9znGBJ87uEi7pW0FwYwX8SZiiKnD2VZ7"> va6l7hf5imdM+P3KA3Jk5OZwFj1/Ed2 </string> <string name="8lqCQqn73Uo84Rj">k73tlfVNYsPshll19ztma7U"> tEcsr41t5orGWT9/pqJrMC5x503cc= </string> </map>
The first time SecurePreferences
is instantiated, an AES encryption key is generated and stored. This key is used to encrypt/decrypt all future keys/values that are saved via the standard SharedPreferences
interface.
The shared preference file is created with Context.MODE_PRIVATE
that enforces app sandbox security and ensures that only your app has access. However, in the case of rooted devices, sandbox security cannot be relied upon. More correctly, Secure-Preferences is obfuscating the preferences; therefore, this should not be considered as bulletproof security. Instead, view it as a quick win for incrementally making an Android app more secure. For instance, it will stop users on rooted devices easily modifying your app's SharedPreferences.
Secure-Preferences could be further enhanced to generate the key based on the user input password using a technique called password-based encryption (PBE ), which is covered in the next chapter.
SharedPreferences
interface in the Android Developers Reference guide at https://developer.android.com/reference/android/content/SharedPreferences.html3.128.226.121