您好,欢迎来到年旅网。
搜索
您的当前位置:首页Sqlite3.7.14.1xxtea加密算法

Sqlite3.7.14.1xxtea加密算法

来源:年旅网
Sqlite3.7.14.1xxtea加密算法

最近在研空Sqlite加密算法,东拼西凑,还没研究出AES怎么⽤,欢迎指正,交流1.从官⽅下载最新版本的Sqlite⽬前www.sqlite.org

是:如sqlite-amalgamation-3071401.zip2.在VS中添加⼀个空项⽬

3.解压sqlite-amalgamation-3071401.zip

复制出⾥⾯的sqlite3.h和sqlite3.c⽂件,放在⼯程⽬录中,并添加到⼯程4.在⼯程中添加\"sqlite3crypt.h\并添加以下代码

#ifndef DCG_SQLITE_CRYPT_FUNC_#define DCG_SQLITE_CRYPT_FUNC_//#ifdef SQLITE_HAS_CODECtypedef unsigned char BYTE;// 加密结构

#define CRYPT_OFFSET 8typedef struct _CryptBlock {

BYTE* ReadKey; // 读数据库和写⼊事务的密钥 BYTE* WriteKey; // 写⼊数据库的密钥 int PageSize; // 页的⼤⼩ BYTE* Data;

} CryptBlock, *LPCryptBlock;

#ifndef DB_KEY_LENGTH_BYTE // 密钥长度#define DB_KEY_LENGTH_BYTE 16 // 密钥长度#endif

#ifndef DB_KEY_PADDING // 密钥位数不⾜时补充的字符#define DB_KEY_PADDING 0x33 // 密钥位数不⾜时补充的字符#endif

// 加密函数

int sqlite3_encrypt(unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key);

// 解密函数

int sqlite3_dencrypt(unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key);// ===

// 被sqlite3调⽤的加/解密函数

void* sqlite3Codec(void *pArg, void *data, int nPageNum, int nMode);// 释放⽽加/密内存的回调

void sqlite3CodecFree(void* arg);

// 验证密码接⼝

unsigned char* DeriveKey(const void *pKey, int nKeyLen);

// 创建或更新⼀个页的加密算法索引.此函数会申请缓冲区.

LPCryptBlock CreateCryptBlock(unsigned char* hKey, int nPageSize, LPCryptBlock pExisting);//#endif // SQLITE_HAS_CODEC#endif

5.在⼯程中添加\"sqlite3crypt.c\并添加以下代码

#include \"sqlite3crypt.h\"#include \"sqlite3.h\"#include #include

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 ; }

// 其它算法,未实现

// ==============================================================================int sqlite3_encrypt(unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key){

return 0;}

// 其它算法,未实现

// ==============================================================================int sqlite3_dencrypt( unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key){

return 0;}

// ==============================================================================void * sqlite3Codec(void *pArg, void *data, int nPageNum, int nMode) { LPCryptBlock pBlock = (LPCryptBlock) pArg; unsigned int dwPageSize = 0; int len = 0;

if (!pBlock)

return data;

// 确保pager的页长度和加密块的页长度相等.如果改变,就需要调整. if (nMode != 2) { int a = 0; a++;

// PgHdr *pageHeader;

// pageHeader = DATA_TO_PGHDR(data);

// if (pageHeader->pPager->pageSize != pBlock->PageSize) { // CreateCryptBlock(0, pageHeader->pPager, 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;

memcpy(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;

memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize); data = pBlock->Data + CRYPT_OFFSET; len = pBlock->PageSize / 4;

xxtea(data, len, pBlock->ReadKey); break; /*

case 3: //载⼊⼀个页

if (!pBlock->ReadKey) break;

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

// 解密

sqlite3_dencrypt((BYTE*)data, dwPageSize, pBlock->ReadKey, DB_KEY_LENGTH_BYTE);

break;

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

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

// 加密

sqlite3_encrypt((BYTE*)data, dwPageSize, pBlock->WriteKey, DB_KEY_LENGTH_BYTE);

break;

case 7:

// 加密事务⽂件的页

// 在正常环境下, 读密钥和写密钥相同. 当数据库是被重新加密的,读密钥和写密钥未必相同. // 回滚事务必要⽤数据库⽂件的原始密钥写⼊.因此,当⼀次回滚被写⼊,总是⽤数据库的读密钥, // 这是为了保证与读取原始数据的密钥相同. //

if (!pBlock->ReadKey) break;

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

sqlite3_encrypt((BYTE*)data, dwPageSize, pBlock->ReadKey, DB_KEY_LENGTH_BYTE);/*调⽤我的加密函数*/

