如何使用 Windows/MinGW 平台使用 SQLCipher 扩展为 SQLite-DB 构建 Qt-SQL-driver-plugin 'QSQLCIPHER'?
这通常不是在哪里可以找到分步指南的问题,而是指南本身的问题.
我写这篇文章的目的是给其他人一个提示,他们在编译驱动程序插件时遇到了和我最近一样的问题.
This is not typically a question where to find a step-by-step guide, but rather the guide itself.
My intention with this post is to give others a hint, who have the same problems in compiling the driver-plugin as I just had recently.
推荐答案
如何使用 Windows/MinGW 平台为 SQLite-DB 和 SQLCipher-extension 构建 Qt-SQL-driver-plugin 'QSQLCIPHER':
适用于 Windows/MinGW 的 Qt 5.4.0
Qt 5.4.0 for Windows/MinGW
- 下载 Qt
- 安装包括源代码,例如
C:QtQt5.4.0
Windows 版 OpenSSL
OpenSSL for Windows
- 下载 Win32 OpenSSL v1.0.2a
- 下载 Visual C++ 2008 Redistributable
- 通过执行vcredist_x86.exe"安装 Visual C++ 2008 Redistributable
- 通过执行Win32OpenSSL-1_0_2.exe"安装 OpenSSL v1.0.2a
- 目标目录,例如
C:OpenSSL-Win32
- 在安装过程中,选择将库安装到 Windows 系统目录 (
C:WindowsSysWOW64
) 的选项
MinGW - 适用于 Windows 的极简主义 GNU
MinGW - Minimalist GNU for Windows
- 下载并安装mingw-get-setup.exe"
- MinGW 安装程序的启动
- 安装MSYS基础系统
- 选择:所有包 -> MSYS -> MSYS 基础系统
- 选择 msys-base (Class 'bin') 进行安装
- 菜单:安装 -> 应用更改
- 默认安装文件到目录
C:MinGW
- 选择:所有包 -> MinGW -> MinGW 贡献
- 选择mingw32-tcl"和mingw32-tk"(类bin")进行安装
- 菜单:安装 -> 应用更改
- 默认安装文件到目录
C:MinGW
在
C:QtQt5.4.0Toolsmingw491_32msys1.0etc
插入内容如下:
Insert content as follows:
#Win32_Path Mount_Point C:/Qt/Qt5.4.0/Tools/mingw491_32 /mingw C:/Qt/Qt5.4.0/5.4 /qt C:/ /c
- 下载 zlib-dll-二进制文件
- 解压并复制文件 'zlib1.dll' 到 Qt-MinGW 目录
C:QtQt5.4.0Toolsmingw491_32msys1.0in
- 下载 SQLCipher 压缩文件
- 提取 zip 文件,例如
C: empsqlcipher-master
- 复制 OpenSSL-Win32-libraries
- 将
C:OpenSSL-Win32inlibeay32.dll
复制到C: empsqlcipher-master
- 将
C:OpenSSL-Win32liblibeay32.lib
复制到C: empsqlcipher-master
- Download the SQLCipher-zip-file
- Extract the zip-file e.g. to
C: empsqlcipher-master
- Copy OpenSSL-Win32-libraries
- Copy
C:OpenSSL-Win32inlibeay32.dll
toC: empsqlcipher-master
- Copy
C:OpenSSL-Win32liblibeay32.lib
toC: empsqlcipher-master
构建 SQLCipher.exe
Build SQLCipher.exe
执行 MSYS:
C:QtQt5.4.0Toolsmingw491_32msys1.0msys.bat
$ cd /c/temp/sqlcipher-master $ ./configure --prefix=$(pwd)/dist --with-crypto-lib=none --disable-tcl CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_CRYPTO_OPENSSL -I/c/openssl-win32/include /c/temp/sqlcipher-master/libeay32.dll -L/c/temp/sqlcipher-master/ -static-libgcc" LDFLAGS="-leay32" $ make clean $ make sqlite3.c $ make $ make dll $ make install
- Copy
- 将
C: empsqlcipher-masterdistinsqlcipher.exe
复制到C:sqlcipher
.
文件sqlcipher.exe"是与非加密原始命令行界面sqlite3.exe"的加密等效项. - 将
C: empsqlcipher-mastersqlite3.dll
复制到C:sqlcipher
.
该文件是加密扩展的 SQLite 库. - 创建目录:
C:QtQt5.4.05.4Srcqtbasesrcpluginssqldriverssqlcipher
在新目录中创建以下三个文件:
- Create directory:
C:QtQt5.4.05.4Srcqtbasesrcpluginssqldriverssqlcipher
Create the following three files within the new directory:
文件 1:smain.cpp:
File 1: smain.cpp:
保存可执行的 SQLite/SQLCipher 数据库,例如
C:sqlcipher
Save the executable SQLite/SQLCipher-database e.g. to
C:sqlcipher
构建 Qt-QSQLCIPHER-driver-plugin
Build Qt-QSQLCIPHER-driver-plugin
#include <qsqldriverplugin.h> #include <qstringlist.h> #include "../../../../src/sql/drivers/sqlite/qsql_sqlite_p.h" // There was a missing " at the end of this line 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 &); }; 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"
- 将
文件 2:sqlcipher.pro
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)
文件 3:sqlcipher.json
File 3: sqlcipher.json
{ "Keys": [ "QSQLCIPHER" ] }
zlib 库
SQLCipher
自定义文件
C:QtQt5.4.05.4Srcqtbasesrcsqldriverssqlcipherqsql_sqlite.pri
文件内容如下:Customize file
C:QtQt5.4.05.4Srcqtbasesrcsqldriverssqlcipherqsql_sqlite.pri
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 path of sqlite.pri to sqlcipher.pri here ! } else { LIBS += $$QT_LFLAGS_SQLITE QMAKE_CXXFLAGS *= $$QT_CFLAGS_SQLITE }
- 安装MSYS基础系统
- 此目录中的其余两个文件无需更改.
在目录
C:QtQt5.4.05.4Srcqtbasesrc3rdparty
中创建文件'sqlcipher.pri',内容如下:- The remaining two files in this directory need not to be changed.
Create file 'sqlcipher.pri' in directory
C:QtQt5.4.05.4Srcqtbasesrc3rdparty
with following content: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 !contains(CONFIG, largefile):DEFINES += SQLITE_DISABLE_LFS contains(QT_CONFIG, posix_fallocate):DEFINES += HAVE_POSIX_FALLOCATE=1 winrt: DEFINES += SQLITE_OS_WINRT winphone: DEFINES += SQLITE_WIN32_FILEMAPPING_API=1 qnx: DEFINES += _QNX_SOURCE INCLUDEPATH += $$PWD/sqlcipher c:/openssl-win32/include SOURCES += $$PWD/sqlcipher/sqlite3.c LIBS += -L$$PWD/sqlcipher/lib -lsqlcipher -leay32 -lsqlite3 TR_EXCLUDE += $$PWD/*
创建并填充
C:QtQt5.4.05.4Srcqtbasesrc3rdpartysqlcipher
创建两个目录:
Create the two directories:
C:QtQt5.4.05.4Srcqtbasesrc3rdpartysqlcipher C:QtQt5.4.05.4Srcqtbasesrc3rdpartysqlcipherlib
将以下文件复制到
C:QtQt5.4.05.4Srcqtbasesrc3rdpartysqlcipher
:C: empsqlcipher-mastershell.c C: empsqlcipher-mastersqlite3.c C: empsqlcipher-mastersqlite3.h C: empsqlcipher-mastersqlite3ext.h
将以下文件/目录复制到
C:QtQt5.4.05.4Srcqtbasesrc3rdpartysqlcipherlib
:C: empsqlcipher-masterdistlib C: empsqlcipher-mastersqlite3.dll C:OpenSSL-Win32inlibeay32.dll
该目录现在包含以下文件和目录:
The directory now consists of the following files and directories:
C:QTQT5.4.05.4SRCQTBASESRC3RDPARTYSQLCIPHER | shell.c | sqlite3.c | sqlite3.h | sqlite3ext.h | ---lib | libeay32.dll | libsqlcipher.a | libsqlcipher.la | sqlite3.dll | ---pkgconfig sqlcipher.pc
- 打开Qt命令行
C:WindowsSystem32cmd.exe/A/Q/KC:QtQt5.4.05.4mingw491_32inqtenv2.bat
莉> 执行以下命令:
- Open Qt-command line
C:WindowsSystem32cmd.exe /A /Q /K C:QtQt5.4.05.4mingw491_32inqtenv2.bat
Execute the following commands:
为 Qt 编译 QSQLCIPHER-driver-plugin:
Compile the QSQLCIPHER-driver-plugin for Qt:
cd C:QtQt5.4.05.4Srcqtbasesrcpluinssqldriverssqlcipher qmake mingw32-make
- 目标目录,例如
这会在以下目录中构建 QSQLCIPHER-driver-plugin:
This builds the QSQLCIPHER-driver-plugin within the following directory:
C:QTQT5.4.05.4SRCQTBASEPLUGINSSQLDRIVERS libqsqlcipher.a libqsqlcipherd.a qsqlcipher.dll qsqlcipherd.dll
- 将qsqlcipher.dll"和qsqlcipherd.dll"复制到SQL-driver-plugin-directory
C:QtQt5.4.05.4mingw491_32pluginssqldrivers
.莉>创建一个新的加密 SQLite/SQLCipher 数据库
Create a new encrypted SQLite/SQLCipher-database
使用测试表和一些测试数据创建新的 SQLite-Plaintext-database 'plaintext.db'
Create new SQLite-Plaintext-database 'plaintext.db' with a test table and some test data
将目录更改为
C:sqlcipher
,其中包含sqlcipher.exe"和sqlite3.dll"(见上文).
Change directory to
C:sqlcipher
, which contains 'sqlcipher.exe' and 'sqlite3.dll' (see above).
C:sqlcipher>sqlcpher.exe plaintext.db SQLCipher version 3.8.6 2014-08-15 11:46:33 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> create table testtable (id integer, name text); sqlite> insert into testtable (id,name) values(1,'Bob'); sqlite> insert into testtable (id,name) values(2,'Charlie'); sqlite> insert into testtable (id,name) values(3,'Daphne'); sqlite> select * from testtable; 1|Bob 2|Charlie 3|Daphne sqlite> .exit
加密明文数据库
这将使用密钥testkey"创建数据库 C:sqlcipherencrypted.db
.
C:sqlcipher>sqlcipher.exe plaintext.db
SQLCipher version 3.8.6 2014-08-15 11:46:33
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'testkey';
sqlite> SELECT sqlcipher_export('encrypted');
sqlite> DETACH DATABASE encrypted;
sqlite> .exit
C:sqlcipherencrypted.db
:数据现已加密.
https://www.zetetic.net/sqlcipher/sqlcipher-api/莉>
使用 SQLite 数据库和 SQLCipher 扩展并通过 Qt 访问
Usage of the SQLite-database with SQLCipher-extension and access via Qt
- 创建一个新的 Qt 命令行项目,例如'qsqlcipher'
项目文件
- Create a new Qt-command-line-project e.g. 'qsqlcipher'
Project file
QT += core sql
QT -= gui
TARGET = qsqlcipher
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
测试程序'main.cpp'
Test-program 'main.cpp'
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>
#include <QString>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
qDebug() << QSqlDatabase::drivers();
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLCIPHER");
db.setDatabaseName("C:/sqlcipher/encrypted.db");
db.open();
QSqlQuery q;
q.exec("PRAGMA key = 'testkey';");
q.exec("insert into testtable (id,name) values(4,'dummy')");
q.exec("SELECT id,name anz FROM testtable");
while (q.next()) {
QString id = q.value(0).toString();
QString name = q.value(1).toString();
qDebug() << "id=" << id << ", name=" << name;
}
db.close();
return 0;
}
编译执行
Compile and execute
("QSQLCIPHER", "QSQLITE", "QMYSQL", "QMYSQL3", "QODBC", "QODBC3", "QPSQL", "QPSQL7")
id= "1" , name= "Bob"
id= "2" , name= "Charlie"
id= "3" , name= "Daphne"
id= "4" , name= "dummy"
在交付 Qt 程序时,不要忘记 Qt 库、平台库、SQL 驱动程序插件qsqlcipher.dll"和 OpenSSL 库libeay32.dll".
上面测试程序的例子:
When delivering a Qt-program do not forget the Qt-libraries, the platforms-libraries, SQL-driver-plugin 'qsqlcipher.dll' and the OpenSSL-library 'libeay32.dll'.
Example for the test program above:
C:TEMPQSQLCIPHER-TEST
| icudt53.dll
| icuin53.dll
| icuuc53.dll
| libeay32.dll
| libgcc_s_dw2-1.dll
| libstdc++-6.dll
| libwinpthread-1.dll
| qsqlcipher.exe
| Qt5Core.dll
| Qt5Sql.dll
|
+---platforms
| qminimal.dll
| qoffscreen.dll
| qwindows.dll
|
---sqldrivers
qsqlcipher.dll
注意:测试程序包含密钥:
Caution: The test program contains the key:
...
q.exec("PRAGMA key = 'testkey';");
...
测试程序的二进制文件中的这个关键字符串可以使用十六进制编辑器轻松读取,在我看来,这缺乏安全性:
This key string in the binary file of the test program can easiliy be read using a hex-editor, which is, to my opinion, a lack in security:
...
00002C90 70 68 65 72 2F 65 6E 63 72 79 70 74 65 64 2E 64 pher/encrypted.d
00002CA0 62 00 50 52 41 47 4D 41 20 6B 65 79 20 3D 20 27 b.PRAGMA key = '
00002CB0 74 65 73 74 6B 65 79 27 3B 00 00 00 69 6E 73 65 testkey';...inse
00002CC0 72 74 20 69 6E 74 6F 20 74 65 73 74 74 61 62 6C rt into testtabl
...
有关如何解决此问题的方法,请咨询您自己选择的搜索引擎.;-)
例如.搜索:在可执行文件中隐藏字符串
For approaches how to solve this problem, ask the search engine of your own choice. ;-)
E.g. search for: hide string in executable
相关文章