针对 qt的sqlite加密数据库sqlitecipher插件QtCipherSqlitePlugin

news2024/11/25 20:17:41

💂 个人主页:pp不会算法^ v ^
🤟 版权: 本文由【pp不会算法v】原创、在CSDN首发、需要转载请联系博主
💬 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦

文章目录

  • 简介
  • 编译安装
  • 使用
  • 可视化工具查看
  • 完结

简介

在客户端存储数据的时候很多情况都会使用sqlite,像微信这种主流软件在客户端储存数据也用到了sqlite,
但是普通的sqlite是没有加密的也就是说别人可以直接打开那个.db文件查看存储的内容,

针对数据安全,有两种方案:
一种就是将写入的数据加密,这样就算别人打开也是加密后的内容
另一种就是对数据库本身加密,sqlite官方提供也一个加密版本但是那是商业收费的
但是还是有两款开源的基于sqlite的加密数据库sqlitecipher和wxsqlite
wxsqlite3是基于sqlitecipher的,

我下面介绍的这个qt插件就是基于wxsqlite的
在这里插入图片描述

编译安装

github链接:https://github.com/devbean/QtCipherSqlitePlugin.git
不要用gitee上那个镜像,那个稍微有点问题(别问为什么我用过出了问题)

把代码拉取下来之后直接打开pro文件用mingw编译,编译完之后在生成目录下的
plugins/sqldrivers/这个目录下生成如下图的三个库文件
在这里插入图片描述
然后将下面这两个文件复制导对对应编译器的:D:\ITSoftWare\QT5.15.2\Qtbase\5.15.2\mingw81_64\plugins\sqldrivers(以我的为例我是用mingw81_64编译的,release和debug模式编译的都一样)中
在这里插入图片描述
然后把下面这个.a文件放到对应编译器目录的lib目录下:D:\ITSoftWare\QT5.15.2\Qtbase\5.15.2\mingw81_64\lib(以我的为例)
在这里插入图片描述

使用

输出QSqlDatabase::drivers()看一看时候包含了 SQLITECIPHER,如果包含了那么证明安装成功了
使用和qt的sqlite模块基本一致,
只要在初始化数据库的时候添加一下密码就行了,
db_ = QSqlDatabase::addDatabase(“SQLITECIPHER”, connectionName_);
db_.setPassword(“123698745”);

示例代码:

#include <QtSql>
#include <QCoreApplication>
#include <QTemporaryDir>

#ifndef QT_DEBUG
#error Must be built in debug mode!
#endif

#ifdef Q_OS_IOS
#  include <QtPlugin>

Q_IMPORT_PLUGIN(SqliteCipherDriverPlugin)
#endif

#define CONNECTION_FAILED -1

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    Q_UNUSED(app)

    qDebug() << QSqlDatabase::drivers();

    Q_ASSERT(QSqlDatabase::isDriverAvailable("QSQLITE")); // from Qt
    Q_ASSERT(QSqlDatabase::isDriverAvailable("SQLITECIPHER")); // from our plugin

    QTemporaryDir tmp;
    Q_ASSERT(tmp.isValid());

    auto withDB = [&](const char *driver, auto fn) {
        QString path = QDir(tmp.path()).absoluteFilePath(QString(driver) + ".db");
        {
            QSqlDatabase db = QSqlDatabase::addDatabase(driver, "db");
            db.setDatabaseName(path);
            Q_ASSERT(db.open());
            fn(db);
        }
        QSqlDatabase::removeDatabase("db");
    };

//    // QSQLITE
//    {
//        // Create a SQLite db
//        withDB("QSQLITE", [](auto db) {
//            db.exec("create table foo (bar integer)");
//            db.exec("insert into foo values (42)");
//        });

//        // Check that we can read from the SQLite db
//        withDB("QSQLITE", [](auto db) {
//            QSqlQuery q = db.exec("select bar from foo");
//            Q_ASSERT(q.next());
//            Q_ASSERT(q.value(0).toInt() == 42);
//        });

//        // Check that SQLite is not SQLCipher
//        withDB("QSQLITE", [](auto db) {
//            QSqlQuery q = db.exec("select sqlcipher_export()");
//            QString errmsg = q.lastError().databaseText();
//            Q_ASSERT(errmsg.startsWith("no such function"));
//        });
//    }

//    // SQLITECIPHER
//    {
//        // Check that SQLiteCipher is not SQLite
//        withDB("SQLITECIPHER", [](auto db) {
//            QSqlQuery q = db.exec("select sqlcipher_export()");
//            QString errmsg = q.lastError().databaseText();
//            qDebug() << errmsg;
//            Q_ASSERT(errmsg.startsWith("wrong number of arguments"));
//        });

//        // Create a SQLiteCipher db with a passphrase
//        withDB("SQLITECIPHER", [](auto db) {
//            db.exec("pragma key='foobar'");
//            db.exec("create table foo (bar integer)");
//            db.exec("insert into foo values (42)");
//        });

//        // Check that we can't read from the SQLiteCipher db without the passphrase
//        withDB("SQLITECIPHER", [](auto db) {
//            QSqlQuery q = db.exec("select bar from foo");
//            Q_ASSERT(!q.next());
//        });

//        // Check that we can read from the SQLiteCipher db with the passphrase
//        withDB("SQLITECIPHER", [](auto db) {
//            db.exec("pragma key='foobar'");
//            QSqlQuery q = db.exec("select bar from foo");
//            Q_ASSERT(q.next());
//            Q_ASSERT(q.value(0).toInt() == 42);
//        });
//    }

    QString dir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
//    QString DB_FILE_PATH = dir + "/test_chacha20.db";
    QString DB_FILE_PATH = dir + "/local.db";
    qDebug() << "DB File Path is:" << DB_FILE_PATH;

    QSqlDatabase dbconn = QSqlDatabase::addDatabase("SQLITECIPHER");
    dbconn.setDatabaseName(DB_FILE_PATH); //localDB.db is already existing before running the application
    dbconn.setPassword("pass");
    dbconn.setConnectOptions("QSQLITE_USE_CIPHER=sqlcipher; SQLCIPHER_LEGACY=1; SQLCIPHER_LEGACY_PAGE_SIZE=4096; QSQLITE_CREATE_KEY");

    bool open = dbconn.open();
    qDebug() << "open: " << open;
    qDebug() << "isOpen(): " << dbconn.isOpen() << dbconn.isOpenError();
    qDebug() << "create_key: " << dbconn.lastError();

    if (!dbconn.isOpen())
    {
        qDebug() << "Connection failed: " << dbconn.lastError().driverText();
        exit(CONNECTION_FAILED);
    }

    QSqlQuery query;
//    query.exec("create table test (id int, name varchar)");
//    query.exec("insert into test values (1, 'AAA')");
//    query.exec("insert into test values (2, 'BBB')");
//    query.exec("insert into test values (3, 'CCC')");
//    query.exec("insert into test values (4, 'DDD')");
//    query.exec("insert into test values (5, 'EEE')");
//    query.exec("insert into test values (6, 'FFF')");
//    query.exec("insert into test values (7, 'GGG')");
//    query.exec("select * from test where name regexp '(a|A)$'");
//    if (query.next()) {
//        qDebug() << "Regexp result: " << query.value(0).toInt() << ": " << query.value(1).toString();
//    } else {
//        qDebug() << "This plugin does not support regexp.";
//    }
//    qDebug() << "----------" << endl;
    query.exec("select id, name from test");
    while (query.next()) {
        qDebug() << query.value(0).toInt() << ": " << query.value(1).toString();
    }
//    qDebug() << "----------" << endl;
//    query.exec("update mapping set name='ZZZ' where id=1");
//    query.exec("select id, name from mapping");
//    while (query.next()) {
//        qDebug() << query.value(0).toInt() << ": " << query.value(1).toString();
//    }
//    qDebug() << "----------" << endl;
//    query.exec("delete from mapping where id=4");
//    query.exec("select id, name from mapping");
//    while (query.next()) {
//        qDebug() << query.value(0).toInt() << ": " << query.value(1).toString();
//    }
//    query.exec("drop table mapping");
    dbconn.close();

    return 0;
}

可视化工具查看

由于数据库被加密了使用一般的数据库可视化工具例如Navicat查看不了,这里我们可以下载sqlitestudio这款工具,也是qt写的,安装好了之打开上述示例代码创建的数据库
在这里插入图片描述

完结

如果你觉得对你有帮助,那麻烦三连一下吧

qt/c++技术交流q群:287590944

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1561431.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【docker】基础操作命令

docker run:干两步&#xff0c;本地找一下有没有集装箱&#xff0c;有运行&#xff0c;没有远程仓库下载运行。还没有报错。 docker好处&#xff1a; 不需要进行物理层模拟&#xff0c;不需要hypervisor利用的内核是宿主机的内核&#xff0c;不需要重新加载Linux内核 镜像相关…

QT-飞机水平仪图标

QT-飞机水平仪图标 一、演示效果二、关键程序三、下载链接 一、演示效果 二、关键程序 #include <stdio.h> #include <stdlib.h> #include <string.h>#include <QtCore> #include <QtGui> #include <QDebug> #include <QTableWidget&g…

刷题之动态规划-路径问题

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;开始刷动态规划的题目了&#xff0c;要特别注意初始化的时候给什么值。 动态规划5个步骤 状态表示 &#xff1a;dp数组中每一个下标对应值的含义是什么->dp[i]表示什么状态转移方程&#xff1a; dp[i] 等于什么1 和 2 是…

python毕业设计django宠物寄存系统fn62p

本文所设计的宠物寄存中心系统的设计与实现拥有前端和后端&#xff0c;前端使用Vue.js框架和创建&#xff0c;后端使用django框架创建&#xff0c;开发语言采用python&#xff0c;使用Mysql数据库对后台数据进行存储。将pcyahrm作为主要的开发工具。接着进行系统的需求分析、功…

surfer绘制等值线图

surfer介绍 Surfer软件&#xff0c;是美国Golden Software公司编制的一款以画三维图的软件。该软件具有强大的插值功能和绘制图件能力&#xff0c;可用来处理XYZ数据&#xff0c;是地质工作者常用的专业成图软件&#xff08;来源于百度百科&#xff09;。 surfer可以用来绘制…

Linux文件与进程交互的窥探者lsof

lsof 是一个 Linux 和 UNIX 系统中的实用工具,用于列出系统中打开文件的所有信息。这个名字代表 “List Open Files”,但它也可以显示进程相关的其他信息,如: 打开的文件描述符列表 打开网络连接的列表 被进程使用的信号和内核对象等 在Linux系统中,有一个经典的概念: …

NOSQL - Redis的简介、安装、配置和简单操作

目录 一. 知识了解 1. 关系型数据库与非关系型数据库 1.1 关系型数据库 1.2 非关系型数据库 1.3 区别 1.4 非关系型数据库产生背景 1.5 NOSQL 与 SQL的数据记录对比 2. 缓存相关知识 2.1 缓存概念 2.2 系统缓存 2.3 缓存保存位置及分层结构 二 . redis 相关知识 1.…

【MySQL】13. 索引(重点)

1. 没有索引&#xff0c;可能会有什么问题 索引&#xff1a;提高数据库的性能&#xff0c;索引是物美价廉的东西了。 不用加内存&#xff0c;不用改程序&#xff0c;不用调sql&#xff0c;只要执行正确的 create index &#xff0c;查询速度就可能提高成百上千倍。 但是天下没…

如何提高小红书笔记的收录率?

在小红书平台上&#xff0c;笔记的收录率是衡量一篇笔记是否受欢迎和有价值的重要因素。为了提高笔记的收录率&#xff0c;有几个关键点需要注意&#xff1a; 1.内容不涉及广告 在发布笔记前要先确保笔记内容不包含任何形式的广告或推广信息。小红书平台对于广告性质的内容有…

关于 HEAP CORRUPTION DETECTED:after Normal block 错误的原因及解析

目录 一、HEAP CORRUPTION DETECTED:after Normal block 出现的报错情况&#xff1a; 二、问题原因&#xff08;重要&#xff09;&#xff1a; 三、举例 1.错误代码如下&#xff1a; 2.错误原因及分析&#xff08;重要&#xff09;&#xff1a; 3.解决方法 ​编辑 4.正…

OMP压缩感知仿真(MATLAB)

clc; clearvars; close all;% 读文件 Ximread(mandrill256.bmp); tic; Xdouble(X); [m,n]size(X);% % 小波变换矩阵生成 [LL1, LH1, HL1, HH1] dwt2(X, haar); [LL2, LH2, HL2, HH2] dwt2(LL1, haar); % [LL3, LH3, HL3, HH3] dwt2(LL2, haar); % [LL4, LH4, HL4, HH4] d…

Demis Hassabis,这位被封为爵士的AI领域的杰出研究者和神经科学家,是否能成为Google的救星?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Jquery——js库

1. jQuery 基础操作 jQuery 是一个快速、小巧的 JavaScript 库&#xff0c;设计用于简化 HTML 文档的遍历、事件处理、动画设计和 Ajax 交互。jQuery 使用户能够更快地编写 JavaScript 代码&#xff0c;并且能够更容易地处理 HTML 文档、事件、动画和 Ajax。 加载 jQuery 要…

HDLbits 刷题 -- Alwaysblock2

学习&#xff1a; For hardware synthesis, there are two types of always blocks that are relevant: Combinational: always (*)Clocked: always (posedge clk) Clocked always blocks create a blob of combinational logic just like combinational always blocks, but…

【DETR系列目标检测算法代码精讲】01 DETR算法03 Dataloader代码精讲

与一般的Dataloader的区别在于我们对图像进行了随机裁剪&#xff0c;需要进行额外的操作才能将其打包到dataloader里面 这一段的代码如下&#xff1a; if args.distributed:sampler_train DistributedSampler(dataset_train)sampler_val DistributedSampler(dataset_val, shu…

LeetCode-48. 旋转图像【数组 数学 矩阵】

LeetCode-48. 旋转图像【数组 数学 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;一行代码&#xff01;Python zip函数图一乐【zip函数实现主对角线翻转&#xff0c;[::-1]实现垂直翻转】解题思路二&#xff1a;其实我们也可以先水平轴翻转&#xff0c;让后主对角线翻转。…

Linux之用户账号、用户组和与账号有关的系统文件

目录 一、基本介绍 1.用户和用户组 2.UID和GID 二、 账户管理 1.查看用户的UID和GID 2.添加账户 3.删除账号 4.修改账号 5.账户口令 三、分组管理 1.新增用户组 2.删除用户组 3.修改用户组 4.用户组切换 四、与账号有关的系统文件 1./etc/passwd 2./etc/shado…

LeetCode_33_中等_搜索旋转排序数组

文章目录 1. 题目2. 思路及代码实现详解&#xff08;Python&#xff09;2.1 二分查找 1. 题目 整数数组 n u m s nums nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c; n u m s nums nums 在预先未知的某个下标 k &#xff08; 0 < k…

python_绘图_多条折线图绘制_显示与隐藏

1. 需求 给定一个二维数组 100行, 5列, 每一列绘制一条折线, 横轴为行索引, 纵轴为对应位置的值, 绘制在一个子图里面, 使用python plot, 使用随机颜色进行区别添加显示和隐藏按钮, 可以对每条折线进行显示和隐藏 2. 代码 import numpy as np import matplotlib.pyplot as p…

使用Docker快速搭建Kafka

前言 今天讲下如何使用Docker快速搭建kafka。 前期准备&#xff0c;需要安装好docker、docker-compose。 一、安装Kafka 1、创建Kafka目录&#xff0c;执行如下命令。 mkdir -p /docker/kafka/ cd /docker/kafka/ 2、编写yaml文件&#xff0c;内容如下。 vim docker-com…