天天看點

SQLITE3 使用總結(5)本文轉摘自http://www.sqlite.com.cn        作者:董淳光

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

本文轉摘自http://www.sqlite.com.cn        作者:董淳光