← All posts
EncryptionSQLCipherChwilioCipherSecurity

Encrypt your SQLite databases with SQLCipher (and actually open them)

A plain SQLite file is readable by anyone who gets a copy. SQLCipher fixes that with whole-database AES-256 encryption, but most GUI tools can't open the result. ChwilioCipher can — opening, creating, and re-keying encrypted databases without ever dropping to the command line.

Chwilio6 min read

A SQLite database is a single, portable file. That’s its best feature. At rest, it’s also its scariest one, because the file is plaintext. Anyone who gets a copy of your .sqlite (from a lost laptop, a synced backup, a shared drive, a stolen phone) can open it and read every row. For a scratch database that’s fine. For messages, health records, API tokens, or anything you’d call private, it isn’t.

SQLCipher is the standard answer, and it’s the same technology behind encrypted local storage in apps like Signal. The catch has always been the desktop: once a database is encrypted, most SQLite browsers can’t open it at all. That’s the gap ChwilioCipher closes.

A SQLite file is plaintext by default

Open any ordinary .sqlite in a hex editor and the first sixteen bytes spell it out literally: SQLite format 3. Everything after is your schema and data, lightly structured but not hidden. Run strings mydata.db and it will happily print email addresses, notes, and tokens straight out of the file.

Encryption “at rest” is what protects data while it’s sitting on disk rather than moving over a network. Full-disk encryption (FileVault) helps while a machine is locked, but it does nothing once the file leaves that disk: copied to a USB stick, uploaded to a bucket, attached to a bug report. To protect the database itself, wherever it travels, the file has to be encrypted.

What SQLCipher does

SQLCipher is a build of SQLite with a transparent encryption layer bolted in underneath. You give it a passphrase, and from then on every page is encrypted before it touches the disk and decrypted as it’s read back. The application on top sees ordinary SQL; the file on disk is opaque ciphertext from byte zero.

Concretely, SQLCipher 4 gives you:

  • AES-256 encryption of the whole database, in CBC mode.
  • A per-page HMAC, so tampering is detected rather than silently returned as corrupt data.
  • A PBKDF2-derived key, so a passphrase is stretched into a strong key instead of used directly.
  • A random salt in the first 16 bytes of the file. That’s exactly why an encrypted database has no readable SQLite format 3 header.
  • Transparency. It’s a superset of SQLite, so a build that speaks SQLCipher still opens ordinary, unencrypted databases with no key and no fuss.

In ChwilioCipher the crypto comes from each platform’s own vetted primitives: Apple’s CommonCrypto on macOS, and a static-linked OpenSSL on Windows, which has no CommonCrypto. Either way nothing extra ships alongside the app, and both produce standard SQLCipher 4 files — a database encrypted on one platform opens on the other.

The catch: most tools can’t open an encrypted database

Here’s the practical problem. Because an encrypted file starts with a random salt instead of the familiar magic bytes, a normal SQLite tool takes one look and gives up:

$ sqlite3 secrets.db "SELECT * FROM notes;"
Error: file is not a database

It isn’t corrupt. It’s encrypted, and the plain tool has no way to tell the difference or supply a key. So encrypting a SQLite database has traditionally meant giving up your GUI and living in the sqlcipher command line: no data grid, no schema editor, no filters, no export, just a prompt. The security is the easy part. Working with the data afterward is what hurts.

ChwilioCipher: encrypted SQLite, natively

ChwilioCipher is the encrypted edition of Chwilio. It’s the same app, with the same data grid, SQL editor, schema tools, import/export, and extension loading, and SQLCipher running underneath. Nothing about the workflow changes except that encrypted files now just open.

  • Open an encrypted database. Pick the file and you get a native passphrase prompt, with an optional “remember in Keychain” toggle so you’re not retyping it. A wrong key re-prompts instead of throwing a cryptic error.
  • Plain files still just work. Because SQLCipher is a superset of SQLite, your existing unencrypted databases open with no prompt and no extra steps. One app for both.
  • Create a new encrypted database from scratch, or encrypt an existing plain one with a single menu action.
  • Change the passphrase in place (re-key) when you need to rotate it.
  • No accidental plaintext on disk. Copies, backups, and exports of an encrypted database stay encrypted unless you explicitly choose a plaintext export. A lock badge marks encrypted databases so you always know which is which.
  • Even over the network. ChwilioCipher can open an encrypted database straight from a URL, using the same Open from URL feature with a passphrase prompt for the remote file.
File ▸ New Encrypted Database…      → choose a passphrase, start clean
File ▸ Open…  (an encrypted file)   → passphrase prompt · optional Keychain
Database ▸ Change Passphrase…       → re-key in place
Database ▸ Encrypt Database…        → turn a plain file into an encrypted one

And it’s the same seat: one license activates both Chwilio and ChwilioCipher on the same machine — macOS or Windows — so you’re not buying encryption twice.

Under the hood, briefly

If you’re curious, everything above maps onto a handful of SQLCipher PRAGMAs that ChwilioCipher drives for you behind the menus:

-- Supply the key to open an encrypted database
PRAGMA key = 'correct horse battery staple';

-- Rotate the passphrase in place (re-key every page)
PRAGMA rekey = 'a new, stronger passphrase';

-- Turn a plain database into an encrypted copy
ATTACH DATABASE 'secrets.db' AS enc KEY 'correct horse battery staple';
SELECT sqlcipher_export('enc');
DETACH DATABASE enc;

-- Confirm what you're running
PRAGMA cipher_version;   -- e.g. 4.x

Because the encryption sits below SQL, the query planner, indexes, triggers, virtual tables, and loadable extensions all behave exactly as they do on a plain database. You get privacy at rest without giving up a single SQLite feature.


You can try this right now, for free. Chwilio is in private beta, and the beta build of ChwilioCipher unlocks full database encryption, and every other feature, for the whole beta period at no cost. Grab a beta invite and start creating encrypted databases today; you can even open an encrypted one over HTTP. When the beta period ends, access reverts to the free trial, and keeping these features needs a license. Questions about a specific setup? Get in touch.