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

时间:2021-02-16 16:01:50

 

    最近在做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];intnRightPageSize = 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 pageint 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 itreturn rc;}

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


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