// break;*/ } return data;}

// ==============================================================================void sqlite3CodecFree(void* pArg) { if (pArg) {

LPCryptBlock pBlock = (LPCryptBlock)pArg; //销毁读密钥.

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); }}

// =====================================================================================LPCryptBlock CreateCryptBlock(unsigned char* hKey, int nPageSize, LPCryptBlock pExisting){

LPCryptBlock pBlock;

if (!pExisting) //创建新加密块 {

pBlock = sqlite3_malloc(sizeof(CryptBlock)); memset(pBlock, 0, sizeof(CryptBlock)); pBlock->ReadKey = hKey; pBlock->WriteKey = hKey;

pBlock->PageSize = nPageSize;

pBlock->Data = (unsigned char*) sqlite3_malloc( pBlock->PageSize + CRYPT_OFFSET); }

else //更新存在的加密块 {

pBlock = pExisting;

if (pBlock->PageSize != nPageSize && !pBlock->Data) { sqlite3_free(pBlock->Data);

pBlock->PageSize = nPageSize;

pBlock->Data = (unsigned char*) sqlite3_malloc( pBlock->PageSize + CRYPT_OFFSET); } }

memset(pBlock->Data, 0, pBlock->PageSize + CRYPT_OFFSET); return pBlock;}

// 从⽤户提供的缓冲区中得到⼀个加密密钥

// =====================================================================================unsigned char * DeriveKey(const void *pKey, int nKeyLen){

unsigned char * hKey = 0; int j;

if (pKey == 0 || nKeyLen == 0) {

return 0; }

hKey = sqlite3_malloc(DB_KEY_LENGTH_BYTE + 1); if (hKey == 0) {

return 0; }

hKey[DB_KEY_LENGTH_BYTE] = 0;

if (nKeyLen < DB_KEY_LENGTH_BYTE) {

memcpy(hKey, pKey, nKeyLen); //先拷贝得到密钥前⾯的部分 j = DB_KEY_LENGTH_BYTE - nKeyLen;

//补充密钥后⾯的部分

memset(hKey + nKeyLen, DB_KEY_PADDING, j); } else {

//密钥位数已经⾜够,直接把密钥取过来

memcpy(hKey, pKey, DB_KEY_LENGTH_BYTE); }

return hKey;}

6.在splite3.c⽂件的最后⾯添加以下代码

#ifdef SQLITE_HAS_CODEC#include \"sqlite3crypt.h\"

// 得到页所对应的编/解码块

static void * sqlite3pager_get_codecarg(struct Pager *pPager)

{

return (pPager->xCodec) ? pPager->pCodec : 0;}

// 设置页所对应的编/解码块// @Param pPager 要加密的页// @Param xCodec 加/解密回调

// @Param xCodecFree 释放页对应的加/解密模块回调// @Param pCodecArg 加/解密模块

void sqlite3pager_set_codec(Pager *pPager, void *(*xCodec)(void*, void*, Pgno, int), void (*xCodecFree)(void*), void *pCodecArg){

pPager->xCodec = xCodec; pPager->pCodec = pCodecArg; pPager->xCodecFree = xCodecFree;}

// 实现Sqlite3接⼝

// ===============================================================================// ===============================================================================// 下⾯是编译时提⽰缺少的函数

// 这个函数不需要做任何处理,获取密钥的部分在下⾯ DeriveKey 函数⾥实现void sqlite3CodecGetKey(struct sqlite3* db, int nDB, void** Key, int* nKey) { return;}

// 这个函数好像是 sqlite 3.3.17前不久才加的,以前版本的sqlite⾥没有看到这个函数// 这个函数我还没有搞清楚是做什么的,它⾥⾯什么都不做直接返回,对加解密没有影响void sqlite3_activate_see(const char* right) { return;}

// 实现加密接⼝

