Sqlite 3.7.14.1 xxtea 암호 화 알고리즘

http://blog.csdn.net/wzq9706/article/details/8133314
최근 에 Sqlite 암호 화 알고리즘 을 연구 하고 있 습 니 다. 여기저기 서 긁 어 모 았 습 니 다. AES 를 어떻게 사용 하 는 지 연구 하지 못 했 습 니 다. 지적, 교 류 를 환영 합 니 다.
1. 최신 버 전 을 공식 다운로드 한 Sqlite 현재
www.sqlite.org
sqlite - amalgamion - 3071401. zip
2. VS 에 빈 항목 추가
3. sqlite - amalgamion - 3071401. zip 압축 풀기
안에 있 는 sqlite 3. h 와 sqlite 3. c 파일 을 복사 하여 프로젝트 디 렉 터 리 에 넣 고 프로젝트 에 추가 합 니 다.
4. 프로젝트 에 "sqlite3crypt. h" 를 추가 하고 다음 코드 를 추가 합 니 다.
#ifndef  DCG_SQLITE_CRYPT_FUNC_
#define  DCG_SQLITE_CRYPT_FUNC_

//#ifdef SQLITE_HAS_CODEC

typedef unsigned char BYTE;
//     
#define CRYPT_OFFSET 8
typedef struct _CryptBlock {

	BYTE* ReadKey; //             
	BYTE* WriteKey; //         
	int PageSize; //     
	BYTE* Data;

} CryptBlock, *LPCryptBlock;

#ifndef DB_KEY_LENGTH_BYTE        //     
#define DB_KEY_LENGTH_BYTE   16   //     
#endif

#ifndef DB_KEY_PADDING            //             
#define DB_KEY_PADDING       0x33 //             
#endif

//     
int sqlite3_encrypt(unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key);
 
//     
int sqlite3_dencrypt(unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key);

// ===
//  sqlite3    /    
void* sqlite3Codec(void *pArg, void *data, int nPageNum, int nMode);

//     /      
void sqlite3CodecFree(void* arg);

//       
unsigned char* DeriveKey(const void *pKey, int nKeyLen);

//                .         .
LPCryptBlock CreateCryptBlock(unsigned char* hKey, int nPageSize, LPCryptBlock pExisting);

//#endif // SQLITE_HAS_CODEC
#endif


5. 프로젝트 에 "sqlite3crypt. c" 를 추가 하고 다음 코드 를 추가 합 니 다.
#include "sqlite3crypt.h"
#include "sqlite3.h"
#include <memory.h>
#include <stdlib.h>

int xxtea( int * v, int n , int * k ) {  
	unsigned int z/*=v[n-1]*/, y=v[0], sum=0,  e,    DELTA=0x9e3779b9 ;  
	int m, p, q ;  
	if ( n>1) {  
		/* Coding Part */  
		z = v[n-1];  
		q = 6+52/n ;  
		while ( q-- > 0 ) {  
			sum += DELTA ;  
			e = sum >> 2&3 ;  
			for ( p = 0 ; p < n-1 ; p++ ){  
				y = v[p+1],  
					z = v[p] += (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);  
			}  
			y = v[0] ;  
			z = v[n-1] += (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);  
		}  
		return 0 ;  

		/* Decoding Part */  
	}else if ( n <-1 ) {  
		n = -n ;  
		q = 6+52/n ;  
		sum = q*DELTA ;  
		while (sum != 0) {  
			e = sum>>2 & 3 ;  
			for (p = n-1 ; p > 0 ; p-- ){  
				z = v[p-1],  
					y = v[p] -= (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);  
			}  
			z = v[n-1] ;  
			y = v[0] -= (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z);  
			sum -= DELTA ;   
		}  
		return 0 ;  
	}  

	return 1 ;  
} 

//     ,   
 // ==============================================================================
int sqlite3_encrypt(unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key)
{
	return 0;
}

//     ,   
// ==============================================================================
int sqlite3_dencrypt( unsigned char * pData, unsigned int data_len, unsigned char * key, unsigned int len_of_key)
{
	
	return 0;
}

