SQLite 3.7.13的加密解密(四)―― 挂接加密解密函数

SQLite 3.7.13的加密解密(四)―― 挂接加密解密函数,第1张

概述把crypt.c中实现的加密解密函数挂接到sqlite3.c中,并且实现前面编译提示的未实现的函数。在sqlite3.c的最后一行的后面,添加如下代码: #ifdef SQLITE_HAS_CODEC #include "crypt.h"   /***  加密结构  ***/ #define CRYPT_OFFSET 8 typedef struct _CryptBlock {        BY

把crypt.c中实现的加密解密函数挂接到sqlite3.c中,并且实现前面编译提示的未实现的函数。在sqlite3.c的最后一行的后面,添加如下代码:
#ifdef sqlITE_HAS_CODEC #include "crypt.h" /*** 加密结构 ***/ #define CRYPT_OFFSET 8 typedef struct _CryptBlock { BYTE* ReadKey; // 读数据库和写入事务的密钥 BYTE* WriteKey; // 写入数据库的密钥 int PageSize; // 页的大小 BYTE* Data; } CryptBlock,*LPCryptBlock; #ifndefDB_KEY_LENGTH_BYTE /*密钥长度*/ #defineDB_KEY_LENGTH_BYTE 16 /*密钥长度*/ #endif #ifndefDB_KEY_padding /*密钥位数不足时补充的字符*/ #defineDB_KEY_padding 0x33/*密钥位数不足时补充的字符*/ #endif /*** 下面是编译时提示缺少的函数 ***/ /** 这个函数不需要做任何处理,获取密钥的部分在下面 DeriveKey 函数里实现 **/ voID sqlite3CodecGetKey(sqlite3* db,int nDB,voID** Key,int* nKey) { return; } /*被 sqlite@H_404_132@ 和 sqlite3_key_interop 调用,附加密钥到数据库.*/ int sqlite3CodecAttach(sqlite3 *db,int nDb,const voID *pKey,int nKeyLen); /** 这个函数好像是 sqlite@H_404_132@ 3.3.17前不久才加的,以前版本的 sqlite@H_404_132@里没有看到这个函数 这个函数我还没有搞清楚是做什么的,它里面什么都不做直接返回,对加解密没有影响 **/ voID sqlite3_activate_see( const char* right) { return; } int sqlite3_key(sqlite3 *db,int nKey); int sqlite3_rekey(sqlite3 *db,int nKey); /*** 下面是上面的函数的辅助处理函数 ***/ // 从用户提供的缓冲区中得到一个加密密钥 // 用户提供的密钥可能位数上满足不了要求,使用这个函数来完成密钥扩展 static unsigned char * DeriveKey( const voID *pKey,int nKeyLen); //创建或更新一个页的加密算法索引.此函数会申请缓冲区.

static LPCryptBlock CreateCryptBlock(unsigned char* hKey,Pager@H_404_132@ *pager,

LPCryptBlock pExisting); //加密/解密函数,被pager调用

voID * sqlite3Codec(voID *pArg,unsigned char *data,Pgno@H_404_132@ nPageNum,int nMode);

//设置密码函数 int __stdcall sqlite3_key_interop(sqlite3 *db,int nKeySize); // 修改密码函数 int __stdcall sqlite3_rekey_interop(sqlite3 *db,int nKeySize); //销毁一个加密块及相关的缓冲区,密钥. static voID DestroyCryptBlock(LPCryptBlock pBlock);

static voID * sqlite3pager_get_codecarg(Pager@H_404_132@ *pPager);

voID sqlite3pager_set_codec( Pager@H_404_132@ *pPager, voID *(*xCodec)( voID*,voID*,Pgno,int),voID *pCodecArg); //加密/解密函数,int nMode) {

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

PgHdr@H_404_132@ *pageheader;

pageheader = DATA_TO_PGHDR(data);

