關於解決sqlite中加密設計方案缺陷問題

 
 

    最近在做sqlite存儲數據庫,但是後臺總是會出現一些離奇的崩潰,但又為數不多,查了好久,定位到使用加密以後才會崩潰;調試中發現問題出現在pagesize出錯後出現的page指向地址有問題,原來sqlite3BtreeOpen的時候取出了file的文件頭,但是這部分是加密過後的數據,因此在此時取出的pagesize是不可預料的,但此時數據庫未有key的存在,考慮到如果更改sqlite的加密機制的話難度和風險較大,為此採用在key的時候同時計算出pagesize,並將其設重設到數據庫中,經檢驗此方法可行,以下貼出重設pagesize的代碼:

int sqlite3_key_resetpagesize(sqlite3 *db)
{
	Btree *pbt = db->aDb[0].pBt;
	Pager *p = sqlite3BtreePager(pbt);

	PgHdr *pPg;
	Pager *pPager;
	unsigned char zDbHeader[100];
	int	nRightPageSize = SQLITE_DEFAULT_PAGE_SIZE;

	Pgno nPage = sqlite3pager_pagecount(p);
	Pgno nSkip = PAGER_MJ_PGNO(p);
	void *pPage;
	Pgno n = 1;// sqlite page is from 1 begin, 0 means no page
	int rc = SQLITE_ERROR;
	if (n != nSkip)
	{
		rc = sqlite3pager_get(p, n, &pPage);
		if(!rc)
		{
			pPg = DATA_TO_PGHDR(pPage);
			pPager = pPg->pPager;
			memcpy(zDbHeader, PGHDR_TO_DATA(pPg), sizeof(zDbHeader));
			nRightPageSize = get2byte(&zDbHeader[16]);
			sqlite3BtreeSetPageSize(pbt, nRightPageSize, -1);
		}
	}
	else
		 return SQLITE_OK;//this page must skip,do not mind it
	
	return rc;
}

附注意:必須在sqlite3BtreeOpen中把pageSizeFixed設置為0;具體看這個值的解釋


另外一種方式是將pagesize設置成一個默認的值,不需要去讀取文件頭,不過就是有點耗硬盤。

你可能感兴趣的:(加密,sqlite,File,byte)