int sqlite3_key(sqlite3 *db, const void *pKey, int nKey){

return sqlite3CodecAttach(db, 0, pKey, nKey);}

// 实现解密接⼝

int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey){

Pgno nSkip; void *pPage; Pgno n;

Btree *pbt = db->aDb[0].pBt;

Pager *p = sqlite3BtreePager(pbt);

LPCryptBlock pBlock = (LPCryptBlock) sqlite3pager_get_codecarg(p); unsigned char * hKey = DeriveKey(pKey, nKey); int rc = SQLITE_ERROR;

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

//重新加密⼀个数据库,改变pager的写密钥, 读密钥依旧保留. if (!pBlock) //加密⼀个未加密的数据库 {

pBlock = CreateCryptBlock(hKey, p->pageSize, NULL); pBlock->ReadKey = 0; // 原始数据库未加密

sqlite3pager_set_codec(sqlite3BtreePager(pbt), sqlite3Codec, sqlite3CodecFree, pBlock); }

else // 改变已加密数据库的写密钥 {

pBlock->WriteKey = hKey; }

// 开始⼀个事务

rc = sqlite3BtreeBeginTrans(pbt, 1); if (!rc) {

// ⽤新密钥重写所有的页到数据库。

//Pgno nPage = sqlite3PagerPagecount(p); int nPage = 0;

sqlite3PagerPagecount(p, &nPage);

nSkip = PAGER_MJ_PGNO(p);

for (n = 1; rc == SQLITE_OK && n <= nPage; n++) {

if (n == nSkip) continue;

rc = sqlite3PagerGet(p, n, (DbPage**)&pPage); if (!rc) {

rc = sqlite3PagerWrite((DbPage*)pPage);

sqlite3PagerUnref((DbPage*)pPage); } } }

// 如果成功,提交事务。 if (!rc) {

rc = sqlite3BtreeCommit(pbt); }

// 如果失败,回滚。 if (rc) {

sqlite3BtreeRollback(pbt, SQLITE_OK); }

// 如果成功,销毁先前的读密钥。并使读密钥等于当前的写密钥。 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) {

sqlite3pager_set_codec(p, NULL, NULL, NULL); sqlite3CodecFree(pBlock); }

return rc;}

// 实现附加密钥到数据库接⼝

// ================================================================================int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen){

int rc = SQLITE_ERROR; unsigned char* hKey = 0;

//如果没有指定密匙,可能标识⽤了主数据库的加密或没加密. if (!pKey || !nKeyLen) {

if (!nDb) {

return SQLITE_OK; //主数据库, 没有指定密钥所以没有加密. }

else //附加数据库,使⽤主数据库的密钥. {

//获取主数据库的加密块并复制密钥给附加数据库使⽤

LPCryptBlock pBlock = (LPCryptBlock) sqlite3pager_get_codecarg(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)->pageSize, NULL);

sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, sqlite3CodecFree, pBlock); rc = SQLITE_OK; }

return rc;}

#endif //#ifdef SQLITE_HAS_CODEC

7.OK,代码部分完成了,但要使⽤Sqlite的加密前必须要预添加加SQLITE_HAS_CODEC这个宏,怎么加就不详诉了8.最后,测试代码

#include #include #include extern \"C\" {

#include \"sqlite3.h\"};

#define SQLITE3_STATIC

extern int sqlite3_key(sqlite3 *db, const void *pKey, int nKey);

static int _callback_exec(void * notused,int argc, char ** argv, char ** aszColName){ int i;

for ( i=0; iprintf( \"%s = %s\\r\\n\ } return 0;}

int main(int argc, char * argv[]){

const char * sSQL; char * pErrMsg = 0; int ret = 0;

sqlite3 * db = 0;

//创建数据库

ret = sqlite3_open(\"encrypt.db\

//添加密码

ret = sqlite3_key( db, \"mypass\ //在内存数据库中创建表

sSQL = \"create table class(name varchar(20), student);\"; sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg ); //插⼊数据

sSQL = \"insert into class values('mem_52911', 'zhaoyun');\"; sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg ); //取得数据并显⽰

sSQL = \"select * from class;\";

sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg ); //关闭数据库

sqlite3_close(db); db = 0; return 0;}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务