if (pageheader->pPager@H_404_132@->pageSize@H_404_132@ != pBlock->PageSize) {

CreateCryptBlock(0,pageheader->pPager@H_404_132@,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,pBlock->WriteKey,DB_KEY_LENGTH_BYTE); /*调用我的加密函数*/

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

memcpy(pBlock->Data + CRYPT_OFFSET,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@H_404_132@ *pPager)

{

return (pPager->xCodec@H_404_132@) ? pPager->pCodecArg@H_404_132@ : NulL@H_404_132@;

} // 从用户提供的缓冲区中得到一个加密密钥 static unsigned char * DeriveKey( const voID *pKey,int nKeyLen) { unsigned char * hKey = NulL@H_404_132@; int j;

if (pKey == NulL@H_404_132@ || nKeyLen == 0)

{ return NulL@H_404_132@; }

hKey = sqliteMalloc(DB_KEY_LENGTH_BYTE + 1);

if (hKey == NulL@H_404_132@) { return NulL@H_404_132@; }

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,DB_KEY_LENGTH_BYTE);

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

static LPCryptBlock CreateCryptBlock(unsigned char* hKey,

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

pBlock = sqliteMalloc(sizeof(CryptBlock));

memset(pBlock,sizeof(CryptBlock)); pBlock->ReadKey = hKey; pBlock->WriteKey = hKey; pBlock->PageSize = pager-> pageSize@H_404_132@; pBlock->Data = ( unsigned char*) sqliteMalloc( pBlock->PageSize + CRYPT_OFFSET); } else //更新存在的加密块 {

pBlock = pExisting;

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

