SQLCipher is one of the simplest ways to enable secure storage in an Android app, and it's compatible for devices running Android 2.1+. SQLCipher uses 256-bit AES in CBC mode to encrypt each database page; in addition, each page has its own random initialization vector to further increase security.
SQLCipher is a separate implementation of the SQLite database, and rather than implementing its own encryption, it uses the widely used and tested OpenSSL libcrypto
library. While this ensures greater security and wider compatibility, it does come with a relatively high .apk
file footprint of roughly 7 MB. This additional weight is probably the only disadvantage of using SQLCipher.
According to the SQLCipher website, in terms of read/write performance, there is a ~5 percent performance hit that is negligible unless your app is performing complex SQL joins (but it is worth noting that these aren't great in SQLite either). The good news for commercial development is that not only is SQLCipher for Android open source, it is also released under a BSD-style license.
To start with, we will download and set up your Android project with SQLCipher.
icudt46l.zip
file from /asset
s to /assets
of your application./libs
directory contains several JARs and folders containing native libraries.*.jar
files to you application's /libs
directory. You may already be using Commons-codec and/or guava; if so, check if the version is compatible with SQLCipher.armeabi
folder to /libs
of your application. Let's create an encrypted SQLite database.
SQLiteDatabase
object or using SQLiteOpenHelper
. But generally, if you are already using an SQLite database in your app, simply replace the import android.database.sqlite.*
statement with import net.sqlcipher.database.*
.openOrCreateDatabase(…)
with a password:private static final int DB_VERSION = 1; private static final String DB_NAME = "my_encrypted_data.db"; public void initDB(Context context, String password) { SQLiteDatabase.loadLibs(context); SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(DB_NAME, password, null); database.execSQL("create table MyTable(a, b)"); }
SQLiteOpenHelper
object, you would have extended it. In this example, we'll assume that your extension is called SQLCipherHelper
. When you call getWritableDatabase
, you'll notice that you are required to pass a string argument (the database passphrase) with SQLCipher's version of SQLiteOpenHelper
:import net.sqlcipher.database.SQLiteOpenHelper; public class SQLCipherHelper extends SQLiteOpenHelper { private static final int DB_VERSION = 1; private static final String DB_NAME = "my_encrypted_data.db"; public SQLCipherHelper (Context context) { super(context, DB_NAME, null, DB_VERSION); SQLiteDatabase.loadLibs(context); } }
The sample code illustrates the two most common ways of working with SQLite database: directly with the SQLiteDatabase
object or using SQLiteOpenHelper
.
The main point to note is the difference between using the net.sqlcipher.database
API and the default SQLite API is the use of passphrase when we create or retrieve the SQLCipher database object. SQLCipher derives the encryption key using PBKDF2
, as covered in the previous recipe. The default configuration generates a 256 bit AES key using 4,000 iterations at the time of writing this book. It's the job of the developer to decide how to generate the passphrase. You could generate using a PRNG on a per app basis or for greater randomness and so greater security input by the user. SQLCipher transparently encrypts and decrypts with the derived key. It also uses a message authentication code (MAC) to ensure both integrity and authenticity, ensuring that the data has not been accidently or maliciously tampered with.
It's worth noting that because much of SQLCipher is written in native C/C++, it is compatible with other platforms such as Linux, Windows, iOS, and Mac OS.
Think of IOCipher as SQLCipher's long lost cousin from the good people at the Guardian project. It offers the ability to mount an encrypted virtual filesystem that allows developers to transparently encrypt all files within their app's directory. As with SQLCipher, IOCipher relies on the developer to manage the password and supports Android 2.1+.
One huge advantage of IOCipher is that it is a clone of the java.io
API. This means that from an integration perspective, there are few code changes to the existing file management code. The difference is that the filesystem is first mounted with a password, and instead of using java.io.File
, you use info.guardianproject.iocipher.File
.
Even though IOCipher uses parts of SQLCipher, it is less mature but worth investigating if you wish to protect the files rather than data within SQLite database.
3.147.69.50