作者:高张远瞩(HiLoveS)
博客:http://www.cnblogs.com/hiloves/
转载请保留该信息
(http://sourceforge.net/projects/wxcode/files/Components/)
SQLite 3 开源版不带加密功能,对于一个保存在本地的数据库来说没有加密功能让人难以接受,只要用记事本打开数据库就可以看到数据库内保存的数据,对安全多多少少有一点影响。有一个办法是把内容加密后保存到数据库中,但遇到类似 like,或字段内容与字段内容比较这就不行了。治本的办法是让 SQLite 原生的支持加密。好在 SQLite 的作者预留了加密解密的相关接口,许多爱好者也自己修改源版添加加密功能。如果你也在关注,那你可能已经阅读了大量关于如何添加加密的文章,同时我也不是很通相关的技术,我就不再讲解如何修改源码了。虽然网上有大量的文章教你如何修改源码,但都没有提供编译后的 DLL 文件,或者提供的 DLL 版本过低。这里介绍一个开源项目:wxSQLite3,该项目是一个 SQLite 的 C++ warpper,它顺带将 SQLite 的加密函数实现了,并且它使用 AES 算法进行加密。你可以在这里下载到最新的包,在目录 \sqlite3\secure 下有这几个目录,aes128 目录下的 sqlite3.dll 文件,是已编译的用128位 AES 算法加密的 SQLite 3 DLL 文件,而 aes 256 目录下的是用256位 AES 算法加密的,而 src 目录下是实现加密的 SQLite 3 源代码。同时 wxSQLite3 项目更新很快,你总是可以下载到较新的包。从1.9.8版本开始将对256位 AES 加密算法进行实验,估计不久的版本就可以稳定使用。
使用起来也很简单,首先打开数据库 sqlite3_open,然后在操作数据库之前执行 sqlite3_key 后就可进行数据库操作,否则会返回错误。
sqlite3_key是输入密钥,如果数据库已加密必须先执行此函数并输入正确密钥才能进行操作,如果数据库没有加密,执行此函数后进行数据库操作反而会出现“此数据库已加密或不是一个数据库文件”的错误。
int sqlite3_key( sqlite3 *db, const void *pKey, int nKey),db 是指定数据库,pKey 是密钥,nKey 是密钥长度。例:sqlite3_key( db, "abc", 3);
sqlite3_rekey是变更密钥或给没有加密的数据库添加密钥或清空密钥,变更密钥或清空密钥前必须先正确执行 sqlite3_key。在正确执行 sqlite3_rekey 之后在 sqlite3_close 关闭数据库之前可以正常操作数据库,不需要再执行 sqlite3_key。
int sqlite3_rekey( sqlite3 *db, const void *pKey, int nKey),参数同上。
清空密钥为 sqlite3_rekey( db, NULL, 0)。
///另一个文章
SQLite 简介
SQLite是非常优秀的跨平台数据库引擎。与最常见的需要服务进程的数据库引擎(如MySQL)不同,SQLite 引擎不是独立的进程,而是与主程序编译在一起、并运行在同一个进程空间中的代码。数据的存取则是通过程序内直接调用其API 实现的,整个数据库都在宿主主机上存储在一个单一的文件中。这些使得 SQLite在读写效率、消耗总量、延迟时间和整体简单性上具有很大的优越性。
最为重要的的是,整个 SQLite 引擎是一个相对小规模的轻量级 C 语言库。理论上说,任何平台,只要有 C语言编译器,SQLite 就能够移植到该平台上。又由于其轻量性,SQLite成为了处理器性能、内存容量上都相对有限的嵌入式平台数据库的最佳解决方案(如 Google 的开源手机平台Android);同时也是中小规模 CMS 系统数据库的良好解决方案;当然,PC 上的软件,也大量的采用了 SQLite (如Firefox)。
不过,SQLite有一个致命的缺点:免费版并不能对数据库进行加密。也就是说,这个存储于本地的数据库文件,如果用任何文本编辑器打开,数据内容便一览无余……相当的可怕吧,想想如果嘻来嚷往使用未加密的 SQLite来存储数据,各位用户的密码那就是垂手可得啦,哈哈哈,说不准你就使用的跟银行帐户一样的密码。不过呢站长 Tim是非常负责滴,WordPress 是非常强大滴,密码在存入数据库之前已经通过 WordPress程序经过不可逆加密,就算能看到这些密码,也是一堆乱七八糟的东西。
给 SQLite 上把锁
作为一个著名的开源项目和著名的数据库,SQLite的作者不可能没有想到数据加密的问题。其实作者只是留下了接口sqlite3_key而没有实现,这也给使用者更大的空间来用自己需要的算法加密数据。
密码学是一个庞大复杂的学科,普通的数据库开发者不可能为了加密 SQLite而耗费大量时间去学习这门学科,我们只需要在sqlite3_key接口中调用一些加密API即可(如OpenSSL)。如果你是Windows开发人员,你也可以使用.net提供的加密函数。这样虽然免去了自己编译、学习OpenSSL的麻烦,不过也使得SQLite 失去了跨平台的优势。
这里,Tim 要介绍的是SourceForge 上的一个开源项目wxSQLite3,这一个兼具易用性和可移植性的 SQLite加密解决方案。作者采用了比日益衰老的DES 更为先进的使用Rijndael 算法的AES(退出DES,进入 Rijndael)实现了 SQLite 的加密接口。下面就开始编译加密 SQLite 库前的准备工作吧。
- 首先,到SQLite 官方网站 – http://www.sqlite.org/的download页面,下载 SQLite源码:sqlite-source-x.zip(其中x代表当前的版本号)。注意:不要下载前面的sqlite-amalgamation-x.zip,这是把所有源文件合成单个C文件的源码包,wxSQLite需要独立源文件的源码,否则你要修改 wxSQLite 源码才能编译成功;
- 接着,到wxSQLite 项目 – http://wxcode.sourceforge.net/components/wxsqlite3/主页下载wxSQLite3 最新的release版本。
准备工作就绪后,解开 wxSQLite3 的源码包你可以看到sqlite3子目录,这个目录下现有的代码就是对 SQLite加密接口的 Rijndael 算法实现。将这些代码编译进入 SQLite 库,你有两种选择:
注意:这两种选择,在您最后一道编译时,切记都要在编译参数中开启SQLITE_HAS_CODEC的宏定义,否则即使你调用了sqlite3_key,数据库也得不到加密!
- 动态链接 SQLite 库:首先解开 SQLite 源码包,用你所使用的平台的 C 编译器将 SQLite编译成动态链接库。接着将编译好的库文件拷贝到 wxSQLite3 源码的 sqlite3/lib 目录,将 SQLite的头文件拷贝至 sqlite3/include 目录。接着,在你的编译器的编译选项里加入对这些头文件的包含以及刚刚编译号的SQLite 库的链接,继续编译 sqlite3\secure\src\codec 下的代码。如果一切顺利,一个动态链接的 AES加密 SQLite 引擎库就产生了。
- 静态链接 SQLite 库:同动态链接,先把 SQLite 的头文件拷贝至sqlite3/include 目录,接着将SQLite的c文件拷贝至sqlite3/secure/src。接着你需要自己编写makefile,设置宏USE_DYNAMIC_SQLITE3_LOAD的值为0,最后编译包括sqlite3\secure\src\codec 中的所有代码。一切顺利,一个静态的 AES 加密 SQLite引擎库就产生了。
到这里,你就可以在你的程序中使用这个 AES 加密的 SQLite库了。加密您的数据库的方法,就是在打开的数据库后,在进行读写操作前,用自己指定的密匙调用 SQLite 的加密函数:
其中,pdb是刚刚打开的数据库的指针,XLRW是密匙,4代表密匙长度。这时候,你再用文本编辑器打开 SQLite的数据库文件,那就是一本天书啦。
编译 SQLite 的 C++ warpper – wxSQLite3
最后还是要提一下 wxSQLite3 到底是什么。其实 wxSQLite3 是一个 SQLite 的 C++warpper,只是它只是顺带将 SQLite 的加密函数实现了。如果你是一个 C++ 开发者,又喜欢使用 STL的迭代器模式进行数据访问,那么接下来,推荐你通过链接刚刚编译好的加密 SQLite 库,来编译以 C++ STL 迭代器方式访问SQLite 数据库的 wxSQLite3 库。wxSQLite3的源代码是 src\wxsqlite3.cpp。具体如何编译,笔者就不再赘述。
///
关键字: VC 编译 加密 Sqlite wxSqlite3 编译 wxSqlite3 使用
wxSqlite3作为wxWidgets的扩展组件用C++语法对Sqlite3的API进行了封装,为Sqlite3的使用提供了方便.
wxSqlit3 虽然实现了Sqlite3的加密接口,但默认下载的二进制文件中确没有实现加密,如果需要加密的Sqlite3,需要我们自己动手编译.
在这里我将wxSqlite3编译成Static lib来使用.注意:wxSqlite3的代码依赖于 Sqlite3. 这里为了方便,我将Sqlite3也编译成Static Lib.
编译步骤如下:
分为两大步:
一. 编译加密的Sqlite3
二. 编译wxSqlite3
最新的 wxSqlite3-1.9.9 相对于以前的版本在加密实现源码部分调整为纯C代码了,这对于编译的步骤来说相当简单了.
一. 编译加密的Sqlite3
1. 下载wxSqlite3-1.9.9.zip后,解压到wxsqlite3-1.9.9
(http://sourceforge.net/projects/wxcode/files/Components/)
2. 下载www.Sqlite.org的sqlite-amalgamation-3_XXXX.zip,将压缩包中的文件全部提取到 wxsqlite3-1.9.9\sqlite3\secure\src\codec-c 下(写这篇文章时用的版本是3.6.23.1).
编辑 sqlite3.def , 添加 下面两个函数导出
sqlite3_rekey
sqlite3_key
3. 打开VS,新建一个"static lib",工程名为"Sqlite3Encrypt",保存到"wxsqlite3-1.9.9\sqlite3"下.
4. 导入文件:只要单纯的导入 sqlite3secure.c 这个文件就好了.
5. 设置工程属性: (为方便使用 将Sqlite3的输出调整到wxSqlite3工程的输出目录中).在这一步中,分为Debug与Release版.( 可以通过新建工程时建一个DLL工程,这样就内置了两个版本的配置,然后再将"常规->配置类型"设置为"静态库(lib)"就可以了.)
常规->输出目录:
"..\..\lib\vc_lib"
C/C++->预处理->预处理器定义:
SQLITE3ENCRYPT_EXPORTS
SQLITE_ENABLE_FTS3
SQLITE_ENABLE_FTS3_PARENTHESIS
SQLITE_ENABLE_RTREE
SQLITE_SECURE_DELETE
SQLITE_SOUNDEX
SQLITE_ENABLE_COLUMN_METADATA
SQLITE_HAS_CODEC
CODEC_TYPE=CODEC_TYPE_AES128
C/C++->输出文件->程序数据库文件名:
"..\..\lib\vc_lib\Sqlite3EncryptD.pdb" //Debug版
"..\..\lib\vc_lib\Sqlite3Encrypt.pdb" //Release版
管理员->输出文件:
$(OutDir)\$(ProjectName)D.lib //Debug版
$(OutDir)\$(ProjectName).lib //Release版
6. 编译生成 Sqlite3EncryptD.lib,Sqlite3Encrypt.lib
二. 编译wxSqlite3.
wxSqlite3的编译需要wxWidgets库.去http://www.wxwidgets.org/下载安装包默认安装后,进入"wxWidgets-2.9.0\build\msw"下找到VS的工程文件打开后,编译debug与Release版(这两个版本默认是Static lib).
1. 到"wxsqlite3-1.9.9\build"下找到VS的工程文件打开.这里我只编译 "Static Unicode Debug Monolithic Static"与 "Static Unicode Release Monolithic Static" 版.
2. 设置工程属性:
C/C++->常规->附加包含目录:
"C:\wxWidgets-2.9.0\lib\vc_lib\mswud";"C:\wxWidgets-2.9.0\include";..\include;..\sqlite3\include //Debug版
"C:\wxWidgets-2.9.0\lib\vc_lib\mswu";"C:\wxWidgets-2.9.0\lib\include";..\include;..\sqlite3\include //Release版
C/C++->预处理->预处理器定义:
WXSQLITE3_HAVE_METADATA=1 //修改0为1
WXSQLITE3_HAVE_CODEC=1 //修改0为1
SQLITE_HAS_CODEC //添加
3. 编译生成. wxcode_msw28ud_wxsqlite3.lib,wxcode_msw28u_wxsqlite3.lib
使用:
要使用 wxSqlite3,也是需要 wxWidgets库的.
例:
1. 新建一个控制台项目
2. 设置工程属性:
C/C++->常规->附加包含目录:
"C:\wxWidgets-2.9.0\include" \
"C:\wxWidgets-2.9.0\lib\vc_lib\mswud" // Debug版 --- wxWidgets 库
"C:\wxWidgets-2.9.0\lib\vc_lib\mswu" // Release版 /
"??\wxsqlite3-1.9.9\include" // wxSqlite3 include 目录。
链接器->常规->附加库目录:
"C:\wxWidgets-2.9.0\lib\vc_lib";"??\wxsqlite3-1.9.9\lib\vc_lib"; // Debug版
"C:\wxWidgets-2.9.0\lib\vc_lib";"??\wxsqlite3-1.9.9\lib\vc_lib" // Release版
链接器->输入->附加依赖项:
wxcode_msw28ud_wxsqlite3.lib wxbase29ud.lib Sqlite3EncryptD.lib // Debug版
Sqlite3Encrypt.lib wxcode_msw28u_wxsqlite3.lib wxbase29u.lib // Release版
3. 在代码中引用 #include "wx/wxsqlite3.h"
完成~!
/
SQLite3非常适合跨平台开发而且小巧、免费,现在决定使用该库。
ps:本文只是作为一个记录,并不是一个使用sqlite3的教程,不同的编译环境需要有不同的编译设置,请根据具体的情况进行修改,然后编译
编译环境:
vs2008 express + wxwidget 2.8.9
采用命令行的方式编译的wxwidget库,生成了2套unicode版本的wxwidget的dll库(非monolithic方式,多个dll文件)
一般wxwidget工程的设置情况,右键工程,“属性”->“c/c++”->“预处理器”
debug版本:WIN32;_WINDOWS;__WXMSW__;_DEBUG;__WXDEBUG__;WXUSINGDLL
release版本:WIN32;NDEBUG;_WINDOWS;__WXMSW__;WXUSINGDLL
参见:wxwidget2.8.9+vs2008 express编译
1、在c++中使用sqlite3
1)官网有预编译好的windows版本的dll文件,可以到 http://www.sqlite.org/sqlitedll-3_6_6_2.zip 下载
2)解压,然后执行lib /def:sqlite3.def 生成sqlite3.lib (这里需要设置好编译器的环境变量,否则会提示lib命令找不到)
3)测试,参照 http://www.sqlite.com.cn/MySqlite/4/378.Html 的C/C++例子,然后编译运行
ps:其中具体关于编译环境的设置,就不详细说明了,学习编程最好先把如何使用命令行编译程序的知识熟悉一下,搞清楚环境变量到底是怎么一回事
测试例子的目录结构(为了简单一点,这里将sqlite3的头文件和编译后的lib、dll文件都放在同一个目录sqlite3Test下)
sqlite3Test
|-- sqlite3.dll
|-- sqlite3.h
|-- sqlite3.lib
|-- sqlite3ext.h
|-- sqlite3Test.cpp
编译指令:cl /EHsc sqlite3Test.cpp
使用方法(作为参考):
sqlite3Test.exe test.db "create table film(title,length,year,starring);"
sqlite3Test.exe test.db "insert into film values ('Silence of the Lambs, The', 118, 1991, 'Jodie Foster');"
sqlite3Test.exe test.db "select * from film;"
//sqlite3Test.cpp
02 #include <stdlib.h>
03 #include "sqlite3.h"
04 #pragma comment(lib,"sqlite3.lib")
05
06 static int callback( void *NotUsed, int argc, char **argv, char **azColName) {
07 int i;
08 for(i=0; i<argc; i++) {
09 printf( "%s = %s \n ", azColName[i], argv[i] ? argv[i] : "NULL");
10 }
11 printf( " \n ");
12 return 0;
13 }
14
15 int main( int argc, char **argv) {
16 sqlite3 *db;
17 char *zErrMsg = 0;
18 int rc;
19
20 if( argc!=3 ) {
21 fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT \n ", argv[0]);
22 exit(1);
23 }
24 rc = sqlite3_open(argv[1], &db);
25 if( rc ) {
26 fprintf(stderr, "Can't open database: %s \n ", sqlite3_errmsg(db));
27 sqlite3_close(db);
28 exit(1);
29 }
30 rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
31 if( rc!=SQLITE_OK ) {
32 fprintf(stderr, "SQL error: %s \n ", zErrMsg);
33 sqlite3_free(zErrMsg);
34 }
35 sqlite3_close(db);
36 return 0;
37 }
2、在wxwidget中使用sqlite3(确保wxwidget已经编译完成)
1)下载wxSQLite3 ,参见:http://wxcode.sourceforge.net/components/wxsqlite3/
2)解压,到进入wxsqlite3-1.9.2\sqlite3\lib目录下,执行“lib /def sqlite3.def”生成sqlite3.lib (wxsqlite3编译的时候,在链接的时候用到了sqlite3.lib和sqlite3.dll这2个文件)
2)进入到wxsqlite3-1.9.2\build文件夹
3)使用vs2008 express打开wxsqlite3_vc8.sln,转化成vs2008的sln
4)执行“项目”-> “批生成”,选择“wxsqlite3 DLL Unicode Debug MultilibDLL|Win32”和“wxsqlite3 DLL Unicode release MultilibDLL|Win32”,(因为我编译wxwidget的时候使用的是unicode和multilib)
附注:multilib指的是非Monolithic(单一)的方式,将wxwidget库编译成多个dll文件
5)编译完成之后,文件输出到了wxsqlite3-1.9.2\lib目录下,然后将
wxcode_msw28ud_wxsqlite3.lib
wxcode_msw28ud_wxsqlite3.dll
wxcode_msw28u_wxsqlite3.lib
wxcode_msw28u_wxsqlite3.dll
拷贝到wxWidgets-2.8.9\lib\vc_dll 路径下(我的wxwidget编译环境:vc2008 express+wxWidgets-2.8.9 ,编译生成2套unicode的dll库,位于lib\vc_dll目录下),
6)将wxsqlite3-1.9.2下的include目录拷贝到wxWidgets-2.8.9 ,然后覆盖
7)将从sqlite3官网下载的源码、dll压缩包解压到一个文件夹sqlite3中,然后使用lib /def:sqlite3.def 生成sqlite3.lib ,将该路径添加到path环境变量中
8)将sqlite3添加到vc的include目录中
sqlite3目录结构:
sqlite3
|-- sqlite3.dll
|-- sqlite3.exe
|-- sqlite3.h
|-- sqlite3.lib
|-- sqlite3ext.h
ps:也可以将wxsqlite3单独放在一个位置,然后设置环境变量或者在vc中添加相应的include和lib目录,本文将wxsqlite3-1.9.2下的include和lib全部拷贝到wxwidget的目录下,这么做只是为了方便,将wxsqlite3集成到wxwidget库中,可以避免设置太多的环境变量;
9)测试例子 (前提已经将wxwidget的include和lib以及path设置好了)
a、使用vc2008 express创建一个console程序
b、不使用预编译头
c、将wxsqlite3-1.9.2\sample下的minimal.cpp添加到工程中,
d、右键该工程,“属性”->“c/c++”->“预处理器”,
debug版本修改为"WIN32;_DEBUG;_CONSOLE;__WXDEBUG__;__WXMSW__;WXUSINGDLL"
release版本修改为"WIN32;NDEBUG;_CONSOLE;__WXMSW__;WXUSINGDLL"
e、然后修改“链接器”->“输入”,
debug版本添加wxcode_msw28ud_wxsqlite3.lib
release版本添加wxcode_msw28u_wxsqlite3.lib
然后编译执行,如果没有错误,则表示wxsqlite3编译设置成功 (生成的exe程序执行的时候要能够找到wxwidget、wxsqlite3、sqlite3的几个dll文件)