伯乐共勉

讨论。NET专区
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

SQLITE3 使用总结4

Posted on 2007-08-30 15:39  伯乐共勉  阅读(545)  评论(0编辑  收藏  举报

 

/*** 下面是编译时提示缺少的函数 ***/

 

/** 这个函数不需要做任何处理,获取密钥的部分在下面 DeriveKey 函数里实现 **/

void sqlite3CodecGetKey(sqlite3* db, int nDB, void** Key, int* nKey)

{

return ;

}

 

/*sqlite sqlite3_key_interop 调用, 附加密钥到数据库.*/

int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen);

 

/**

这个函数好像是 sqlite 3.3.17前不久才加的,以前版本的sqlite里没有看到这个函数

这个函数我还没有搞清楚是做什么的,它里面什么都不做直接返回,对加解密没有影响

**/

void sqlite3_activate_see(const char* right )

{   

return;

}

 

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

 

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

 

 

 

/***

下面是上面的函数的辅助处理函数

***/

 

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

// 用户提供的密钥可能位数上满足不了要求,使用这个函数来完成密钥扩展

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

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

static LPCryptBlock CreateCryptBlock(unsigned char* hKey, Pager *pager, LPCryptBlock pExisting);

//加密/解密函数, pager调用

void * sqlite3Codec(void *pArg, unsigned char *data, Pgno nPageNum, int nMode);

//设置密码函数

int __stdcall sqlite3_key_interop(sqlite3 *db, const void *pKey, int nKeySize);

// 修改密码函数

int __stdcall sqlite3_rekey_interop(sqlite3 *db, const void *pKey, int nKeySize);

//销毁一个加密块及相关的缓冲区,密钥.

static void DestroyCryptBlock(LPCryptBlock pBlock);

static void * sqlite3pager_get_codecarg(Pager *pPager);

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

 

 

 

//加密/解密函数, pager调用

void * sqlite3Codec(void *pArg, unsigned char *data, Pgno nPageNum, int nMode)

{

LPCryptBlock pBlock = (LPCryptBlock)pArg;

unsigned int dwPageSize = 0;

 

if (!pBlock) return data;

 

// 确保pager的页长度和加密块的页长度相等.如果改变,就需要调整.

if (nMode != 2)

{

     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;

 

 

     dwPageSize = pBlock->PageSize;

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

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

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

     break;

}

 

return data;

}

 

 

 

 

//销毁一个加密块及相关的缓冲区,密钥.

static void DestroyCryptBlock(LPCryptBlock pBlock)

{

//销毁读密钥.

if (pBlock->ReadKey){

     sqliteFree(pBlock->ReadKey);

}

 

//如果写密钥存在并且不等于读密钥,也销毁.

if (pBlock->WriteKey && pBlock->WriteKey != pBlock->ReadKey){

     sqliteFree(pBlock->WriteKey);

}

 

if(pBlock->Data){

     sqliteFree(pBlock->Data);

}

 

//释放加密块.

sqliteFree(pBlock);

}

 

static void * sqlite3pager_get_codecarg(Pager *pPager)

{

return (pPager->xCodec) ? pPager->pCodecArg: NULL;

}

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

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

{

unsigned char *  hKey = NULL;

int j;

 

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

{

     return NULL;

}

 

hKey = sqliteMalloc( DB_KEY_LENGTH_BYTE + 1 );

if( hKey == NULL )

{

     return NULL;

}

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;

}

 

 

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

static LPCryptBlock CreateCryptBlock(unsigned char* hKey, Pager *pager, LPCryptBlock pExisting)

{

LPCryptBlock pBlock;

 

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

{

     pBlock = sqliteMalloc(sizeof(CryptBlock));

     memset(pBlock, 0, sizeof(CryptBlock));

     pBlock->ReadKey = hKey;

     pBlock->WriteKey = hKey;

     pBlock->PageSize = pager->pageSize;

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

}

else //更新存在的加密块

{

     pBlock = pExisting;

     if ( pBlock->PageSize != pager->pageSize && !pBlock->Data){

          sqliteFree(pBlock->Data);

          pBlock->PageSize = pager->pageSize;

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

     }

}

 

 

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

 

return pBlock;

}

 

/*

** Set the codec for this pager

*/

void sqlite3pager_set_codec(

                             Pager *pPager,

                             void *(*xCodec)(void*,void*,Pgno,int),

                            void *pCodecArg

                             )

{

pPager->xCodec = xCodec;

pPager->pCodecArg = pCodecArg;

}