sqliteFree(pBlock->Data); pBlock->PageSize = pager-> pageSize@H_404_132@; pBlock->Data = ( unsigned char*) sqliteMalloc( pBlock->PageSize + CRYPT_OFFSET); } } memset(pBlock->Data,pBlock->PageSize + CRYPT_OFFSET); return pBlock; } /*

** Set the codec@H_404_132@ for this pager

*/ voID sqlite3pager_set_codec( Pager@H_404_132@ *pPager,voID *(*xCodec)( voID*,voID *pCodecArg) {

pPager->xCodec@H_404_132@ = xCodec;

pPager->pCodecArg@H_404_132@ = pCodecArg;

} int sqlite3_key(sqlite3 *db,int nKey) {

return sqlite3_key_interop(db,nKey);

} int sqlite3_rekey(sqlite3 *db,int nKey) {

return sqlite3_rekey_interop(db,nKey);

} /*被 sqlite@H_404_132@ 和 sqlite3_key_interop 调用,int nKeyLen) { int rc = sqlITE_ERROR@H_404_132@; unsigned char* hKey = 0; //如果没有指定密匙,可能标识用了主数据库的加密或没加密.

if (!pKey || !nKeyLen)

{ if (!nDb) { return sqlITE_OK@H_404_132@; //主数据库,没有指定密钥所以没有加密. } else //附加数据库,使用主数据库的密钥. { //获取主数据库的加密块并复制密钥给附加数据库使用

LPCryptBlock pBlock = (LPCryptBlock) sqlite3pager_get_codecarg(

sqlite3BtreePager(db->aDb[0].pBt)); if (!pBlock) return sqlITE_OK@H_404_132@; //主数据库没有加密 if (!pBlock->ReadKey) return sqlITE_OK@H_404_132@; //没有加密 memcpy(pBlock->ReadKey,&hKey,16); } } else //用户提供了密码,从中创建密钥. {

hKey = DeriveKey(pKey,nKeyLen);

} //创建一个新的加密块,并将解码器指向新的附加数据库. if (hKey) {

LPCryptBlock pBlock = CreateCryptBlock(hKey,

sqlite3BtreePager(db->aDb[nDb].pBt),NulL@H_404_132@); sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt),

sqlite3Codec,pBlock);

rc = sqlITE_OK@H_404_132@; } return rc; } // Changes the encryption key for an existing database. int __stdcall sqlite3_rekey_interop(sqlite3 *db,int nKeySize) {

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

Pager@H_404_132@ *p = sqlite3BtreePager(pbt);

LPCryptBlock pBlock = (LPCryptBlock) sqlite3pager_get_codecarg(p);

unsigned char * hKey = DeriveKey(pKey,nKeySize);

int rc = sqlITE_ERROR@H_404_132@;

if (!pBlock && !hKey)

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

pBlock = CreateCryptBlock(hKey,p,NulL@H_404_132@);

pBlock->ReadKey = 0; // 原始数据库未加密

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

} else // 改变已加密数据库的写密钥 { pBlock->WriteKey = hKey; } // 开始一个事务

rc = sqlite3BtreeBeginTrans(pbt,1);

if (!rc) { // 用新密钥重写所有的页到数据库。

Pgno@H_404_132@ nPage = sqlite3PagerPagecount(p);

Pgno@H_404_132@ nSkip = PAGER_MJ_PGNO(p);

voID *pPage;

Pgno@H_404_132@ n;

for (n = 1; rc == sqlITE_OK@H_404_132@ && n <= nPage; n++)

{ if (n == nSkip) continue; rc = sqlite3PagerGet(p,n,&pPage); if (!rc) {

rc = sqlite3PagerWrite(pPage);

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

rc = sqlite3BtreeCommit(pbt);

} // 如果失败,回滚。 if (rc) { sqlite3BtreeRollback(pbt); } // 如果成功,销毁先前的读密钥。并使读密钥等于当前的写密钥。 if (!rc) { if (pBlock->ReadKey) { sqliteFree(pBlock->ReadKey); } pBlock->ReadKey = pBlock->WriteKey; } else // 如果失败,销毁当前的写密钥,并恢复为当前的读密钥。 { if (pBlock->WriteKey) { sqliteFree(pBlock->WriteKey); } pBlock->WriteKey = pBlock->ReadKey; } // 如果读密钥和写密钥皆为空,就不需要再对页进行编解码。 // 销毁加密块并移除页的编解码器

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

{

sqlite3pager_set_codec(p,NulL@H_404_132@,NulL@H_404_132@);

DestroyCryptBlock(pBlock); } return rc; } /*** 下面是加密函数的主体 ***/ int __stdcall sqlite3_key_interop(sqlite3 *db,int nKeySize) {

return sqlite3CodecAttach(db,nKeySize);

} // 释放与一个页相关的加密块 voID sqlite3pager_free_codecarg( voID *pArg) { if (pArg) DestroyCryptBlock((LPCryptBlock) pArg); } #endif //# ifdef@H_404_132@ sqlITE_HAS_CODEC
特别说明: DeriveKey 函数,这个函数是对密钥的扩展。比如,你要求密钥是128位,即是16字节,但是如果用户只输入 1个字节呢?2个字节呢?或输入50个字节呢?你得对密钥进行扩展,使之符合16字节的要求。

DeriveKey 函数就是做这个扩展的。有人把接收到的密钥求md5,这也是一个办法,因为md5运算结果固定16字节,不论你有多少字符,最后就是16字节。这是md5算法的特点。但是我不想用md5,因为还得为它添加包含一些 md5 的.c或.cpp文件。我不想这么做。我自己写了一个算法来扩展密钥,很简单的算法。当然,你也可以使用你的扩展方法,也而可以使用 md5 算法。只要修改 DeriveKey 函数就可以了。

在 DeriveKey 函数里,只管申请空间构造所需要的密钥,不需要释放,因为在另一个函数里有释放过程,而那个函数会在数据库关闭时被调用。参考上面 DeriveKey 函数来申请内存。

总结

以上是内存溢出为你收集整理的SQLite 3.7.13的加密解密(四)―― 挂接加密解密函数全部内容,希望文章能够帮你解决SQLite 3.7.13的加密解密(四)―― 挂接加密解密函数所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1175544.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存