// ==============================================================================
void * sqlite3Codec(void *pArg, void *data, int nPageNum, int nMode) {

	 LPCryptBlock pBlock = (LPCryptBlock) pArg;
       unsigned int dwPageSize = 0;
	   int len = 0;
 
       if (!pBlock)
              return data;
       //   pager              .    ,     .
       if (nMode != 2) {
		   int a = 0;
		   a++;
             // PgHdr *pageHeader;
 
             // pageHeader = DATA_TO_PGHDR(data);
             // if (pageHeader->pPager->pageSize != pBlock->PageSize) {
                    // CreateCryptBlock(0, pageHeader->pPager, pBlock);
              //}
       }
 
       switch (nMode) {
       case 0: // Undo a "case 7" journal file encryption
       case 2: //     
		   case 3: //       
        if (!pBlock->ReadKey) break;  
  
        len = 0 - (pBlock->PageSize / 4);  
        xxtea(data, len, pBlock->ReadKey);  
  
        break;  
    case 6: 

		//              
        if (!pBlock->WriteKey) break;  
  
        memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);  
        data = pBlock->Data + CRYPT_OFFSET;  
  
  
        len = pBlock->PageSize / 4;  
        xxtea(data , len, pBlock->WriteKey);  
        break;  

    case 7:
		//         
        if (!pBlock->ReadKey) break;  
        memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);  
        data = pBlock->Data + CRYPT_OFFSET;  
        len = pBlock->PageSize / 4;  
        xxtea(data, len, pBlock->ReadKey);  
        break; 
		   /*
       case 3: //     
              if (!pBlock->ReadKey)
                     break;
 
			  memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);
			  data = pBlock->Data + CRYPT_OFFSET;
			  dwPageSize = pBlock->PageSize;
				
			  //   
              sqlite3_dencrypt((BYTE*)data, dwPageSize, pBlock->ReadKey, DB_KEY_LENGTH_BYTE);
 
              break;
 
       case 6: //            
              if (!pBlock->WriteKey)
                     break;
 
              memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);
              data = pBlock->Data + CRYPT_OFFSET;
              dwPageSize = pBlock->PageSize;
 
			  //   
              sqlite3_encrypt((BYTE*)data, dwPageSize, pBlock->WriteKey, DB_KEY_LENGTH_BYTE); 
 
              break;
 
       case 7: 
			  //         
              //       ,          .            ,           .
              //                    .  ,        ,          ,
              //                   .
              //
              if (!pBlock->ReadKey)
                     break;
 
              memcpy(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);
              data = pBlock->Data + CRYPT_OFFSET;
              dwPageSize = pBlock->PageSize;
 
              sqlite3_encrypt((BYTE*)data, dwPageSize, pBlock->ReadKey, DB_KEY_LENGTH_BYTE);/*        */
 
             // break;*/
       }

	   return data;
}

// ==============================================================================
void sqlite3CodecFree(void* pArg) {
	if (pArg)
	{
		LPCryptBlock pBlock = (LPCryptBlock)pArg;
		//     .
		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);
	}
}


// =====================================================================================
LPCryptBlock CreateCryptBlock(unsigned char* hKey, int nPageSize, LPCryptBlock pExisting)
{
	LPCryptBlock pBlock;

	if (!pExisting) //      
	{
		pBlock = sqlite3_malloc(sizeof(CryptBlock));
		memset(pBlock, 0, sizeof(CryptBlock));
		pBlock->ReadKey = hKey;
		pBlock->WriteKey = hKey;
		pBlock->PageSize = nPageSize;
		pBlock->Data = (unsigned char*) sqlite3_malloc(
			pBlock->PageSize + CRYPT_OFFSET);
	}
	else //        
	{
		pBlock = pExisting;

		if (pBlock->PageSize != nPageSize && !pBlock->Data) {
			sqlite3_free(pBlock->Data);
			pBlock->PageSize = nPageSize;

			pBlock->Data = (unsigned char*) sqlite3_malloc(
				pBlock->PageSize + CRYPT_OFFSET);
		}
	}

	memset(pBlock->Data, 0, pBlock->PageSize + CRYPT_OFFSET);

	return pBlock;
}

//                   
// =====================================================================================
unsigned char * DeriveKey(const void *pKey, int nKeyLen)
{
	unsigned char * hKey = 0;
	int j;

	if (pKey == 0 || nKeyLen == 0)
	{
		return 0;
	}

	hKey = sqlite3_malloc(DB_KEY_LENGTH_BYTE + 1);
	if (hKey == 0)
	{
		return 0;
	}

	hKey[DB_KEY_LENGTH_BYTE] = 0;

	if (nKeyLen < DB_KEY_LENGTH_BYTE)
	{
		memcpy(hKey, pKey, nKeyLen); //            
		j = DB_KEY_LENGTH_BYTE - nKeyLen;

		//         
		memset(hKey + nKeyLen, DB_KEY_PADDING, j);
	}
	else
	{
		//        ,        
		memcpy(hKey, pKey, DB_KEY_LENGTH_BYTE);
	}

	return hKey;
}


