My E-Journal... To share my experiences, thoughts etc..


Tuesday, November 10, 2015

Building Qt SQLcipher Driver Plugin



Below are the steps that I followed to install and build sqlcipher driver plugin for Qt in kubuntu 14.04. Qt5.3.1 was already installed on top of it
  1. git clone https://github.com/sqlcipher/sqlcipher
  1. cd sqlcipher
  1. ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS" LDFLAGS="-lcrypto"
  1. make
  1. sudo make install
If you get errors anywhere in the above steps, please don't panic and  try to "google" the error as you might need to install some dependent libraries for the steps to work. :)
Now, Follow the below steps,
1. Build Qt-QSQLCIPHER-driver-plugin

* Create directory:
\
    \Qt5.3.1\5.3\Src\qtbase\src\plugins\sqldrivers\sqlcipher

* Create the following three files within the new directory:

File 1: smain.cpp:
*****************************************************************
#include
#include
#include "../../../../src/sql/drivers/sqlite/qsql_sqlite_p.h"
QT_BEGIN_NAMESPACE

class QSQLCipherDriverPlugin : public QSqlDriverPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QSqlDriverFactoryInterface" FILE "sqlcipher.json")

public:
QSQLCipherDriverPlugin();

QSqlDriver* create(const QString &) Q_DECL_OVERRIDE;
};

QSQLCipherDriverPlugin::QSQLCipherDriverPlugin()
:QSqlDriverPlugin()
{
}

QSqlDriver* QSQLCipherDriverPlugin::create(const QString &name)
{
if (name == QLatin1String("QSQLCIPHER")) {
QSQLiteDriver* driver = new QSQLiteDriver();
return driver;
}
return 0;
}

QT_END_NAMESPACE

#include "smain.moc"
********************************************************************



File 2: sqlcipher.pro
==========================
TARGET=qsqlcipher
SOURCES = smain.cpp
OTHER_FILES += sqlcipher.json
include(../../../sql/drivers/sqlcipher/qsql_sqlite.pri)
wince*: DEFINES += HAVE_LOCALTIME_S=0
PLUGIN_CLASS_NAME = QSQLCipherDriverPlugin
include(../qsqldriverbase.pri)

*************************************************************************

File 3: sqlcipher.json
=============================
{
"Keys": [ "QSQLCIPHER" ]
}

****************************************************************

2. Copy directory
    \Qt5.3.1\5.3\Src\qtbase\src\sql\drivers\sqlite to

3. Customize file
The content of the file shall be like:

HEADERS += $$PWD/qsql_sqlite_p.h
SOURCES += $$PWD/qsql_sqlite.cpp
!system-sqlite:!contains(LIBS, .*sqlite3.*) {
include($$PWD/../../../3rdparty/sqlcipher.pri) #<-- change="" font="" here="" of="" path="" sqlcipher.pri="" sqlite.pri="" to="">
} else {
LIBS += $$QT_LFLAGS_SQLITE
QMAKE_CXXFLAGS *= $$QT_CFLAGS_SQLITE
}

Note: The remaining two files in this directory need not to be changed.

4. Create file 'sqlcipher.pri' in directory
CONFIG(release, debug|release):DEFINES *= NDEBUG
DEFINES += SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_RTREE SQLITE_HAS_CODEC SQLITE_HAS_CODEC SQLCIPHER_CRYPTO_OPENSSL SQLITE_OS_UNIX=1
!contains(CONFIG, largefile):DEFINES += SQLITE_DISABLE_LFS
contains(QT_CONFIG, posix_fallocate):DEFINES += HAVE_POSIX_FALLOCATE=1
INCLUDEPATH += $$PWD/sqlcipher
SOURCES +=$$PWD/sqlcipher/sqlite3.c
LIBS += -L$$PWD/sqlcipher/lib -lsqlcipher -lsqlite3 -lcrypto
TR_EXCLUDE += $$PWD/*

5. Create and fill /Qt5.3.1/5.3/Src/qtbase/src/3rdparty/sqlcipher
  • Create the two directories:

    /Qt5.3.1/5.3/Src/qtbase/src/3rdparty/sqlcipher
    /Qt5.3.1/5.3/Src/qtbase/src/3rdparty/sqlcipher/lib
  • Copy the following files to /Qt5.3.1/5.3/Src/qtbase/src/3rdparty/sqlcipher:

    git cloned sqlcipher>\sqlcipher\shell.c
    git cloned sqlcipher>\sqlcipher\sqlite3.c
    git cloned sqlcipher>\sqlcipher\sqlite3.h
    git cloned sqlcipher>\sqlcipher\sqlite3ext.h
  • Copy the following file/directories to /Qt5.3.1/5.3/Src/qtbase/src/3rdparty/sqlcipher/lib:

    git cloned sqlcipher>\sqlcipher\dist\lib
  • The directory now consists of the following files and directories:

    /Qt5.3.1/5.3/Src/qtbase/src/3rdparty/sqlcipher
    |
    shell.c
    |
    sqlite3.c
    |
    sqlite3.h
    |
    sqlite3ext.h
    |
    \---lib
    |
    libsqlcipher.so
    |
    libsqlcipher.a
    |
    libsqlcipher.la
    |
    libsqlcipher.so.0
    |
    libsqlcipher.so.0.8.6
    \---pkgconfig
    sqlcipher.pc
6. Compile the QSQLCIPHER-driver-plugin for Qt:
* Execute the following commands:cd /opt/Qt5.3.1/5.3/Src/qtbase/src/plugins/sqldrivers/sqlcipher
* qmake (or) make
* This builds the QSQLCIPHER-driver-plugin within the following directory: /opt/Qt5.3.1/5.3/Src/qtbase/plugins/sqldrivers
  • libqsqlcipher.so
  • libqsqlite.so
  • libsqlcipher.so
7. Copy 'libqsqlcipher.so' to the SQL-driver-plugin-directory /Qt5.3.1/5.3/gcc_64/plugins/sqldrivers
Note:
  • Now restart your Qt creator and add QSQLCIPHER to your database as below,
    QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLCIPHER");
  • Or, Print the Drivers available currently using QSqlDatabase::drivers() to verify if QSQLCIPHER is loaded properly.
  • We faced few performance issues in my application due to frequent open and close of DB for each query. You could either think of making your DB class as singleton and try to avoid frequent opening and closing of DB as it is very time consuming and expensive to use the key derivation each time.
  • We happened to run a sqlcipher command to perform few opertions on unix shell script. Below is one example on how you could add multiple statements in one line along with key derivation(-line),
    sqlcipher -line -csv "/location/path/to/create/csv/file" "pragma key = myKey; SELECT * FROM tableName;"


1 comment: