热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在Node.js中使用SQLCipher

经过试验,使用Electron打包之后我们实现的加密代码并没有打入.经过排查,发现是由于在Electron重新编译代码的过程中,从服务器端下载了已经官方提供的编译好的工具,并没有使

经过试验, 使用 Electron 打包之后我们实现的加密代码并没有打入. 经过排查, 发现是由于在 Electron 重新编译代码的过程中, 从服务器端下载了已经官方提供的编译好的工具, 并没有使用我们自己的工具. 因此这里需要自己对 Node-SQLite 代码做出修改. 此外, 由于尽量少的采用 dll 的原则, 因此对于 SQLCipher 我们采用了静态库链接的方式. 修改后的 Node-Sqlite3

命令行安装

网络上查到的命令安装方式:

  • 在 Windows 上执行以下命令

    npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=yourlib --verbose

  • 在 Mac 上执行以下命令

    export LDFLAGS="-L/yourlib"
    export CPPFLAGS="-I/yourlib/include -I/yourlib/include/sqlcipher -I/yourlib/include/openssl"
    export CXXFLAGS="-I/yourlib/include -I/yourlib/include/sqlcipher -I/yourlib/include/openssl"
    npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --openssl_libname=crypto --sqlite=yourlib --verbose

    这个时候, 在本机上你就已经根据你的 sqlcipher 安装好了一份加密的 sqlite3. 但是这里有个问题, 所有的库全部都是动态库!. 由于我们不想使用 dll ,因此需要对 Node-Sqlite3 进行修改. 这个修改会在会面做出详解.

    修改后执行以下命令, sqlcipher 就安装好了.

    npm install git+https://github.com/chinaofmelon/node-sqlite3.git --build-from-source --verbose

注意:

  1. 当 lib 中存在有动态库的时候, 默认会安装动态库. 但是我们需要连接静态库. 这时候删除动态库就可以了. 但是 sqlcipher 的静态库依赖于 openssl 的静态库, 因此需要将 openssl 的库也放到 yourlib 中, 并指定名称.

  2. 由于默认的 node-sqlite3 只有一个参数, 因此我对其做了修改, 增加了一个 openssl_lib 的参数适应静态编译过程.

使用 package.json 安装

但是大部分的时候, 我们都是很多开发人员共同开发. 那么一般情况下, 就是在工程中创建一个 package.json 文件, 然后开发人员在各自的环境中进行安装各个模块. 这时候上面的命令就用不了了. 我的做法是, 在 git 仓库上自建一个 npm package. 在这个 package 内部, 根据平台不同执行不同的编译命令, 以提供在不同的平台上使用.

如下:

package.json

{
...
"dependencies": {
...
"sqlite3": "git+https://github.com/chinaofmelon/node-sqlite3.git",
...
}
...
}

postinstall.js

require('shelljs/global');
var isArray = require('util').isArray;
var args;
try {
args = JSON.parse(process.env.npm_config_argv).original
} finally {
if (!isArray(args)) {
args = [];
}
}
var targetArgs = args.filter(function (arg) {
return /^--(runtime|target)/.test(arg);
})
var targetStr = targetArgs.reduce(function (m, arg) {
return m + ' ' + arg;
}, '');
if (process.platform == 'win32') {
// WINDOWS
exec("cd node_modules\\sqlite3 && npm install --build-from-source");
} else if (process.platform === 'darwin') {
// MAC
exec("cd node_modules/sqlite3 && npm install --build-from-source");
} else {
// linux
console.warn("[AKSQLiteCipher] Do not support linux OS yet");
exit(1);
}

至此, 执行 npm install, SQLCipher 就已经安装好了.

使用 js 代码进行测试:

// node test-sqlcipher-fts.js
'use strict';
var sqlite3 = require('你的名字');
var db = new sqlite3.Database('./test.sqlcipher');
db.serialize(function() {
var stmt
, messages
;
db.run("PRAGMA KEY = 'secret'");
// db.run("PRAGMA key = \"x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'\"");
// db.run("PRAGMA CIPHER = 'aes-128-cbc'");
db.run("CREATE TABLE messages(id INTEGER, user VARCHAR, msg TEXT)");
db.run("CREATE VIRTUAL TABLE messages_fts USING FTS4(user VARCHAR, msg TEXT)");
stmt = db.prepare("INSERT INTO messages(id, user, msg) VALUES (?, ?, ?)");
messages = [
[1, 'coolaj86', 'this is test message number one']
, [2, 'ajthedj', 'this is test message number two']
, [3, 'coolaj86', 'this is test message number three']
];
messages.forEach(function (msg) {
stmt.run(msg);
});
stmt.finalize();
db.run("INSERT INTO messages_fts SELECT user, msg FROM messages");
db.get("SELECT * FROM messages INNER JOIN messages_fts ON messages.user = messages_fts.user WHERE messages_fts.msg MATCH 'one'", function (err, data) {
if (err) {
console.error(err);
return;
}
console.log(data);
});
db.all("SELECT * FROM messages INNER JOIN messages_fts ON messages.user = messages_fts.user WHERE messages_fts.msg MATCH 'two'", function (err, data) {
if (err) {
console.error(err);
return;
}
console.log(data);
});
db.each("SELECT * FROM messages INNER JOIN messages_fts ON messages.user = messages_fts.user WHERE messages_fts.msg MATCH 'message'", function (err, data) {
if (err) {
console.error(err);
return;
}
console.log(data);
});
});

执行 node test-sqlcipher-fts.js. 如果出现以下画面, 就说明编译成功了.

$ node test-sqlcipher-fts.js
{ id: 1,
user: 'coolaj86',
msg: 'this is test message number one' }
[ { id: 2,
user: 'ajthedj',
msg: 'this is test message number two' } ]
{ id: 1,
user: 'coolaj86',
msg: 'this is test message number one' }
{ id: 1,
user: 'coolaj86',
msg: 'this is test message number three' }
{ id: 2,
user: 'ajthedj',
msg: 'this is test message number two' }
{ id: 3,
user: 'coolaj86',
msg: 'this is test message number one' }
{ id: 3,
user: 'coolaj86',
msg: 'this is test message number three' }
$ hexdump -C test.sqlcipher | head -15
00000000 8f 47 28 8d cc 91 72 15 8c fd c6 11 57 41 99 16 |.G(...r.....WA..|
00000010 bf 15 20 d4 65 b1 17 1c 73 30 ae 43 fd 31 9e 0c |.. .e...s0.C.1..|
00000020 c3 5c dc e1 a6 2e 80 b1 3b 97 d9 ed fe dc ea f3 |.\......;.......|
00000030 a8 de ad 04 4b 73 cf ad 01 74 f0 c7 19 71 d3 07 |....Ks...t...q..|
00000040 a3 4f fa 88 ce 00 f1 53 15 dd 06 1b e0 e7 94 50 |.O.....S.......P|
00000050 dd 44 a5 8e d9 21 0d 86 f1 7c 37 7e a2 c1 ce a4 |.D...!...|7~....|
00000060 6e d5 54 c3 79 67 0f dd 1c 0f 3a ac c7 1f ad b3 |n.T.yg....:.....|
00000070 75 63 e7 88 d1 9b f3 f0 16 f3 58 6b 5a 59 b1 70 |uc........XkZY.p|
00000080 c1 77 30 29 fa b4 ef 42 f5 88 57 3f 4c a9 e8 1b |.w0)...B..W?L...|
00000090 ba d3 aa cb b4 40 a1 0b 53 23 48 92 d1 25 a7 7a |.....@..S#H..%.z|
000000a0 60 ea 65 b0 56 ea 25 7f 6e cb 74 c5 71 a4 83 df |`.e.V.%.n.t.q...|
000000b0 52 83 a5 82 0e f7 6b 0f 33 85 16 85 9b 08 2e 93 |R.....k.3.......|
000000c0 23 e0 75 bc 09 bf 76 ca 9a cf e6 8d bf 65 82 0b |#.u...v......e..|
000000d0 de 68 4e d9 77 0b 5b d4 23 b2 b9 56 7e c5 5c a5 |.hN.w.[.#..V~.\.|
000000e0 c7 a5 75 cc 9b 85 f4 64 ca 47 f9 e3 54 ca 20 c6 |..u....d.G..T. .|

这个时候就可以看出来, 数据库已经被加密了.

错误
  1. LNK2001 无法解析的外部符号 imp _endthreadex

    缺少了 Windows 多线程的库 msvcrt.lib

  2. LNK2001 无法解析的外部符号 __imp__CertOpenStore@20

    因为 OpenSSL 使用了 Windows 的一个加密库: crypt32ws2_32. 加上就可以了.

  3. LINK : fatal error C1007: 无法识别的标志“-Ot”(在“p2”中)

    在 Windows 系统上, SQLCipher 的静态库是我们自己编译的. 我遇到这个错误的原因是我使用的是 VS2017 编译的静态库, 但是连接的工具缺失 vs 2015. 将 SQLCipher 的工具版本降级就可以了.


推荐阅读
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • node.jsrequire和ES6导入导出的区别原 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了JavaScript进化到TypeScript的历史和背景,解释了TypeScript相对于JavaScript的优势和特点。作者分享了自己对TypeScript的观察和认识,并提到了在项目开发中使用TypeScript的好处。最后,作者表示对TypeScript进行尝试和探索的态度。 ... [详细]
  • Python已成为全球最受欢迎的编程语言之一,然而Python程序的安全运行存在一定的风险。本文介绍了Python程序安全运行需要满足的三个条件,即系统路径上的每个条目都处于安全的位置、"主脚本"所在的目录始终位于系统路径中、若python命令使用-c和-m选项,调用程序的目录也必须是安全的。同时,文章还提出了一些预防措施,如避免将下载文件夹作为当前工作目录、使用pip所在路径而不是直接使用python命令等。对于初学Python的读者来说,这些内容将有所帮助。 ... [详细]
  • 其实之前也有下载过完整的android源码,但是从来没有对这个做过一些总结,在加上最近需要经常去看,索性就在从新下载,编译一下,其实这些东西官网上面都有。http:sou ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • 微信民众号商城/小顺序商城开源项目介绍及使用教程
    本文介绍了一个基于WeiPHP5.0开发的微信民众号商城/小顺序商城的开源项目,包括前端和后端的目录结构,以及所使用的技术栈。同时提供了项目的运行和打包方法,并分享了一些调试和开发经验。最后还附上了在线预览和GitHub商城源码的链接,以及加入前端交流QQ群的方式。 ... [详细]
author-avatar
手机用户2602879695
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有