6. splite 3. c 파일 의 맨 뒤에 다음 코드 를 추가 합 니 다.
#ifdef SQLITE_HAS_CODEC
#include "sqlite3crypt.h"

//         /   
static void * sqlite3pager_get_codecarg(struct Pager *pPager)
{
       return (pPager->xCodec) ? pPager->pCodec : 0;
}

//         /   
// @Param pPager      
// @Param xCodec  /    
// @Param xCodecFree        /      
// @Param pCodecArg  /    
void sqlite3pager_set_codec(Pager *pPager, void *(*xCodec)(void*, void*, Pgno, int), void (*xCodecFree)(void*), void *pCodecArg)
{
       pPager->xCodec = xCodec;
       pPager->pCodec = pCodecArg;
	   pPager->xCodecFree = xCodecFree;
}


//   Sqlite3  
// ===============================================================================
// ===============================================================================
//               
//             ,           DeriveKey      
void sqlite3CodecGetKey(struct sqlite3* db, int nDB, void** Key, int* nKey) {
	return;
}

//         sqlite 3.3.17      ,     sqlite         
//                 ,            ,        
void sqlite3_activate_see(const char* right) {
	return;
}
 
 //       
int sqlite3_key(sqlite3 *db, const void *pKey, int nKey)
{
	return sqlite3CodecAttach(db, 0, pKey, nKey);
}
 
 //       
int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey)
{
	Pgno nSkip;
     void *pPage;
     Pgno n;
       Btree *pbt = db->aDb[0].pBt;
       Pager *p = sqlite3BtreePager(pbt);
       LPCryptBlock pBlock = (LPCryptBlock) sqlite3pager_get_codecarg(p);
       unsigned char * hKey = DeriveKey(pKey, nKey);
       int rc = SQLITE_ERROR;
 
       if (!pBlock && !hKey)
              return SQLITE_OK;
 
       //         ,  pager    ,        .
       if (!pBlock) //           
       {
              pBlock = CreateCryptBlock(hKey, p->pageSize, NULL);
              pBlock->ReadKey = 0; //         
              sqlite3pager_set_codec(sqlite3BtreePager(pbt), sqlite3Codec, sqlite3CodecFree, pBlock);
       }
       else //             
       {
              pBlock->WriteKey = hKey;
       }
 
       //       
       rc = sqlite3BtreeBeginTrans(pbt, 1);
       if (!rc)
       {
              //               。
              //Pgno nPage = sqlite3PagerPagecount(p);
		   int nPage = 0;
		   sqlite3PagerPagecount(p, &nPage);
             
			 nSkip = PAGER_MJ_PGNO(p);
              for (n = 1; rc == SQLITE_OK && n <= nPage; n++)
              {
                     if (n == nSkip)
                           continue;
 
                     rc = sqlite3PagerGet(p, n, (DbPage**)&pPage);
                     if (!rc)
                     {
                           rc = sqlite3PagerWrite((DbPage*)pPage);
                           sqlite3PagerUnref((DbPage*)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, NULL);
			  sqlite3CodecFree(pBlock);
       }
 
       return rc;
}
 
//             
// ================================================================================
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)->pageSize, NULL);
              sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, sqlite3CodecFree, pBlock);
              rc = SQLITE_OK;
       }
 
       return rc;
}

#endif //#ifdef SQLITE_HAS_CODEC

7. OK, 코드 부분 이 완성 되 었 지만 Sqlite 의 암호 화 를 사용 하기 전에 SQLITE 를 미리 추가 해 야 합 니 다.HAS_CODEC 라 는 매크로 를 어떻게 넣 으 면 상세 하 게 말 하지 못 합 니까?
8. 마지막, 테스트 코드
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
#include "sqlite3.h"
};

#define  SQLITE3_STATIC

extern int sqlite3_key(sqlite3 *db, const void *pKey, int nKey);

static int _callback_exec(void * notused,int argc, char ** argv, char ** aszColName)
{
	int i;
	for ( i=0; i<argc; i++ )
	{
		printf( "%s = %s\r
", aszColName[i], argv[i] == 0 ? "NUL" : argv[i] ); } return 0; } int main(int argc, char * argv[]) { const char * sSQL; char * pErrMsg = 0; int ret = 0; sqlite3 * db = 0; // ret = sqlite3_open("encrypt.db", &db); // ret = sqlite3_key( db, "mypass", strlen("mypass")); // sSQL = "create table class(name varchar(20), student);"; sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg ); // sSQL = "insert into class values('mem_52911', 'zhaoyun');"; sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg ); // sSQL = "select * from class;"; sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg ); // sqlite3_close(db); db = 0; return 0; }

좋은 웹페이지 즐겨찾기