//销毁一个加密块及相关的缓冲区,密钥.
//加密/解密
函数,
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;
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;
/*在正常环境下,读密钥和写密钥相同. 当
数据库是被重新加密的,读密钥和写密钥未必相同.
回滚事务必要用
数据库文件的原始密钥写入.因此,当一次回滚被写入,总是用
数据库的读密钥,
这是为了保证与读取原始数据的密钥相同.
*/
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);
}
//释放加密块.
}
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)
{
unsignedchar* hKey = 0;
//如果没有指定密匙,可能标识用了主
数据库的加密或没加密.
if(!pKey || !nKeyLen)
{
if(!nDb)
{
return
sqlITE_OK; //主
数据库,没有指定密钥所以没有加密.
}
{
LPCryptBlock pBlock = (LPCryptBlock) sqlite3pager_get_codecarg(
sqlite3BtreePager(db->aDb[0].pBt));
if(!pBlock)
if(!pBlock->ReadKey)
memcpy(pBlock->ReadKey,&hKey,16);
}
}
{
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);
}
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);
if(!pBlock && !hKey)
//重新加密一个
数据库,改变pager的写密钥,读密钥依旧保留.
if(!pBlock) //加密一个未加密的
数据库
{
pBlock = CreateCryptBlock(hKey,p,NULL);
pBlock->ReadKey = 0; // 原始
数据库未加密
sqlite3pager_set_codec(sqlite3BtreePager(pbt),sqlite3Codec,pBlock);
}
{
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