Sqlite 3.7.14.1 xxtea 加密算法

Sqlite 3.7.14.1 xxtea 加密算法,第1张

概述http://blog.csdn.net/wzq9706/article/details/8133314 最近在研空Sqlite加密算法,东拼西凑,还没研究出AES怎么用,欢迎指正,交流 1.从官方下载最新版本的Sqlite目前 www.sqlite.org 是:如sqlite-amalgamation-3071401.zip 2.在VS中添加一个空项目 3.解压sqlite-amalgamati

http://www.jb51.cc/article/p-fgfdxxce-yd.html

最近在研空sqlite加密算法,东拼西凑,还没研究出AES怎么用,欢迎指正,交流

1.从官方下载最新版本的sqlite目前

www.sqlite.org

是:如sqlite-amalgamation-3071401.zip

2.在VS中添加一个空项目

3.解压sqlite-amalgamation-3071401.zip

复制出里面的sqlite3.h和sqlite3.c文件,放在工程目录中,并添加到工程

4.在工程中添加"sqlite3crypt.h",并添加以下代码

#ifndef  DCG_sqlITE_CRYPT_FUNC_#define  DCG_sqlITE_CRYPT_FUNC_//#ifdef sqlITE_HAS_CODECtypedef unsigned char BYTE;// 加密结构#define CRYPT_OFFSET 8typedef 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 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 len_of_key){	return 0;}// 其它算法,未实现// ==============================================================================int sqlite3_dencrypt( unsigned char * pData,unsigned int len_of_key){		return 0;}// ==============================================================================voID * sqlite3Codec(voID *pArg,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,pBlock->WriteKey);          break;      case 7:		// 加密事务文件的页        if (!pBlock->ReadKey) break;          memcpy(pBlock->Data + CRYPT_OFFSET,pBlock->PageSize);          data = pBlock->Data + CRYPT_OFFSET;          len = pBlock->PageSize / 4;          xxtea(data,pBlock->ReadKey);          break; 		   /*       case 3: //载入一个页              if (!pBlock->ReadKey)                     break; 			  memcpy(pBlock->Data + CRYPT_OFFSET,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,pBlock->PageSize);              data = pBlock->Data + CRYPT_OFFSET;              DWPageSize = pBlock->PageSize; 			  // 加密              sqlite3_encrypt((BYTE*)data,pBlock->WriteKey,DB_KEY_LENGTH_BYTE);                break;        case 7: 			  // 加密事务文件的页              // 在正常环境下,读密钥和写密钥相同. 当数据库是被重新加密的,读密钥和写密钥未必相同.              // 回滚事务必要用数据库文件的原始密钥写入.因此,当一次回滚被写入,总是用数据库的读密钥,// 这是为了保证与读取原始数据的密钥相同.              //              if (!pBlock->ReadKey)                     break;               memcpy(pBlock->Data + CRYPT_OFFSET,pBlock->PageSize);              data = pBlock->Data + CRYPT_OFFSET;              DWPageSize = pBlock->PageSize;               sqlite3_encrypt((BYTE*)data,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,LPCryptBlock pExisting){	LPCryptBlock pBlock;	if (!pExisting) //创建新加密块	{		pBlock = sqlite3_malloc(sizeof(CryptBlock));		memset(pBlock,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,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,DB_KEY_LENGTH_BYTE);	}	return hKey;}

6.在splite3.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,nKey);}  // 实现解密接口int sqlite3_rekey(sqlite3 *db,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);			  sqlite3CodecFree(pBlock);       }        return rc;} // 实现附加密钥到数据库接口// ================================================================================int sqlite3CodecAttach(sqlite3 *db,int nDb,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),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_STATICextern int sqlite3_key(sqlite3 *db,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\n",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,&pErrMsg );	//插入数据	ssql = "insert into class values('mem_52911','zhaoyun');";	sqlite3_exec( db,&pErrMsg );	//取得数据并显示	ssql = "select * from class;";	sqlite3_exec( db,&pErrMsg );	//关闭数据库	sqlite3_close(db);	db = 0;	return 0;}
总结

以上是内存溢出为你收集整理的Sqlite 3.7.14.1 xxtea 加密算法全部内容,希望文章能够帮你解决Sqlite 3.7.14.1 xxtea 加密算法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1174949.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存