Sqlite xxteacrypt.c代码
来源:互联网 发布:软件著作权转让费用 编辑:程序博客网 时间:2024/05/11 14:59
http://bbs.2ccc.com/topic.asp?topicid=337891
今天刚好改 风铃兄 的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测试,未发现明显问题。
#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
- Sqlite xxteacrypt.c代码
- c++SQLite
- sqlite-sqlite接口-C/C++
- sqlite代码的编写
- sqlite 增删改查附代码
- SQLite代码与工具
- SQLite代码与工具
- SQLite速度评测代码
- android SQLITE代码
- SQLite使用方法(代码笔记)
- sqlite数据库代码封装
- c/c++ sqlite 範例
- SQLite与C结合
- c/c++ 操纵sqlite
- c/c++ 操作sqlite
- sqlite c库使用
- c/c++ 操作sqlite
- c/c++ 操作sqlite
- 关于ios中编译ffmpeg0.9.2库
- Test语言及Lex使用说明
- 3ds文件结构(四)
- Parse 教程 框架倒入
- 代码之谜(二) - 语句与表达式
- Sqlite xxteacrypt.c代码
- android 查看代码覆盖率
- 北京圣思园_Java SE Lesson 7
- 英语练习95 Computers
- Ubuntu使用Oracle客户端(sqlplus)远程连接Oracle数据库
- 项目管理 笔记之十 —— 项目风险管理
- Linux 驱动编程
- 帮助你操作数字和处理数字格式的javascript类库 - Numeral.js
- VB中的String类型调用VC的DLL