Sqlite xxteacrypt.c代码

来源:互联网 发布:软件著作权转让费用 编辑:程序博客网 时间:2024/05/11 14:59

http://bbs.2ccc.com/topic.asp?topicid=337891


今天刚好改 风铃兄 的sqlite,随便说说,不对的请大家指正.

sqlite3PagerSetCodec变化非常大
static void sqlite3PagerSetCodec(
  Pager *pPager,
  void *(*xCodec)(void*,void*,Pgno,int),
  void (*xCodecSizeChng)(void*,int,int),  //新加的
  void (*xCodecFree)(void*), //新加的
  void *pCodec //对应原来的 pCodecArg

xCodecSizeChng 更改page大小时候调用的函数,暂时没用上直接NULL
xCodecFree 其实就是代替了xFreeAux的作用,现在释放page,不用我们自己做了。

DestroyCryptBlock 函数要改一下参数类型,不然编译不过。

用20M的Demo测试,未发现明显问题。


#ifdef SQLITE_SOURCESTD  #include <pager.c>#else  #include <sqlite3.c>#endif#ifndef SQLITE_OMIT_DISKIO#ifdef SQLITE_HAS_CODEC#include "md5c.c"#define CRYPT_OFFSET 8#define BYTE unsigned char#define WX_PAGER_MJ_PGNO(x) ((PENDING_BYTE/(x))+1)Btree *m_bt;typedef struct _CryptBlock{    BYTE*     ReadKey;     // 读数据库和写入事务的密钥    BYTE*     WriteKey;    // 写入数据库的密钥    int       PageSize;    // 页的大小    BYTE*     Data;} CryptBlock, *LPCryptBlock;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 ;} /* Signal n=0,1,-1 */void sqlite3_activate_see(const char *info){}void sqlite3CodecSizeChange(void *pArg, int pageSize, int reservedSize){}/*** Get the codec argument for this pager*/void* mySqlite3PagerGetCodec(  Pager *pPager){#if (SQLITE_VERSION_NUMBER >= 3006016)  return sqlite3PagerGetCodec(pPager);#else  return (pPager->xCodec) ? pPager->pCodecArg : NULL;#endif}/*** Set the codec argument for this pager*/void mySqlite3PagerSetCodec(  Pager *pPager,  void *(*xCodec)(void*,void*,Pgno,int),  void (*xCodecSizeChng)(void*,int,int),  void (*xCodecFree)(void*),  void *pCodec){  sqlite3PagerSetCodec(pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec);}//创建或更新一个页的加密算法索引.此函数会申请缓冲区.static LPCryptBlock CreateCryptBlock(BYTE* hKey, Pager *pager, LPCryptBlock pExisting){    LPCryptBlock pBlock;    if (!pExisting) //创建新加密块    {        pBlock = sqlite3_malloc(sizeof(CryptBlock));        ZeroMemory(pBlock, sizeof(CryptBlock));        pBlock->ReadKey = hKey;        pBlock->WriteKey = hKey;        pBlock->PageSize = pager->pageSize;        pBlock->Data = (BYTE*)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 = (BYTE*)sqlite3_malloc(pBlock->PageSize + CRYPT_OFFSET);        }    }    ZeroMemory(pBlock->Data, pBlock->PageSize + CRYPT_OFFSET);    return pBlock;}//销毁一个加密块及相关的缓冲区,密钥.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);}// 释放与一个页相关的加密块void sqlite3CodecFree(void *pArg){    if (pArg)        DestroyCryptBlock((LPCryptBlock)pArg);}//加密/解密函数, 被pager调用void * sqlite3Codec(void *pArg, BYTE *data, Pgno nPageNum, int nMode){    LPCryptBlock pBlock = (LPCryptBlock)pArg;    int len = 0;    if (!pBlock) return data;    // 确保pager的页长度和加密块的页长度相等.如果改变,就需要调整.    if (nMode != 2)    {    Pager *pageHeader = sqlite3BtreePager(m_bt);        if (pageHeader->pageSize != pBlock->PageSize)  //适用旧版        {          CreateCryptBlock(0, pageHeader, 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;        CopyMemory(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;        CopyMemory(pBlock->Data + CRYPT_OFFSET, data, pBlock->PageSize);        data = pBlock->Data + CRYPT_OFFSET;        len = pBlock->PageSize / 4;        xxtea(data, len, pBlock->ReadKey);        break;    }    return data;}// 从用户提供的缓冲区中得到一个加密密钥static BYTE * DeriveKey(const void *pKey, int nKeyLen){    BYTE *  hKey = NULL;    BYTE *  digest = NULL;    MD5_CTX md5ctx;    if ((pKey == NULL) || (nKeyLen <1 ))    {        return NULL;    }    digest = sqlite3_malloc(16);    MD5Init(&md5ctx);    MD5Update(&md5ctx, (unsigned char*)pKey, nKeyLen);    MD5Final(digest, &md5ctx);    hKey = digest;    return hKey;}//被sqlite 和 sqlite3_key_interop 调用, 附加密钥到数据库.int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen){    int rc = SQLITE_ERROR;    BYTE* hKey = 0;    //如果没有指定密匙,可能标识用了主数据库的加密或没加密.    if (!pKey || !nKeyLen)    {        if (!nDb)        {          return SQLITE_OK; //主数据库, 没有指定密钥所以没有加密.        }        else //附加数据库,使用主数据库的密钥.         {          //获取主数据库的加密块并复制密钥给附加数据库使用          LPCryptBlock pBlock = (LPCryptBlock)mySqlite3PagerGetCodec(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), NULL);        m_bt = db->aDb[nDb].pBt;#if (SQLITE_VERSION_NUMBER >= 3006016)    mySqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, sqlite3CodecSizeChange, sqlite3CodecFree, pBlock);#else  #if (SQLITE_VERSION_NUMBER >= 3003014)    sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);  #else        sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);  #endif        db->aDb[nDb].pAux = pBlock;        db->aDb[nDb].xFreeAux = sqlite3CodecFree;#endif        rc = SQLITE_OK;    }    return rc;}//不保存用户的原始密码.返回NULL.void sqlite3CodecGetKey(sqlite3 *db, int nDb, void **ppKey, int *pnKeyLen){    *ppKey = NULL;    *pnKeyLen = 0;}//密钥并不保留到临时空间,仅保存于主数据库.int sqlite3_key_interop(sqlite3 *db, const void *pKey, int nKeySize){    return sqlite3CodecAttach(db, 0, pKey, nKeySize);}//改变已有数据库的加密密钥int sqlite3_rekey_interop(sqlite3 *db, const void *pKey, int nKeySize){    Btree *pbt = db->aDb[0].pBt;    Pager *pPager = sqlite3BtreePager(pbt);    LPCryptBlock pBlock = (LPCryptBlock)mySqlite3PagerGetCodec(pPager);    BYTE * hKey = DeriveKey(pKey, nKeySize);    int rc = SQLITE_ERROR;    if (!pBlock && !hKey) return SQLITE_OK;     //重新加密一个数据库,改变pager的写密钥, 读密钥依旧保留.    if (!pBlock) //加密一个未加密的数据库    {        pBlock = CreateCryptBlock(hKey, pPager, NULL);        pBlock->ReadKey = 0; // 原始数据库未加密  m_bt = db->aDb[0].pBt;#if (SQLITE_VERSION_NUMBER >= 3006016)    mySqlite3PagerSetCodec(pPager, sqlite3Codec, sqlite3CodecSizeChange, sqlite3CodecFree, pBlock);#else  #if (SQLITE_VERSION_NUMBER >= 3003014)          sqlite3PagerSetCodec(sqlite3BtreePager(pbt), sqlite3Codec, pBlock);  #else        sqlite3pager_set_codec(pPager, sqlite3Codec, pBlock);  #endif        db->aDb[0].pAux = pBlock;        db->aDb[0].xFreeAux = sqlite3CodecFree;#endif    }    else // 改变已加密数据库的写密钥    {        pBlock->WriteKey = hKey;    }    // 开始一个事务    rc = sqlite3BtreeBeginTrans(pbt, 1);    if (!rc)    {        // 用新密钥重写所有的页到数据库。  #if (SQLITE_VERSION_NUMBER >= 3006000)          int nPageCount = -1;          int rc = sqlite3PagerPagecount(pPager, &nPageCount);    Pgno nPage = (Pgno) nPageCount;  #elif (SQLITE_VERSION_NUMBER >= 3003014)    Pgno nPage = sqlite3PagerPagecount(pPager);  #else    Pgno nPage = sqlite3pager_pagecount(pPager);  #endif  int pageSize = sqlite3BtreeGetPageSize(pbt);        Pgno nSkip = WX_PAGER_MJ_PGNO(pageSize);  #if (SQLITE_VERSION_NUMBER >= 3003014)      DbPage *pPage;  #else      void *pPage;  #endif        Pgno n;        for(n = 1; rc == SQLITE_OK && n <= nPage; n ++)        {          if (n == nSkip) continue;      #if (SQLITE_VERSION_NUMBER >= 3003014)          rc = sqlite3PagerGet(pPager, n, &pPage);      #else          rc = sqlite3pager_get(pPager, n, &pPage);      #endif          if(!rc)          {    #if (SQLITE_VERSION_NUMBER >= 3003014)          rc = sqlite3PagerWrite(pPage);          sqlite3PagerUnref(pPage);    #else        rc = sqlite3pager_write(pPage);        sqlite3pager_unref(pPage);    #endif          }        }    }    // 如果成功,提交事务。    if (!rc)    {        rc = sqlite3BtreeCommit(pbt);    }    // 如果失败,回滚。    if (rc)    {        sqlite3BtreeRollback(pbt);    }    // 如果成功,销毁先前的读密钥。并使读密钥等于当前的写密钥。    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)    {#if (SQLITE_VERSION_NUMBER >= 3006016)    mySqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL);#else  #if (SQLITE_VERSION_NUMBER >= 3003014)          sqlite3PagerSetCodec(pPager, NULL, NULL);  #else    sqlite3pager_set_codec(pPager, NULL, NULL);  #endif        db->aDb[0].pAux = NULL;        db->aDb[0].xFreeAux = NULL;        sqlite3CodecFree(pBlock);#endif    }    return rc;}SQLITE_API int sqlite3_key(sqlite3 *db, const void *pKey, int nKey){    return sqlite3_key_interop(db, pKey, nKey);}SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey){    return sqlite3_rekey_interop(db, pKey, nKey);}#endif // SQLITE_HAS_CODEC#endif // SQLITE_OMIT_DISKIO


原创粉丝点击