#ifdef sqlITE_HAS_CODEC #include"crypt.h" /*** 加密结构 ***/ #defineCRYPT_OFFSET 8 typedefstruct_CryptBlock { BYTE* ReadKey; // 读数据库和写入事务的密钥 BYTE* WriteKey; // 写入数据库的密钥 intPageSize; // 页的大小 BYTE* Data; } CryptBlock,*LPCryptBlock; #ifndefDB_KEY_LENGTH_BYTE /*密钥长度*/ #defineDB_KEY_LENGTH_BYTE 16/*密钥长度*/ #endif #ifndefDB_KEY_padding /*密钥位数不足时补充的字符*/ #defineDB_KEY_padding 0x33/*密钥位数不足时补充的字符*/ #endif /*** 下面是编译时提示缺少的函数 ***/ /** 这个函数不需要做任何处理,获取密钥的部分在下面 DeriveKey 函数里实现 **/ voIDsqlite3CodecGetKey(sqlite3* db,intnDB,voID** Key,int* nKey) { return; } /*被 sqlite和 sqlite3_key_interop 调用,附加密钥到数据库.*/ intsqlite3CodecAttach(sqlite3 *db,intnDb,constvoID*pKey,intnKeyLen); /** 这个函数好像是 sqlite3.3.17前不久才加的,以前版本的 sqlite里没有看到这个函数 这个函数我还没有搞清楚是做什么的,它里面什么都不做直接返回,对加解密没有影响 **/ voIDsqlite3_activate_see( constchar* right) { return; } intsqlite3_key(sqlite3 *db,intnKey); intsqlite3_rekey(sqlite3 *db,intnKey); /*** 下面是上面的函数的辅助处理函数 ***/ // 从用户提供的缓冲区中得到一个加密密钥 // 用户提供的密钥可能位数上满足不了要求,使用这个函数来完成密钥扩展 staticunsignedchar* DeriveKey( constvoID*pKey,intnKeyLen); //创建或更新一个页的加密算法索引.此函数会申请缓冲区. staticLPCryptBlockCreateCryptBlock(unsignedchar* hKey,Pager*pager, LPCryptBlock pExisting); //加密/解密函数,被pager调用 voID*sqlite3Codec(voID*pArg,unsignedchar*data,PgnonPageNum,intnMode); //设置密码函数 int__stdcall sqlite3_key_interop(sqlite3 *db,intnKeySize); // 修改密码函数 int__stdcall sqlite3_rekey_interop(sqlite3 *db,intnKeySize); //销毁一个加密块及相关的缓冲区,密钥. staticvoIDDestroyCryptBlock(LPCryptBlock pBlock); staticvoID*sqlite3pager_get_codecarg(Pager*pPager); voIDsqlite3pager_set_codec( Pager*pPager, voID*(*xCodec)( voID*,voID*,Pgno,int),voID*pCodecArg); //加密/解密函数,intnMode) { LPCryptBlock pBlock = (LPCryptBlock) pArg; unsignedintDWPageSize = 0; if(!pBlock) returndata; // 确保pager的页长度和加密块的页长度相等.如果改变,就需要调整. if(nMode != 2) { PgHdr*pageheader; pageheader = DATA_TO_PGHDR(data); if(pageheader->pPager->pageSize!= pBlock->PageSize) { CreateCryptBlock(0,pageheader->pPager,pBlock); } } switch(nMode) { case0:// Undo a "case 7" journal file encryption case2: //重载一个页 case3: //载入一个页 if(!pBlock->ReadKey) break; DWPageSize = pBlock->PageSize; My_DeEncrypt_Func(data,DWPageSize,pBlock->ReadKey, DB_KEY_LENGTH_BYTE);/*调用我的解密函数*/ break; case6: //加密一个主数据库文件的页 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; case7: //加密事务文件的页 /*在正常环境下,读密钥和写密钥相同. 当数据库是被重新加密的,读密钥和写密钥未必相同. 回滚事务必要用数据库文件的原始密钥写入.因此,当一次回滚被写入,总是用数据库的读密钥, 这是为了保证与读取原始数据的密钥相同. */ if(!pBlock->ReadKey) break; memcpy(pBlock->Data+ CRYPT_OFFSET,DB_KEY_LENGTH_BYTE); /*调用我的加密函数*/ break; } returndata; } //销毁一个加密块及相关的缓冲区,密钥. staticvoIDDestroyCryptBlock(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); } staticvoID*sqlite3pager_get_codecarg(Pager*pPager) { return(pPager->xCodec) ? pPager->pCodecArg:NulL; } // 从用户提供的缓冲区中得到一个加密密钥 staticunsignedchar* DeriveKey( constvoID*pKey,intnKeyLen) { unsignedchar* hKey = NulL; intj; 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,DB_KEY_LENGTH_BYTE); } returnhKey; } //创建或更新一个页的加密算法索引.此函数会申请缓冲区. staticLPCryptBlockCreateCryptBlock(unsignedchar* 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; pBlock->Data = ( unsignedchar*) sqliteMalloc( pBlock->PageSize + CRYPT_OFFSET); } else//更新存在的加密块 { pBlock = pExisting; if(pBlock->PageSize!= pager->pageSize&& !pBlock->Data) { sqliteFree(pBlock->Data); pBlock->PageSize = pager-> pageSize; pBlock->Data = ( unsignedchar*) sqliteMalloc( pBlock->PageSize + CRYPT_OFFSET); } } memset(pBlock->Data,pBlock->PageSize + CRYPT_OFFSET); returnpBlock; } /* ** Set thecodecfor this pager */ voIDsqlite3pager_set_codec( Pager*pPager,voID*(*xCodec)( voID*,voID*pCodecArg) { pPager->xCodec= xCodec; pPager->pCodecArg= pCodecArg; } intsqlite3_key(sqlite3 *db,intnKey) { returnsqlite3_key_interop(db,nKey); } intsqlite3_rekey(sqlite3 *db,intnKey) { returnsqlite3_rekey_interop(db,nKey); } /*被 sqlite和 sqlite3_key_interop 调用,intnKeyLen) { intrc = sqlITE_ERROR; unsignedchar* 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) { LPCryptBlockpBlock = CreateCryptBlock(hKey, sqlite3BtreePager(db->aDb[nDb].pBt),NulL); sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec,pBlock); rc =sqlITE_OK; } returnrc; } // Changes the encryption key for an existing database. int__stdcall sqlite3_rekey_interop(sqlite3 *db,intnKeySize) { Btree*pbt = db->aDb[0].pBt; Pager*p = sqlite3BtreePager(pbt); LPCryptBlock pBlock = (LPCryptBlock) sqlite3pager_get_codecarg(p); unsignedchar* hKey = DeriveKey(pKey,nKeySize); intrc = sqlITE_ERROR; if(!pBlock && !hKey) return sqlITE_OK; //重新加密一个数据库,改变pager的写密钥,读密钥依旧保留. if(!pBlock) //加密一个未加密的数据库 { pBlock = CreateCryptBlock(hKey,p,NulL); pBlock->ReadKey = 0; // 原始数据库未加密 sqlite3pager_set_codec(sqlite3BtreePager(pbt),sqlite3Codec,pBlock); } else// 改变已加密数据库的写密钥 { pBlock->WriteKey = hKey; } // 开始一个事务 rc = sqlite3BtreeBeginTrans(pbt,1); if(!rc) { // 用新密钥重写所有的页到数据库。 PgnonPage = sqlite3PagerPagecount(p); PgnonSkip = PAGER_MJ_PGNO(p); voID*pPage; Pgnon; for(n = 1; rc ==sqlITE_OK&& 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,NulL); DestroyCryptBlock(pBlock); } returnrc; } /*** 下面是加密函数的主体 ***/ int__stdcall sqlite3_key_interop(sqlite3 *db,intnKeySize) { returnsqlite3CodecAttach(db,nKeySize); } // 释放与一个页相关的加密块 voIDsqlite3pager_free_codecarg( voID*pArg) { if(pArg) DestroyCryptBlock((LPCryptBlock) pArg); } #endif//# ifdefsqlITE_HAS_CODEC |
评论列表(0条)