SQLCipher for Linux C/C++

Commercial & Enterprise Edition Feature

Buy SQLCipher for Linux Now »

SQLCipher for Linux provides full database encryption when targeting C or C++ projects. The pre-compiled binaries allow for easy inclusion in your project whether you prefer dynamic or static linking. SQLCipher for Linux includes processor support for x86, x86_64, arm, and arm64 architectures.

The SQLCipher for Linux package includes the following components:

  • Header files (include/): sqlite3.h, sqlite3ext.h, and sqlite3session.h
  • Libraries (libs/): Platform-specific directories (arm, arm64, x86, x86_64) each containing:
    • libsqlcipher.so - dynamic library
    • libsqlcipher.a - static library
    • libcrypto.a - OpenSSL cryptographic library
  • Example project (examples/sqlcipher-c/): A complete working example with Makefile demonstrating compilation and linking

SQLCipher for Linux allows for either dynamic or static linking for integration.

Dynamic linking uses the shared library libsqlcipher.so. The shared library must be available at runtime, either by installing it in a system library path or by placing it alongside the application binary and using rpath.

  1. Copy the libsqlcipher.so from the appropriate platform directory (e.g. libs/x86_64/) to your project's build directory or a known library path.
  2. Compile your application with the SQLCipher include path and the SQLITE_HAS_CODEC preprocessor definition:
    cc -I/path/to/sqlcipher/include -DSQLITE_HAS_CODEC -c myapp.c -o myapp.o
    
  3. Link your application against libsqlcipher.so. Use -Wl,-rpath to ensure the dynamic linker can locate the shared library at runtime relative to the binary:
    cc myapp.o -o myapp -L/path/to/libs -lsqlcipher -Wl,-rpath,'$ORIGIN'
    

The following is a complete Makefile example for dynamic linking on x86_64:

CFLAGS := -I../../include -DSQLITE_HAS_CODEC
LDFLAGS := -L. -lsqlcipher -Wl,-rpath,'$$ORIGIN'

all: myapp

myapp: myapp.c
	cp ../../libs/x86_64/libsqlcipher.so .
	cc $^ -o $@ $(CFLAGS) $(LDFLAGS)

clean:
	-rm myapp

Static linking embeds SQLCipher directly into the application binary, eliminating the need to distribute the shared library alongside the executable. When linking statically, you must also link libcrypto.a (included in the package) along with the required system libraries.

  1. Compile your application with the SQLCipher include path and the SQLITE_HAS_CODEC preprocessor definition:
    cc -I/path/to/sqlcipher/include -DSQLITE_HAS_CODEC -c myapp.c -o myapp.o
    
  2. Link your application against the static libraries. Include libsqlcipher.a, libcrypto.a, and the required system libraries -lpthread and -ldl:
    cc myapp.o -o myapp -L/path/to/libs/x86_64 -l:libsqlcipher.a -l:libcrypto.a -lpthread -ldl
    
#include <stdio.h>
#include <string.h>
#include "sqlite3.h"

int main()
{
    int rc = 0;
    sqlite3* db;
    sqlite3_stmt* stmt = NULL;
    const char* password = "demo";

    rc = sqlite3_open("demo.db", &db);
    if (rc != SQLITE_OK) {
        printf("Failed to open database\n");
        goto done;
    }

    rc = sqlite3_key(db, password, strlen(password));
    if (rc != SQLITE_OK) {
        printf("Failed to key database\n");
        goto done;
    }

    rc = sqlite3_exec(db, "PRAGMA cipher_license = '*** SET LICENSE CODE HERE ***';", NULL, NULL, NULL);
    if (rc != SQLITE_OK) {
        goto error;
    }

    rc = sqlite3_prepare(db, "PRAGMA cipher_version;", -1, &stmt, NULL);
    rc = sqlite3_step(stmt);
    if (rc == SQLITE_ROW) {
        printf("SQLCipher version: %s\n", sqlite3_column_text(stmt, 0));
    }
    sqlite3_finalize(stmt);

    rc = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS t1(a, b);", NULL, NULL, NULL);
    if (rc != SQLITE_OK) {
        goto error;
    }
    printf("Created table succeeded\n");

    rc = sqlite3_prepare(db, "INSERT INTO t1(a, b) VALUES(?, ?);", -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        goto error;
    }
    sqlite3_bind_text(stmt, 1, "row one, column one", -1, NULL);
    sqlite3_bind_text(stmt, 2, "row one, column two", -1, NULL);
    rc = sqlite3_step(stmt);
    if (rc == SQLITE_DONE) {
        printf("Inserted data into t1 table\n");
    } else {
        printf("Failed to insert data into t1\n");
        goto error;
    }
    sqlite3_finalize(stmt);

    sqlite3_prepare(db, "SELECT * FROM t1;", -1, &stmt, NULL);
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        printf("a: %s  b: %s\n",
            (char*)sqlite3_column_text(stmt, 0),
            (char*)sqlite3_column_text(stmt, 1));
    }
    sqlite3_finalize(stmt);
    stmt = NULL;

    goto done;

error:
    if (rc != SQLITE_OK) {
        printf("An error occurred, error number: %d message: %s\n",
            sqlite3_errcode(db),
            sqlite3_errmsg(db));
    }

done:
    if (stmt != NULL) {
        sqlite3_finalize(stmt);
    }
    if (db != NULL) {
        sqlite3_close(db);
    }
    return 0;
}

This package can be purchased directly from the Zetetic Store and licensed software is delivered immediately upon payment.

Buy SQLCipher for Linux Now »

If you have additional comments or questions please contact us.