Encrypting a database with SQLCipher

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.

Getting ready

To start with, we will download and set up your Android project with SQLCipher.

  1. Download the latest binary packages via the link on the SQLCipher GitHub page, or follow this direct link https://s3.amazonaws.com/sqlcipher/SQLCipher+for+Android+v3.0.0.zip.
  2. Unpack the ZIP file.
  3. Copy the icudt46l.zip file from /assets to /assets of your application.
  4. The /libs directory contains several JARs and folders containing native libraries.
  5. Copy the *.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.
  6. Both the ARM and x86 implementations of the native code are included; however, you'll probably only need the ARM-based native libraries. So, copy the armeabi folder to /libs of your application.

How to do it...

Let's create an encrypted SQLite database.

  1. There are several ways to handle SQLite database, either by working directly with the 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.*.
  2. The simplest way to create an encrypted SQLCipher database is to call 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)");
    
      }
  3. If you're using the 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);
    
    }
    }

Tip

The SQLCipher native libraries need to be loaded before any database operation can be completed using the SQLiteDatabase.loadLibs(context) statement. Ideally this call should be located in the onCreate lifecycle method of either a content provider or your application's application object.

How it works…

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.

There's more...

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.

IOCipher

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.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.69.50