【问题标题】:How to build the Qt-SQL-driver-plugin 'QSQLCIPHER' for SQLite-DB with SQLCipher-extension using the Windows/MinGW-platform?如何使用 Windows/MinGW 平台使用 SQLCipher-extension 为 SQLite-DB 构建 Qt-SQL-driver-plugin 'QSQLCIPHER'?
【发布时间】:2015-05-25 14:34:12
【问题描述】:

这通常不是在哪里可以找到分步指南的问题,而是指南本身。
我写这篇文章的目的是给其他人一个提示,他们在编译驱动程序插件时遇到了和我最近一样的问题。

如何使用 Windows/MinGW 平台为带有 SQLCipher-extension 的 SQLite-DB 构建 Qt-SQL-driver-plugin 'QSQLCIPHER'?

【问题讨论】:

  • 必须遵循 StackOverflow 的 Question & Answer 格式。我建议您将答案作为实际答案发布在您的问题下,并将问题简化为实际问题(您需要稍等片刻)。如果您将遇到的一些问题添加到问题中会更好,以便清楚地表明您已尝试解决问题(我知道您解决了问题,但问题必须独立存在。他们即使您已经有了答案,也不能依赖潜在的答案。)另请参阅:meta.stackexchange.com/questions/17463
  • 如果您在步骤 5 中遇到问题,gawk 抱怨“反斜杠不是最后一个字符”,那么请在两个 makeopcode?.awk 文件中将您的行编辑修复为 unix 格式。
  • 教程内容非常丰富,但是,按照您设置的所有步骤后,我停在这里:D:\Qt\5.5.1\5.5\src\qtbase\src\plugins\sqldrivers\sqlcipher>mingw32-make mingw32-make -f Makefile.Release all mingw32-make[1]: Entering directory 'D:/Qt/5.5.1/5.5/src/qtbase/src/plugins/sqldrivers/sqlcipher' mingw32-make[1]: *** No rule to make target 'release/smain.moc', needed by 'release/smain.o'. Stop. mingw32-make[1]: Leaving directory 'D:/Qt/5.5.1/5.5/src/qtbase/src/plugins/sqldrivers/sqlcipher' makefile:38: recipe for target 'release-all' failed mingw32-make: *** [release-all] Error 2
  • 驱动程序是在 Windows 7 下构建的,在 Windows 8.1 下也可以运行。但我没有使用其他 Windows 版本的经验。 @rrrfusco:或者您是在询问其他操作系统,例如 Linux?这行不通。
  • @rrrfusco:对不起,我不能直接评论你的问题。我在 Windows 7(64 位)上构建了驱动程序,该驱动程序也在 Windows 8.1(64 位)上运行。但我没有 32 位 Windows 的经验。你的 XP 和 Win8 是 32 位系统吗?我将尝试获得一个 32 位系统来测试 mydriver 并得到答案。

标签: qt sqlite encryption mingw sqlcipher


【解决方案1】:

