Clone or fork this project from GitHub: https://github.com/bmarrdev/AndroidDatabaseSQLCipher
Data security is a hot topic that will only intensify under the weight of the petabytes of information accumulating in data centres around the world. Securing your users data is no longer a bolt on afterthought, but a non-negotiable in any system that deals with sensitive data. It is not just the data centres that hold this sensitive data, those ever increasingly powerful computers we carry in our pockets or strap to our wrists are a treasure trove of personal information that others would love to get their hands on. As an app developer it is your responsibility to do everything in your power to protect the users of your product. In doing so you are not only protecting those users but the reputation of your company. Wherever possible you must avoid storing sensitive data within your app. This article discusses the pros and cons of encrypting your Android database with SQLCipher for the cases where you have no choice other than to store sensitive data.
SECTION 1: SQLCipher
SQLCipher is often the go to choice for Android apps for the following reasons:
- Strong encryption (256-bit AES)
- Mature technology
- Maintained and supported by its developers and the open source community
- Supports virtually the same API as standard Android database functions
Unfortunately there is no such thing as a free lunch, it is important to understand not only the benefits but also the consequences of switching to an encrypted database. Here are a few to consider:
- APK size will be increased substantially
- Database performance will decrease
- Secure management of the encryption key (or password) is required
- Use of strong encryption has legal considerations in some jurisdictions
Firstly there is APK size to consider. Using the sample project that accompanies this article as an example, a release build (without proguard enabled) of the APK expands from 1MB to over 9MB. This equates to 2-3MB for each architecture you want to support.
It is possible to build different APK files to support each architecture. When including SQLCipher this can lead to a significant reduction in the size of your app. For example, it reduces the size of the sample app included with this project by more than half if you build a separate app for each of armeabi, armeabi-v7a and x86. You can read more about distributing your app with multiple APK’s.
Any layer of encryption is going to come with a performance hit. SQLCipher is no different. If a 10-20% performance hit is going to impact the user experience of your app then you may want to look at different options. For most purposes the database in your app in unlikely to be big enough for this to cause an issue.
To encrypt and decrypt you need a key. SQLCipher does some of the hard work for you, encrypting a password into a key using PBKDF2. This password however still needs to be managed and should not be stored within your source code.
Apps that use strong cryptography, such as the algorithms used in SQLCipher, have obligations for compliance to the strict United States export requirements. You should not add any encryption without understanding what these export requirements are and what your obligations are. This will not be discussed further in the article, you should seek your own clarification.
Before you can publish your app on the Google Play Store you must acknowledge that your software application may be subject to United States export laws regardless of your location or nationality and you certify that your app is authorized for export under these laws.
Partial database encryption
SQLCipher is applied to a complete database. It does not support encryption of specific columns in your database.
SECTION 2: Add SQLCipher library to your app
Update August 2015: Commonsguy has released an unofficial GitHub repository that packages the SQLCipher for Android distribution in a standard Android library module. You can use this as an alternative to following the steps in this section to unpack the official version from Zetetic.
If, after careful consideration, you have decided that you just have to store that sensitive data, this is how to use SQLCipher to do it. These instructions are for Android Studio 1.0+, if you are an Eclipse user you should visit the SQLCipher project home for details about how to add the SQLCipher library to your Eclipse project. When developing in Android Studio your first port of call for including libraries should be through the Maven repository via your Gradle script. Unfortunately at this time SQLCipher is not available officially through Maven so we will have to get the libraries and import them manually.
Step 1: Download the SQLCipher for Android binaries from here: https://www.zetetic.net/sqlcipher/open-source
What are these libraries? SQLCipher is written in C code. These libraries (.so) have been build using the Android NDK, which allows native languages such as C and C++ to be compiled and used by your Android app. Unlike the Java code in your app which is compiled to bytecode to run in Androids VM (Dalvik or ART), this library contains native code that is architecture dependent. This means there is a library for will support each possible architecture that the target device may use.
Step 2: In your app\src\main directory create two new child folders named jniLibs and assets.
Step 3: From the binaries you downloaded in step 1, copy the contents of the assets folder into your newly created assets folder and copy the sub-folders from the libs folder into your newly created jniLibs folder. Be sure that you have named the folder correctly and copied all the files as well as the sub-folder for each architecture type you wish to support.
Step 4: From the binaries archive you downloaded in step 1 you now need to copy the jar files from the libs folder into app/libs. In addition to these jars you also need to copy guava-r09.jar and commons-codec.jar into this folder. Currently these are not included in the binaries archive above. If you download the sample project attached to this article you can find the jar files there.
Step 5: To ensure your project can find the libraries add an include in your gradle script for your app module, this should go in the dependencies section. (This may already be present in your gradle script)
compile fileTree(dir: 'libs', include: ['*.jar'])
SECTION 3: Replacing your Sqlite database with SQLCipher database
Now the SQLCipher library is added for your project you need to do a clean and rebuild. Follow the steps below to switch your sqlite database across to a SQLCipher database. This will work even if your sqlite database is within a content provider.
Step 1: Replace imports that reference standard Android sqlite database classes with SQLCipher classes. To do this look for any import from the standard database classes, for example:
import android.database.Cursor; import android.database.DatabaseUtils; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase;
Replace these with calls to the equivalent SQLCipher classes:
import net.sqlcipher.Cursor; import net.sqlcipher.DatabaseUtils; import net.sqlcipher.SQLException; import net.sqlcipher.database.SQLiteDatabase;
Step 2: Replace calls to open or create the database passing the password as an argument. For example:
Needs to be replaced with:
Step 3: Add the initialization call to SQLCipher. This must be called before any call the SQLCipher classes and you should ensure that this is only called once.
import net.sqlcipher.database.SQLiteDatabase; ... SQLiteDatabase.loadLibs(context);
Step 4: That’s it, build your app and run!
Remember to head over to GitHub to clone or fork the sample project: https://github.com/bmarrdev/AndroidDatabaseSQLCipher
SECTION 4: Distributing an App with native libraries
Since this article was initially release I have described in detail the considerations of distributing apps that include native libraries, such as those required by SQLCipher.
To learn more I recommend reviewing these articles: