SQLite XXTea加密学习

Posted 朝闻道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQLite XXTea加密学习相关的知识,希望对你有一定的参考价值。

这几天优化数据库读写,移植了xxtea加密到最新的数据库sqlite 3.12.2里,一些好文章放在这里。移植后,数据库读写性能异常优秀!

这几天又发现,数据库还是发生了无法写入情况,数据库崩溃掉了。所以,估计想兼容以前数据库是很困难的了。。

  1. 十分推荐他的博客:SQLite学习笔记(十)&&加密     Sqlite学习笔记(一)&&编译安装
  2. sqlite3.6.18加密模块change(讨论)
  3. sqlite3 加解密
  4. SQLITE3 加密总结
  5. sqlite3+使用总结

SQLite学习笔记(十)&&加密 – 天士梦 – 博客园

SQLite学习笔记(十)&&加密

 

     随着移动互联网的发展,手机使用越来越广泛,sqlite作为手机端存储的一种解决方案,使用也非常普遍。但是sqlite本身安全特性却比较弱,比如不支持用户权限,只要能获取到数据库文件就能进行访问;另外也没有加密功能,任何人获取到文件后,就可以查到明文数据。这使得大家对于sqlite又爱又不敢用,毕竟用户的隐私是非常重要的。Sqlite分为开源版本和收费版,收费的版本是支持加密的,只不过需要付2000刀的技术支持费。当然,由于sqlite本身是开源的,业内有很多产品对sqlite增加了加密功能,比如wxsqlite,sqlcipher等。因此想免费使用加密版本的sqlite也不是不可以,但前提是使用过程遇到问题,一定要能hold住,因为免费的东西不一定是稳定的。废话少说,本文主要讨论两个问题, 1.自己如何实现sqlite的加密功能,2.如何使用加密的sqlite。

加密算法选择

要实现加密,首先需要选择一种主流、高效、安全的加密算法,对于手机端和嵌入式设备,还要加上一条简单的原则。加密算法主要分为对称加密算法和非对称加密算法,对于文本加密一般采用对称加密,而对于秘钥的管理则采用非对称加密。目前主流的对称加密算法有DES,AES,RC系列,TEA系列, Blowfish等,非对称加密算法有RSA、Diffie-Hellman等。本人对几种常见的对称加密算法进行了测试,综合起来AES和XXTEA算法性能最好,XXTEA的优势在于实现非常简单,代码不到100行,在端设备上也是一种优势。另外,腾讯一直在使用TEA系列算法作为它的通讯加密和本地存储加密,用实践证明了TEA系列算法的可靠性和安全性。下图是AES算法和XXTEA算法的一些测试数据,仅供参考。XXTEA-256和XXTEA-64,分别表示块大小是256个INT和64个INT。通过测试读写200M数据的时间来评估算法的优劣,每个数据通过测试5次取平均值。

  不加密 AES XXTEA-256 XXTEA-64
写操作 7879.3ms 10283.6ms 10577.3ms 10649.4ms
读操作 315.69ms 3681.4ms 3527ms 3598ms

上层应用加密

     选择好加密算法,那么要实现加密功能了。有童鞋会问,为啥一定要在sqlite内部实现加密,上层应用加密不是一样OK吗?这个确实可以。很多开发语言都自带了加密库函数,直接调用即可。写入数据时进行加密,读出数据时再进行解密。但这种方式主要有以下几个缺点:

  1. 对于加密的数据列,无法使用索引,虽然可以用等值查询,但对于范围查询则无能为力。而且所有类型需要设计为BLOB类型,来存储密文。
  2. 虽然可以对数据列进行加密,但表的元数据无法加密。

所以,总地来说,应用层是一种解决方案,但对开发者不太友好。

sqlite自身加密

     从原理上来看,加入加密模块功能也相对简单,在写入数据块前,调用加密模块进行数据块加密,然后写入文件;而在读取数据块时,先调用加密模块解密,然后加载到缓存。加密模块(红色标注)在整个sqlite实现框架的位置如下图。

实现层面,我们要做的工作主要包括三部分,实现加密算法,然后将加密接口与sqlite关联起来,最后在合适的位置(读写文件),调用加/解密接口完成加密解密工作。由于sqlite自身已经预留了加解密接口,因此第3部分的工作已经帮我们做了,我们只需要实现第1和第2部分工作。核心接口如下:

    1.sqlite3CodecAttach

含义:调用sqlite3PagerSetCodec 将加密接口与sqlite的pager模块关联

    2.xxxCodec

含义:自己定义的加密接口,输入参数是(page_no,读写模式),将指定page加、解密。

    3.sqlite3_key

含义:设置数据库密钥,sqlite3_open后调用该接口。对于非加密库,若调用该接口,会导致后续访问数据报错。

Error: file is encrypted or is not a database

    4.sqlite3_rekey

含义:修改数据库密钥,这个接口会遍历数据库中的所有页,然后用新密钥对页进行加密,写入文件。若将新密钥设置为NULL,则可以将加密库变为普通库。

    5.sqlite3_activate_see

       sqlite3CodecGetKey

这两个接口没有实际作用,可以实现一个空函数,保证能编译通过就行。

加密sqlite使用

如果顺利,我们现在已经有了一个包含加密功能的sqlite了,那么如何使用?下面主要列了一些常见的场景。

   1.如何判断一个db文件是否加密

$sqlite3 ./data/test.db

sqlite> .tables Error: file is encrypted or is not a database

sqlite> pragma key=’123456′ ;

sqlite> .tables

Error: file is encrypted or is not a database

对于加密的db文件,如果没有执行pragma key=xxx命令直接执行,则会报错。假设密码是 123456,报错后,重新执行pragma key命令,然后执行.tables,这时候依旧报错。这个主要是因为密钥在连接创建时初始化,所以对于加密数据库,需要执行的第一条命令是pragma key=xxx

    2.导出加密文件数据

$sqlite3 ./data/test.db // 打开加密数据库文件test.db

sqlite> pragma key=’123456′;   // 设置秘钥

sqlite> .output aaa.sql //将输出重定向到文件aaa.sql

sqlite> .dump //导出数据库

sqlite> .exit   这样aaa.sql中包含了test.db中数据库的明文内容。

    3.解密加密数据库

$sqlite3 ./data/test.db

sqlite> pragma key=’123456′

sqlite> pragma rekey=”;  //设置密钥为空,则将密文数据库解密。

//解密后可以直接打开数据库

$sqlite3 ./data/test.db

sqlite> .tables

  • orders  t1  user

sqlite> .exit

参考文档

https://en.wikipedia.org/wiki/XXTEA

 