如何使用 Windows/MinGW 平台为带有 SQLCipher-extension 的 SQLite-DB 构建 Qt-SQL-driver-plugin 'QSQLCIPHER':

  1. Qt 5.4.0 for Windows/MinGW

    • 下载Qt
    • 安装包括源代码,例如C:\Qt\Qt5.4.0
  2. 适用于 Windows 的 OpenSSL

    • 下载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:\Windows\SysWOW64) 的选项
  3. MinGW - 适用于 Windows 的极简 GNU

    • 下载并安装“mingw-get-setup.exe”
    • MinGW 安装程序的启动
      • 安装 MSYS 基础系统
        • 选择:所有包 -> MSYS -> MSYS 基础系统
        • 选择 msys-base (Class 'bin') 进行安装
        • 菜单:安装 -> 应用更改
        • 默认安装文件到目录C:\MinGW
      • 安装 Tcl/Tk
        • 选择:所有包 -> MinGW -> MinGW 贡献
        • 选择“mingw32-tcl”和“mingw32-tk”(类“bin”)进行安装
        • 菜单:安装 -> 应用更改
        • 默认安装文件到目录C:\MinGW
    • C:\MinGW的内容复制到Qt-MinGW-目录C:\Qt\Qt5.4.0\Tools\mingw491_32
    • C:\Qt\Qt5.4.0\Tools\mingw491_32\msys\1.0\etc中创建文件'fstab'

      • 插入内容如下:

        #Win32_Path                        Mount_Point
        C:/Qt/Qt5.4.0/Tools/mingw491_32    /mingw
        C:/Qt/Qt5.4.0/5.4                  /qt
        C:/                                /c
        
  4. zlib 库

    • 下载 zlib-dll-Binaries
    • 解压并复制文件'zlib1.dll'到Qt-MinGW目录C:\Qt\Qt5.4.0\Tools\mingw491_32\msys\1.0\bin
  5. SQL密码

    • 下载 SQLCipher-zip 文件
    • 解压 zip 文件,例如到C:\temp\sqlcipher-master
    • 复制 OpenSSL-Win32 库
      • 复制C:\OpenSSL-Win32\bin\libeay32.dllC:\temp\sqlcipher-master
      • 复制C:\OpenSSL-Win32\lib\libeay32.libC:\temp\sqlcipher-master
    • 构建 SQLCipher.exe

      • 执行 MSYS:C:\Qt\Qt5.4.0\Tools\mingw491_32\msys\1.0\msys.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
        
    • 保存可执行的 SQLite/SQLCipher-database 例如给C:\sqlcipher

      • C:\temp\sqlcipher-master\dist\bin\sqlcipher.exe复制到C:\sqlcipher
        文件“sqlcipher.exe”是加密等价于非加密原始命令行界面“sqlite3.exe”。
      • C:\temp\sqlcipher-master\sqlite3.dll复制到C:\sqlcipher
        该文件是经过加密扩展的 SQLite 库。
    • 带有 SQLCipher-extension 的 SQLite 数据库现已准备就绪。
  6. 构建 Qt-QSQLCIPHER-driver-plugin

    • 创建目录:
      C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\plugins\sqldrivers\sqlcipher
    • 在新目录中创建以下三个文件:

      • 文件1:smain.cpp:

        #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

        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

        {
            "Keys": [ "QSQLCIPHER" ]
        }
        
    • 复制目录C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\sql\drivers\sqliteC:\Qt\Qt5.4.0\5.4\Src\qtbase\src\sql\drivers\sqlcipher
    • 自定义文件C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\sql\drivers\sqlcipher\qsql_sqlite.pri
      文件内容如下:

      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
      }
      
    • 此目录中剩余的两个文件无需更改。
    • 在目录C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\3rdparty 中创建文件'sqlcipher.pri',内容如下:

      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:\Qt\Qt5.4.0\5.4\Src\qtbase\src\3rdparty\sqlcipher

      • 创建两个目录:

        C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\3rdparty\sqlcipher
        C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\3rdparty\sqlcipher\lib
        
      • 将以下文件复制到C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\3rdparty\sqlcipher:

        C:\temp\sqlcipher-master\shell.c
        C:\temp\sqlcipher-master\sqlite3.c
        C:\temp\sqlcipher-master\sqlite3.h
        C:\temp\sqlcipher-master\sqlite3ext.h
        
      • 将以下文件/目录复制到C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\3rdparty\sqlcipher\lib

        C:\temp\sqlcipher-master\dist\lib
        C:\temp\sqlcipher-master\sqlite3.dll
        C:\OpenSSL-Win32\bin\libeay32.dll
        
      • 该目录现在包含以下文件和目录:

        C:\QT\QT5.4.0\5.4\SRC\QTBASE\SRC\3RDPARTY\SQLCIPHER
        |   shell.c
        |   sqlite3.c
        |   sqlite3.h
        |   sqlite3ext.h
        |
        \---lib
            |   libeay32.dll
            |   libsqlcipher.a
            |   libsqlcipher.la
            |   sqlite3.dll
            |
            \---pkgconfig
                    sqlcipher.pc
        
    • 为 Qt 编译 QSQLCIPHER-driver-plugin:

      • 打开Qt-命令行C:\Windows\System32\cmd.exe /A /Q /K C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\qtenv2.bat
      • 执行以下命令:

        cd C:\Qt\Qt5.4.0\5.4\Src\qtbase\src\pluins\sqldrivers\sqlcipher
        qmake
        mingw32-make
        
      • 这会在以下目录中构建 QSQLCIPHER-driver-plugin:

        C:\QT\QT5.4.0\5.4\SRC\QTBASE\PLUGINS\SQLDRIVERS
            libqsqlcipher.a
            libqsqlcipherd.a
            qsqlcipher.dll
            qsqlcipherd.dll
        
      • 将“qsqlcipher.dll”和“qsqlcipherd.dll”复制到 SQL-driver-plugin-directory C:\Qt\Qt5.4.0\5.4\mingw491_32\plugins\sqldrivers
  7. 创建一个新的加密 SQLite/SQLCipher 数据库

    • 使用测试表和一些测试数据创建新的 SQLite-Plaintext-database 'plaintext.db'

      • 将目录更改为C:\sqlcipher,其中包含“sqlcipher.exe”和“sqlite3.dll”(见上文)。

        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
        
    • 使用标准文本编辑器打开C:\sqlcipher\plaintext.db
      数据库方案和测试数据可以明文读取。
    • 加密明文数据库
      这将使用密钥“testkey”创建数据库C:\sqlcipher\encrypted.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:\sqlcipher\encrypted.db
      数据现已加密。
    • 如需更多有用信息,请访问:
      https://www.zetetic.net/sqlcipher/sqlcipher-api/
  8. 使用带有 SQLCipher 扩展的 SQLite 数据库并通过 Qt 访问

    • 创建一个新的 Qt 命令行项目,例如'qsqlcipher'
    • 项目文件

      QT       += core sql
      QT       -= gui
      TARGET = qsqlcipher
      CONFIG   += console
      CONFIG   -= app_bundle
      TEMPLATE = app
      SOURCES += main.cpp
      
    • 测试程序'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;
      }
      
    • 编译并执行

      ("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”。
      上面的测试程序示例:

      C:\TEMP\QSQLCIPHER-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
      
    • 注意:测试程序包含密钥:

      ...
      q.exec("PRAGMA key = 'testkey';");
      ...
      

      测试程序的二进制文件中的这个密钥字符串可以使用十六进制编辑器轻松读取,在我看来,这是缺乏安全性:

      ...
      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
      ...
      

      有关如何解决此问题的方法,请询问您自己选择的搜索引擎。 ;-)
      例如。搜索:隐藏可执行文件中的字符串

【讨论】:

  • 酷!顺便说一句:不要硬编码密钥,即时生成它。
  • 你好,我想在 qt 5.9 及更高版本中完成这项工作。我该怎么做?因为结构在 qt 新版本中发生了变化。非常感谢您的帮助。
  • @Ahmad 您是否成功构建了 qsqlcipher.dll。您能提供要遵循的步骤吗?
  • @Veera 是的,最后我成功地构建了它并构建了 Qt 插件以在 qt 中使用它。我怎样才能为您发送一些信息?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
  • 2014-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多