SQLCipher Support for Database Encryption

SQLite.swift provides first-class support for SQLCipher, an open-source extension to SQLite that provides transparent 256-bit AES encryption of database files.

Installation

To use SQLCipher, you must install SQLite.swift using the SQLCipher CocoaPods subspec. This automatically includes the SQLCipher pod and enables the encryption-specific extensions.

In your Podfile:

target 'YourAppTargetName' do
  # Make sure you only require the subspec. Do not add the base 'SQLite.swift' pod.
  pod 'SQLite.swift/SQLCipher', '~> 0.15.4'
end

Then run pod install.

Encrypting a New Database

To create a new encrypted database, simply open a connection and provide a key using the key() method immediately after.

import SQLite

let db = try Connection("path/to/encrypted.sqlite3")
try db.key("a-very-secret-password")

// The database is now encrypted. All subsequent operations are transparently encrypted/decrypted.
try db.run("CREATE TABLE secrets (id INTEGER PRIMARY KEY, data TEXT)")

Opening an Existing Encrypted Database

To open an existing encrypted database, you follow the same process: connect, then provide the key.

let db = try Connection("path/to/encrypted.sqlite3")
try db.key("a-very-secret-password")

// If the key is correct, you can now access the data.
let count = try db.scalar("SELECT count(*) FROM secrets")

If the key is incorrect, the key() method (or a subsequent database operation) will throw an error, typically with the result code SQLITE_NOTADB.

Changing the Encryption Key

To change the key of an already encrypted database, use the rekey() method. The database must first be unlocked with the current key.

let db = try Connection("path/to/encrypted.sqlite3")

// 1. Unlock with the old key
try db.key("a-very-secret-password")

// 2. Set the new key
try db.rekey("a-new-and-better-password")

Encrypting an Existing Plaintext Database

To encrypt a database that was not previously encrypted, you can use the sqlcipher_export() function. This attaches a new encrypted database and copies the content over.

let unencryptedDB = try Connection("path/to/unencrypted.sqlite3")

// Export the contents to a new, encrypted database
try unencryptedDB.sqlcipher_export(.uri("encrypted.sqlite3"), key: "a-very-secret-password")