作者:
男peliao (国家电位) ▲▲▲▲▲
盒子活跃会员
2009-10-14 21:33:45
标题:
sqlite3.6.18加密模块change(讨论) 附asqlite控件bug 浏览:4467
加入我的收藏
楼主: 很多人使用xxtea的sqlite加密
3.6.18版,
sqlite3PagerSetCodec变化非常大
static void sqlite3PagerSetCodec(
Pager *pPager,
void *(*xCodec)(void*,void*,Pgno,int),
void (*xCodecSizeChng)(void*,int,int),  //新加的
void (*xCodecFree)(void*), //新加的
void *pCodec //对应原来的 pCodecArg另外,xxtea中(如下),  pAux 和 xFreeAux  已经完全消失了
db->aDb[0].pAux = pBlock;
db->aDb[0].xFreeAux = DestroyCryptBlock;**** 问题: xFreeAux 能否用 xCodecFree 代替, 代替后,xxtea怎么变动

 

**** 关于asqlite

风铃兄的sqlite控件看样子是改的disqlite的,对dataset数据行buffer存取
比asqlite好,但太过庞大,且最重要的bug:固定大小varchar截取问题,以及text支持不太好,不支持多条sql语言同时执行(带“;”的sql)

asqlite官版在操作text及widestring上,read做了很多次重复widestring转换,效率低,unicode更是有转换bug
———————————————-

3291763

 
作者:
男ntp2000 (ntp2000) ▲▲▲▲△
普通会员
2009-10-14 22:35:47
1楼: 今天刚好改 风铃兄 的sqlite,随便说说,不对的请大家指正.

 

sqlite3PagerSetCodec变化非常大
static void sqlite3PagerSetCodec(
Pager *pPager,
void *(*xCodec)(void*,void*,Pgno,int),
void (*xCodecSizeChng)(void*,int,int),  //新加的
void (*xCodecFree)(void*), //新加的
void *pCodec //对应原来的 pCodecArg

xCodecSizeChng 更改page大小时候调用的函数,暂时没用上直接NULL
xCodecFree 其实就是代替了xFreeAux的作用,现在释放page,不用我们自己做了。

DestroyCryptBlock 函数要改一下参数类型,不然编译不过。

用20M的Demo测试,未发现明显问题。
———————————————-

作者:
男laihongbo (风铃夜思雨) ▲▲▲▲△
普通会员
2009-10-15 0:42:25
2楼: 即然你都提了,我也发我最新修改的xxteacrypt.c代码

 

#ifdef SQLITE_SOURCESTD
#include <pager.c>
#else
#include <sqlite3.c>
#endif

#ifndef SQLITE_OMIT_DISKIO
#ifdef SQLITE_HAS_CODEC

#include “md5c.c”

#define CRYPT_OFFSET 8
#define BYTE unsigned char
#define WX_PAGER_MJ_PGNO(x) ((PENDING_BYTE/(x))+1)
Btree *m_bt;

typedef struct _CryptBlock
{
BYTE*     ReadKey;     // 读数据库和写入事务的密钥
BYTE*     WriteKey;    // 写入数据库的密钥
int       PageSize;    // 页的大小
BYTE*     Data;
} CryptBlock, *LPCryptBlock;

int xxtea( int * v, int n , int * k ) {
unsigned int z/*=v[n-1]*/, y=v[0], sum=0,  e,    DELTA=0x9e3779b9 ;
int m, p, q ;
if ( n>1) {
/* Coding Part */
z = v[n-1];
q = 6+52/n ;
while ( q– > 0 ) {
sum += DELTA ;
e = sum >> 2&3 ;
for ( p = 0 ; p < n-1 ; p++ ){
y = v[p+1],
z = v[p] += (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
}
y = v[0] ;
z = v[n-1] += (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
}
return 0 ;

/* Decoding Part */
}else if ( n <-1 ) {
n = -n ;
q = 6+52/n ;
sum = q*DELTA ;
while (sum != 0) {
e = sum>>2 & 3 ;
for (p = n-1 ; p > 0 ; p– ){
z = v[p-1],
y = v[p] -= (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
}
z = v[n-1] ;
y = v[0] -= (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
sum -= DELTA ;
}
return 0 ;
}

return 1 ;
} /* Signal n=0,1,-1 */

void sqlite3_activate_see(const char *info)
{
}

void sqlite3CodecSizeChange(void *pArg, int pageSize, int reservedSize)
{
}

/*
** Get the codec argument for this pager
*/
void* mysqlite3PagerGetCodec(
Pager *pPager
){
#if (SQLITE_VERSION_NUMBER >= 3006016)
return sqlite3PagerGetCodec(pPager);
#else
return (pPager->xCodec) ? pPager->pCodecArg : NULL;
#endif
}

/*
** Set the codec argument for this pager
*/
void mySqlite3PagerSetCodec(
Pager *pPager,
void *(*xCodec)(void*,void*,Pgno,int),
void (*xCodecSizeChng)(void*,int,int),
void (*xCodecFree)(void*),
void *pCodec
){
sqlite3PagerSetCodec(pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec);
}

//创建或更新一个页的加密算法索引.此函数会申请缓冲区.
static LPCryptBlock CreateCryptBlock(BYTE* hKey, Pager *pager, LPCryptBlock pExisting)
{
LPCryptBlock pBlock;

if (!pExisting) //创建新加密块
{
pBlock = sqlite3_malloc(sizeof(CryptBlock));
ZeroMemory(pBlock, sizeof(CryptBlock));
pBlock->ReadKey = hKey;
pBlock->WriteKey = hKey;
pBlock->PageSize = pager->pageSize;
pBlock->Data = (BYTE*)sqlite3_malloc(pBlock->PageSize + CRYPT_OFFSET);
}
else //更新存在的加密块
{
pBlock = pExisting;
if ( pBlock->PageSize != pager->pageSize && !pBlock->Data){
sqlite3_free(pBlock->Data);
pBlock->PageSize = pager->pageSize;
pBlock->Data = (BYTE*)sqlite3_malloc(pBlock->PageSize + CRYPT_OFFSET);
}
}

ZeroMemory(pBlock->Data, pBlock->PageSize + CRYPT_OFFSET);

return pBlock;
}

//销毁一个加密块及相关的缓冲区,密钥.
static void DestroyCryptBlock(LPCryptBlock pBlock)
{
//销毁读密钥.
if (pBlock->ReadKey){
sqlite3_free(pBlock->ReadKey);
}

//如果写密钥存在并且不等于读密钥,也销毁.
if (pBlock->WriteKey && pBlock->WriteKey != pBlock->ReadKey){
sqlite3_free(pBlock->WriteKey);
}

if(pBlock->Data){
sqlite3_free(pBlock->Data);
}

//释放加密块.
sqlite3_free(pBlock);
}

// 释放与一个页相关的加密块
void sqlite3CodecFree(void *pArg)
{
if (pArg)
DestroyCryptBlock((LPCryptBlock)pArg);
}

//加密/解密函数, 被pager调用
void * sqlite3Codec(void *pArg, BYTE *data, Pgno nPageNum, int nMode)
{
LPCryptBlock pBlock = (LPCryptBlock)pArg;
int len = 0;

if (!pBlock) return data;

// 确保pager的页长度和加密块的页长度相等.如果改变,就需要调整.
if (nMode != 2)
{
Pager *pageHeader = sqlite3BtreePager(m_bt);
if (pageHeader->pageSize != pBlock->PageSize)  //适用旧版
{
CreateCryptBlock(0, pageHeader, pBlock);
}
}

switch(nMode)
{
case 0: // Undo a “case 7” journal file encryption
case 2: //重载一个页
case 3: //载入一个页
if (!pBlock->ReadKey) break;

len = 0 – (pBlock->PageSize / 4);
xxtea(data, len, pBlock->ReadKey);

break;
case 6: //加密一个主数据库文件的页
if (!pBlock->WriteKey) break;

CopyMemory(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);
data = pBlock->Data + CRYPT_OFFSET;

len = pBlock->PageSize / 4;
xxtea(data , len, pBlock->WriteKey);
break;
case 7: //加密事务文件的页
/*在正常环境下, 读密钥和写密钥相同. 当数据库是被重新加密的,读密钥和写密钥未必相同.
回滚事务必要用数据库文件的原始密钥写入.因此,当一次回滚被写入,总是用数据库的读密钥,
这是为了保证与读取原始数据的密钥相同.
*/
if (!pBlock->ReadKey) break;

CopyMemory(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);
data = pBlock->Data + CRYPT_OFFSET;

len = pBlock->PageSize / 4;
xxtea(data, len, pBlock->ReadKey);
break;
}

return data;
}

// 从用户提供的缓冲区中得到一个加密密钥
static BYTE * DeriveKey(const void *pKey, int nKeyLen)
{
BYTE *  hKey = NULL;
BYTE *  digest = NULL;
MD5_CTX md5ctx;

if ((pKey == NULL) || (nKeyLen <1 ))
{
return NULL;
}

digest = sqlite3_malloc(16);

MD5Init(&md5ctx);

MD5Update(&md5ctx, (unsigned char*)pKey, nKeyLen);
MD5Final(digest, &md5ctx);

hKey = digest;
return hKey;
}

//被sqlite 和 sqlite3_key_interop 调用, 附加密钥到数据库.
int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen)
{
int rc = SQLITE_ERROR;
BYTE* hKey = 0;

//如果没有指定密匙,可能标识用了主数据库的加密或没加密.
if (!pKey || !nKeyLen)
{
if (!nDb)
{
return SQLITE_OK; //主数据库, 没有指定密钥所以没有加密.
}
else //附加数据库,使用主数据库的密钥.
{
//获取主数据库的加密块并复制密钥给附加数据库使用
LPCryptBlock pBlock = (LPCryptBlock)mySqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[0].pBt));

if (!pBlock) return SQLITE_OK; //主数据库没有加密
if (!pBlock->ReadKey) return SQLITE_OK; //没有加密

memcpy(pBlock->ReadKey, &hKey, 16);
}
}
else //用户提供了密码,从中创建密钥.
{
hKey = DeriveKey(pKey, nKeyLen);
}

//创建一个新的加密块,并将解码器指向新的附加数据库.
if (hKey)
{
LPCryptBlock pBlock = CreateCryptBlock(hKey, sqlite3BtreePager(db->aDb[nDb].pBt), NULL);
m_bt = db->aDb[nDb].pBt;
#if (SQLITE_VERSION_NUMBER >= 3006016)
mySqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, sqlite3CodecSizeChange, sqlite3CodecFree, pBlock);
#else
#if (SQLITE_VERSION_NUMBER >= 3003014)
sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);
#else
sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);
#endif
db->aDb[nDb].pAux = pBlock;
db->aDb[nDb].xFreeAux = sqlite3CodecFree;
#endif
rc = SQLITE_OK;
}
return rc;
}

//不保存用户的原始密码.返回NULL.
void sqlite3CodecGetKey(sqlite3 *db, int nDb, void **ppKey, int *pnKeyLen)
{
*ppKey = NULL;
*pnKeyLen = 0;
}

//密钥并不保留到临时空间,仅保存于主数据库.
int sqlite3_key_interop(sqlite3 *db, const void *pKey, int nKeySize)
{
return sqlite3CodecAttach(db, 0, pKey, nKeySize);
}

//改变已有数据库的加密密钥
int sqlite3_rekey_interop(sqlite3 *db, const void *pKey, int nKeySize)
{
Btree *pbt = db->aDb[0].pBt;
Pager *pPager = sqlite3BtreePager(pbt);
LPCryptBlock pBlock = (LPCryptBlock)mySqlite3PagerGetCodec(pPager);
BYTE * hKey = DeriveKey(pKey, nKeySize);
int rc = SQLITE_ERROR;

if (!pBlock && !hKey) return SQLITE_OK;

//重新加密一个数据库,改变pager的写密钥, 读密钥依旧保留.
if (!pBlock) //加密一个未加密的数据库
{
pBlock = CreateCryptBlock(hKey, pPager, NULL);
pBlock->ReadKey = 0; // 原始数据库未加密
m_bt = db->aDb[0].pBt;
#if (SQLITE_VERSION_NUMBER >= 3006016)
mySqlite3PagerSetCodec(pPager, sqlite3Codec, sqlite3CodecSizeChange, sqlite3CodecFree, pBlock);
#else
#if (SQLITE_VERSION_NUMBER >= 3003014)
sqlite3PagerSetCodec(sqlite3BtreePager(pbt), sqlite3Codec, pBlock);
#else
sqlite3pager_set_codec(pPager, sqlite3Codec, pBlock);
#endif
db->aDb[0].pAux = pBlock;
db->aDb[0].xFreeAux = sqlite3CodecFree;
#endif
}
else // 改变已加密数据库的写密钥
{
pBlock->WriteKey = hKey;
}

// 开始一个事务
rc = sqlite3BtreeBeginTrans(pbt, 1);

if (!rc)
{
// 用新密钥重写所有的页到数据库。
#if (SQLITE_VERSION_NUMBER >= 3006000)
int nPageCount = -1;
int rc = sqlite3PagerPagecount(pPager, &nPageCount);
Pgno nPage = (Pgno) nPageCount;
#elif (SQLITE_VERSION_NUMBER >= 3003014)
Pgno nPage = sqlite3PagerPagecount(pPager);
#else
Pgno nPage = sqlite3pager_pagecount(pPager);
#endif
int pageSize = sqlite3BtreeGetPageSize(pbt);
Pgno nSkip = WX_PAGER_MJ_PGNO(pageSize);
#if (SQLITE_VERSION_NUMBER >= 3003014)
DbPage *pPage;
#else
void *pPage;
#endif
Pgno n;

for(n = 1; rc == SQLITE_OK && n <= nPage; n ++)
{
if (n == nSkip) continue;
#if (SQLITE_VERSION_NUMBER >= 3003014)
rc = sqlite3PagerGet(pPager, n, &pPage);
#else
rc = sqlite3pager_get(pPager, n, &pPage);
#endif
if(!rc)
{
#if (SQLITE_VERSION_NUMBER >= 3003014)
rc = sqlite3PagerWrite(pPage);
sqlite3PagerUnref(pPage);
#else
rc = sqlite3pager_write(pPage);
sqlite3pager_unref(pPage);
#endif
}
}
}

// 如果成功,提交事务。
if (!rc)
{
rc = sqlite3BtreeCommit(pbt);
}

// 如果失败,回滚。
if (rc)
{
sqlite3BtreeRollback(pbt);
}

// 如果成功,销毁先前的读密钥。并使读密钥等于当前的写密钥。
if (!rc)
{
if (pBlock->ReadKey)
{
sqlite3_free(pBlock->ReadKey);
}
pBlock->ReadKey = pBlock->WriteKey;
}
else// 如果失败,销毁当前的写密钥,并恢复为当前的读密钥。
{
if (pBlock->WriteKey)
{
sqlite3_free(pBlock->WriteKey);
}
pBlock->WriteKey = pBlock->ReadKey;
}

// 如果读密钥和写密钥皆为空,就不需要再对页进行编解码。
// 销毁加密块并移除页的编解码器
if (!pBlock->ReadKey && !pBlock->WriteKey)
{
#if (SQLITE_VERSION_NUMBER >= 3006016)
mySqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL);
#else
#if (SQLITE_VERSION_NUMBER >= 3003014)
sqlite3PagerSetCodec(pPager, NULL, NULL);
#else
sqlite3pager_set_codec(pPager, NULL, NULL);
#endif
db->aDb[0].pAux = NULL;
db->aDb[0].xFreeAux = NULL;
sqlite3CodecFree(pBlock);
#endif
}
return rc;
}

