因為我們應用的需求,資料庫需要加密(不想被別人用adb pull 就取得資料庫)
Andorid 已經有使用sqlite 來超作資料庫,但是sqlite 沒有加密功能,所以只要自行處理 !!
不過 sqlite 有預留加密的進入點 !!
就一步一步來吧 !!
A.首先先打開 SQLITE_HAS_CODEC 這個 define.
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/external/sqlite/dist/Android.mk 2013-05-27 13:37:12.767651814 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/external/sqlite/dist/Android.mk 2013-05-24 18:55:23.884236340 +0800
@@ -27,7 +27,8 @@
-DSQLITE_OMIT_BUILTIN_TEST \
-DSQLITE_OMIT_COMPILEOPTION_DIAGS \
-DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600
+ -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600\
+ -DSQLITE_HAS_CODEC=1
common_src_files := sqlite3.c
B.Modify sqlite3.c file.
sqlite在編譯之前(Standard method) 會將所有 .c file 合併成為一個 .C file ( 我不知道為何要這樣 )
所以在BSP 內找到對應的檔案, 並且開始修改 !!
在 "Begin file attach.c" 之前開始插入修加密所需要的 code ;
詳細加密的功能可以參考下列網址 :
http://lancelot.blog.51cto.com/393579/940816
這網頁說的蠻清楚的 , 不過因為之前我們舊機種就已經有使用 (linux + GTK 架構 ) , 所以
就移植過來.
因為兩個版本不同,移植過來有些問題 , 所以需要修改一些小東西 , 可以參考下列網址 , 還蠻清楚的 !!
http://lancelot.blog.51cto.com/393579/940814
修改後的 diff 內容如下 , 不過太長加上有些機密問題 (加密方式 ) 所以我只列出一小部份:
diff -Nuraw TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/external/sqlite/dist/sqlite3.c TI-Android-JB-4.1.2_AM335x_4.0.1/external/sqlite/dist/sqlite3.c
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/external/sqlite/dist/sqlite3.c 2013-05-27 13:37:12.802652106 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/external/sqlite/dist/sqlite3.c 2013-05-27 13:33:06.551572993 +0800
@@ -80395,6 +80395,501 @@
#endif /* SQLITE_OMIT_ANALYZE */
/************** End of analyze.c *********************************************/
+/************** Begin file key.c ******************************************/
+
+#ifdef SQLITE_HAS_CODEC
+
+//======== main codec function.
+typedef struct _CryptBlock
+{
+ char *ReadKey;
+ char *WriteKey;
+ int PageSize;
+ char *Data;
+
+} CryptBlock, *LPCryptBlock;
+
+#ifndef DB_KEY_LENGTH_BYTE
+ #define DB_KEY_LENGTH_BYTE 16
+#endif
+
+#ifndef DB_KEY_PADDING
..........
+#endif
+
+#define CRYPT_OFFSET 8
+#define CRYPT_ROW_SIZE 32
+
+int getSBoxValue(int num)
+{
.........................
+ return sbox[num];
+}
+
+int getSBoxInvert(int num)
+{
.................
+return rsbox[num];
+}
+
+int Encrypt_Func( unsigned char * pData, unsigned int data_len, const char * key, unsigned int len_of_key )
+{
+unsigned int i,j;
+//unsigned char *temp1,*temp2,
+unsigned char *sData;
+
+//Encode functino
............................
+ free(sData);
+ return 0;
+}
+
+int DeEncrypt_Func( unsigned char * pData, unsigned int data_len, const char * key, unsigned int len_of_key )
+{
+unsigned int i,j;
+//unsigned char *temp1,*temp2,
+unsigned char *sData;
+
+//Decode functino
+
+
+ //change by row
+// temp1 = (unsigned char*)malloc(CRYPT_ROW_SIZE);
+// temp2 = (unsigned char*)malloc(CRYPT_ROW_SIZE);
+ sData = (unsigned char*)malloc(data_len);
+ memcpy(sData,pData,data_len);
+
+ j = 1;
+ for ( i = 0 ; i < 32 ; i ++)
+ {
+ if ( j >= 32 )
+ j = 0;
+ memcpy(pData+(j*CRYPT_ROW_SIZE),sData+(i*CRYPT_ROW_SIZE),CRYPT_ROW_SIZE);
+ j += 2;
+ }
+
+ //replase by other word
+ for ( i = 0 ; i < data_len ; i++ )
+ {
+ *(pData+i) = getSBoxInvert(*(pData+i));
+ }
+
+ //mask by key
+ for ( i = 0 ; i < data_len ; i++ )
+ {
+ *(pData+i) ^=(*(key+(i%len_of_key)) );
+ }
+
+// free(temp1);
+// free(temp2);
+ free(sData);
+ return 0;
+}
+
+void * sqlite3Codec(void *pArg, void *pdata, Pgno nPageNum, int nMode)
+{
+LPCryptBlock pBlock;
+PgHdr *pageHeader;
+unsigned int dwPageSize = 0;
+unsigned char *data=(unsigned char *)(pdata);
+
+
+ pBlock = (LPCryptBlock)pArg;
+
+ if (!pBlock)
+ return data;
+
+ switch(nMode)
+ {
+ case 0: // Undo a "case 7" journal file encryption
+ case 2: //reload one page
+ case 3: //loading one page
+ if (!pBlock->ReadKey)
+ break;
+
+ dwPageSize = pBlock->PageSize;
+
+ DeEncrypt_Func(data, dwPageSize, pBlock->ReadKey, DB_KEY_LENGTH_BYTE );
+
+ break;
+
+ case 6: //Encrypt one page
+ if (!pBlock->WriteKey)
+ break;
+
+ memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);
+ data = pBlock->Data + CRYPT_OFFSET;
+ dwPageSize = pBlock->PageSize;
+
+ Encrypt_Func(data , dwPageSize, pBlock->WriteKey, DB_KEY_LENGTH_BYTE ); /*?£Y?[K*/
+
+ break;
+
+ case 7:
+ if (!pBlock->ReadKey)
+ break;
+
+ memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);
+ data = pBlock->Data + CRYPT_OFFSET;
+ dwPageSize = pBlock->PageSize;
+
+ Encrypt_Func( data, dwPageSize, pBlock->ReadKey, DB_KEY_LENGTH_BYTE ); /*?£Y?[K*/
+
+ break;
+
+ }
+
+ return data;
+
+}
+
+
+//==========================
+static LPCryptBlock CreateCryptBlock(unsigned char* hKey, Pager *pager, LPCryptBlock pExisting)
+{
+LPCryptBlock pBlock;
+
+ if (!pExisting)
+ {
+ pBlock =(CryptBlock *)sqlite3_malloc(sizeof(CryptBlock));
+
+ memset(pBlock, 0, sizeof(CryptBlock));
+ pBlock->ReadKey = hKey;
+ pBlock->WriteKey = hKey;
+ pBlock->PageSize = pager->pageSize;
+ pBlock->Data = (unsigned char*)sqlite3_malloc(pBlock->PageSize + CRYPT_OFFSET);
+ }
+ else
+ {
+ pBlock = pExisting;
+ if ( pBlock->PageSize != pager->pageSize && !pBlock->Data)
+ {
+ sqlite3_free(pBlock->Data);
+ pBlock->PageSize = pager->pageSize;
+ pBlock->Data = (unsigned char*)sqlite3_malloc(pBlock->PageSize + CRYPT_OFFSET);
+ }
+
+ }
+
+ memset(pBlock->Data, 0, pBlock->PageSize + CRYPT_OFFSET);
+
+ return pBlock;
+
+}
+
+void sqlite3pager_set_codec(Pager *pPager,
+ void *(*xCodec)(void*,void*,Pgno,int),void *pCodecArg)
+{
+ pPager->xCodec = xCodec;
+ pPager->pCodec = pCodecArg;
+}
+
+
+static unsigned char *DeriveKey(const void *pKey, int nKeyLen)
+{
+unsigned char *hKey;
+
+ if( pKey == NULL || nKeyLen == 0 )
+ {
+ return NULL;
+ }
+
+ hKey = NULL;
+ hKey = (unsigned char *)sqlite3_malloc(DB_KEY_LENGTH_BYTE + 1);
+
+ if( hKey == NULL )
+ {
+ return NULL;
+ }
+
+ memset( hKey ,DB_KEY_PADDING, DB_KEY_LENGTH_BYTE + 1 );
+
+ hKey[DB_KEY_LENGTH_BYTE] = '\0';
+
+ if( nKeyLen < DB_KEY_LENGTH_BYTE )
+ {
+ memcpy( hKey, pKey, nKeyLen );
+ memcpy( (hKey+nKeyLen), pKey , (DB_KEY_LENGTH_BYTE-nKeyLen) );
+ }
+ else
+ {
+ memcpy( hKey, pKey, DB_KEY_LENGTH_BYTE );
+ }
+
+ return hKey;
+
+}
+
+
+static void * sqlite3pager_get_codecarg(Pager *pPager)
+{
+ return (pPager->xCodec) ? pPager->pCodec: NULL;
+}
+
+//======== getkey function.
+void sqlite3CodecGetKey(sqlite3 *db, int cnt, void **zKey, int *nKey)
+{
+ return ;
+}
+
+
+
+//======== rekey function.
+
+static void DestroyCryptBlock(LPCryptBlock pBlock)
+{
+ if (pBlock->ReadKey)
+ {
+ sqlite3_free(pBlock->ReadKey);
+ }
+
+ if (pBlock->WriteKey && pBlock->WriteKey != pBlock->ReadKey)
+ {
+ sqlite3_free(pBlock->WriteKey);
+ }
+
+ if(pBlock->Data)
+ {
+ sqlite3_free(pBlock->Data);
+ }
+
+ sqlite3_free(pBlock);
+
+}
+
+
+int 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;
+Pgno nPage;
+
+ if (!pBlock && !hKey)
+ return SQLITE_OK;
+
+ 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)
+ {
+
+ sqlite3PagerPagecount(p,&nPage);
+ 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, (DbPage **)&pPage);
+
+ if(!rc)
+ {
+ rc = sqlite3PagerWrite(pPage);
+ sqlite3PagerUnref(pPage);
+ }
+ }
+ }
+
+ if (!rc)
+ {
+ rc = sqlite3BtreeCommit(pbt);
+ }
+
+
+ if (rc)
+ {
+ sqlite3BtreeRollback(pbt,SQLITE_OK);
+ }
+
+ if (!rc)
+ {
+ if (pBlock->ReadKey)
+ {
+ sqlite3_free(pBlock->ReadKey);
+ }
+
+ pBlock->ReadKey = pBlock->WriteKey;
+
+ }
+ else
+ {
+ if (pBlock->WriteKey)
+ {
+ sqlite3_free(pBlock->WriteKey);
+ }
+
+ pBlock->WriteKey = pBlock->ReadKey;
+
+ }
+
+ if (!pBlock->ReadKey && !pBlock->WriteKey)
+ {
+ sqlite3pager_set_codec(p, NULL, NULL);
+ DestroyCryptBlock(pBlock);
+ }
+
+return rc;
+
+}
+
+int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey)
+{
+ return sqlite3_rekey_interop(db, pKey, nKey);;
+}
+
+//======== acitvate see function.
+void sqlite3_activate_see(const char *zRight)
+{
+ return ;
+}
+
+
+//======== key function.
+
+
+int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *zKey, int nKey)
+{
+int rc;
+unsigned char *hKey;
+LPCryptBlock pBlock;
+
+ rc = SQLITE_ERROR;
+ if (db == NULL)
+ return rc;
+
+ hKey = 0;
+
+ if (!zKey || !nKey)
+ {
+ // not inpute code
+ if (!nDb)
+ {
+ return SQLITE_OK;
+ }
+ else
+ {
+ 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(zKey, nKey);
+ }
+
+ if (hKey)
+ {
+ pBlock = CreateCryptBlock(hKey,sqlite3BtreePager(db->aDb[nDb].pBt), NULL);
+ sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);
+
+ rc = SQLITE_OK;
+ }
+
+ return rc;
+}
+
+int sqlite3_key_interop(sqlite3 *db, const void *pKey, int nKeySize)
+{
+ return sqlite3CodecAttach(db, 0, pKey, nKeySize);
+}
+
+int sqlite3_key(sqlite3 *db, const void *pKey, int nKey)
+{
+ return sqlite3_key_interop(db, pKey, nKey);;
+}
+
+
+#endif
+
+
+/************** End of key.c *********************************************/
/************** Begin file attach.c ******************************************/
/*
** 2003 April 6
大功告成 , 接著 ...... 寫一個程式測試看看吧 ....... (下一篇..... )
沒有留言:
張貼留言