int sqlite3_key(sqlite3 *db, const void *pKey, int nKey)
{
return sqlite3_key_interop(db, pKey, nKey);
}
int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey)
{
return sqlite3_rekey_interop(db, pKey, nKey);
}
int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen)
{
int rc = SQLITE_ERROR;
unsigned char* 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)
{
LPCryptBlock pBlock = CreateCryptBlock(hKey, sqlite3BtreePager(db->aDb[nDb].pBt), NULL);
sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);
rc = SQLITE_OK;
}
return rc;
}
// Changes the encryption key for an existing database.
int __stdcall sqlite3_rekey_interop(sqlite3 *db, const void *pKey, int nKeySize)
{
Btree *pbt = db->aDb[0].pBt;
Pager *p = sqlite3BtreePager(pbt);
LPCryptBlock pBlock = (LPCryptBlock)sqlite3pager_get_codecarg(p);
unsigned char * hKey = DeriveKey(pKey, nKeySize);
int rc = 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)
{
// 用新密鑰重寫所有的頁到資料庫。
Pgno nPage = sqlite3PagerPagecount(p);
Pgno nSkip = PAGER_MJ_PGNO(p);
void *pPage;
Pgno n;
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);
}
return rc;
}
int __stdcall sqlite3_key_interop(sqlite3 *db, const void *pKey, int nKeySize)
{
return sqlite3CodecAttach(db, 0, pKey, nKeySize);
}
// 釋放與一個頁相關的加密塊
void sqlite3pager_free_codecarg(void *pArg)
{
if (pArg)
DestroyCryptBlock((LPCryptBlock)pArg);
}
#endif //#ifdef SQLITE_HAS_CODEC