SQLITE_API int sqlite3_key(sqlite3 *db, const void *pKey, int nKey)
{
return sqlite3_key_interop(db, pKey, nKey);
}

SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey)
{
return sqlite3_rekey_interop(db, pKey, nKey);
}

#endif // SQLITE_HAS_CODEC

#endif // SQLITE_OMIT_DISKIO
———————————————-

作者:
男ntp2000 (ntp2000) ▲▲▲▲△
普通会员
2009-10-15 9:11:29
3楼: 非常感谢,改的比我完善多了. 其实按风兄的思路,改UniDAC的liteprovier支持
sqlite3密码也很简单,这样UniDAC也能支持读取带密码的sqlite3数据库了.
———————————————-
作者:
男peliao (国家电位) ▲▲▲▲▲
盒子活跃会员
2009-10-15 10:37:14
4楼: 谢谢风铃兄修改的xxtea, 这下可以兼容旧的版本了
———————————————-3291763
作者:
男ntp2000 (ntp2000) ▲▲▲▲△
普通会员
2009-10-15 12:03:04
5楼: 另外如果用的BDS2010的话,用BDS2010自带的cw32.lib测试20M Demo

 

内存占用约多7%, 但速度约快7%
———————————————-

作者:
男peliao (国家电位) ▲▲▲▲▲
盒子活跃会员
2009-11-16 13:28:31
6楼: 最好,接过讨论一下风兄的AES加密版的sqlite,如何让bcc32编译通过
———————————————-3291763
作者:
男capelin (多春鱼) ▲▲▲▲▲
盒子活跃会员
2010-2-25 23:05:40
7楼: 我一直想改unidac支持加密的sqlite,但没成功,有谁可以贴出代码?感谢!
———————————————-
作者:
男capelin (多春鱼) ▲▲▲▲▲
盒子活跃会员
2010-3-2 14:01:24
8楼: 有谁可以告诉我如何修改unidac让它支持wxsqlite3.dll的加密功能?我修改了litecalluni.pas和sqliteclassesuni.pas,但都没有成功。
———————————————-
作者:
男jone_h (dodo) ▲▲▲▲△
普通会员
2010-3-28 19:05:19
9楼: ntp2000 :你可发一个带密码的SQlite3.dll和一个支持SQLite加密功能的UniDac组件吗?谢谢~~
———————————————-
没有最好,只有更好!
作者:
男we96127i (weiweijie) ▲▲△△△
注册会员
2012-7-3 11:52:47
10楼: 我把这些方法移植到3.7.13的源码中发现这个不能加密,原来能看到的数据加密后任然可见.后面发现xxtea这个算法根本就没被调用,即使赋值给sqlite3中pager->xCodec后也没见做任何操作,请问这是为什么不能加密。是不是这组代码不完善啊?还有就是如果我需要在linux下编译添加接口后的sqlite3如何编译呢?求大侠尽快回复!!
———————————————-
作者:
男we96127i (weiweijie) ▲▲△△△
注册会员
2012-7-3 13:42:47
11楼: 有人帮我解释一下这是为什么啊?加密部分函数mySqlite3PagerSetCodec这个函数什么都没做啊。
———————————————-
作者:
男we96127i (weiweijie) ▲▲△△△
注册会员
2012-7-3 16:50:55
12楼: 加密/解密函数, 被pager调用sqlite3Codec这个函数是在哪里被调用的呢
———————————————-
作者:
男cool_fish (fish) ▲▲△△△
注册会员
2012-7-10 12:57:39
13楼: 楼主,可不可以指导一下如何实现这个sqlite数据库的加密功能,真心急用呀。
———————————————-
交朋友
作者:
男cool_fish (fish) ▲▲△△△
注册会员
2012-7-10 13:21:33
14楼: 另外楼主,你的sqlite3Codec()这个函数中的CopyMemory(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);这个函数是从哪来的呢?
———————————————-
交朋友

 

sqlite3 加解密

(2013-08-27 09:12:35)

标签:

 

it

分类: 软件开发

SQLite 3.7.13的加密解密(一)—— 前言

SQLite数据库支持加密和解密,但是免费版没有这个功能,不过网上已经有相关的资料,不过这些资料都不是基于SQLite 3.7.13版本的,这里根据网上找到的最全的资料进行整理,实现了SQLite 3.7.13版数据库的加密解密。本系列文章对此进行了详细说明。

开发环境:

操作系统 Win 7
IDE Eclipse Juno (4.2) CDT
编译器 MinGW GCC 4.6.2
SQLite 3.7.13

 

SQLite 3.7.13的加密解密(二)—— 开放宏定义

首先要在sqlite3.c中最前面,添加代码(网上有说在sqlite3.h中添加也可,实际测试在sqlite3.h中打开该宏是无效的):

#ifndef SQLITE_HAS_CODEC

 

#define SQLITE_HAS_CODEC

#endif

 

这个宏是用来确定是否支持加密的。添加上述代码后编译,会出现如下错误:

以上是关于SQLite XXTea加密学习的主要内容,如果未能解决你的问题,请参考以下文章

C#访问加密的SQLite数据库

给 Qt sqlite 增加加密功能

加密你的SQLite

sqlite 加密

将未加密的表移动到加密的 sqlite 数据库

加密你的SQLite

(c)2006-2024 SYSTEM All Rights Reserved IT常识