zoukankan      html  css  js  c++  java
  • 董淳光之SQLITE3 使用总结(5)

    http://www.sqlite.com.cn/MySqlite/6/411.Html


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

    {

    return sqlite3_key_interop(db, pKey, nKey);

    }

     

    int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey)

    {

    return sqlite3_rekey_interop(db, pKey, nKey);

    }

     

    /*被sqlite 和 sqlite3_key_interop 调用, 附加密钥到数据库.*/

    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), NULL);

            sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);

            rc = SQLITE_OK;

        }

        return rc;

    }

     

    // Changes the encryption key for an existing database.

    int __stdcall 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;

     

     

    if (!pBlock && !hKey) return SQLITE_OK;

     

    //重新加密一个数据库,改变pager的写密钥, 读密钥依旧保留.

    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)

    {

         // 用新密钥重写所有的页到数据库。

         Pgno nPage = sqlite3PagerPagecount(p);

         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, &pPage);

              if(!rc)

              {

                   rc = sqlite3PagerWrite(pPage);

                   sqlite3PagerUnref(pPage);

              }

         }

    }

     

    // 如果成功,提交事务。

    if (!rc)

    {

         rc = sqlite3BtreeCommit(pbt);

    }

     

    // 如果失败,回滚。

    if (rc)

    {

         sqlite3BtreeRollback(pbt);

    }

     

     

     

    // 如果成功,销毁先前的读密钥。并使读密钥等于当前的写密钥。

    if (!rc)

    {

         if (pBlock->ReadKey)

         {

              sqliteFree(pBlock->ReadKey);

         }

         pBlock->ReadKey = pBlock->WriteKey;

    }

    else// 如果失败,销毁当前的写密钥,并恢复为当前的读密钥。

    {

         if (pBlock->WriteKey)

         {

              sqliteFree(pBlock->WriteKey);

         }

         pBlock->WriteKey = pBlock->ReadKey;

    }

     

     

     

    // 如果读密钥和写密钥皆为空,就不需要再对页进行编解码。

    // 销毁加密块并移除页的编解码器

    if (!pBlock->ReadKey && !pBlock->WriteKey)

    {

         sqlite3pager_set_codec(p, NULL, NULL);

         DestroyCryptBlock(pBlock);

    }

     

    return rc;

    }

     

     

     

     

     

     

    /***

    下面是加密函数的主体

    ***/

    int __stdcall sqlite3_key_interop(sqlite3 *db, const void *pKey, int nKeySize)

    {

      return sqlite3CodecAttach(db, 0, pKey, nKeySize);

    }

     

     

    // 释放与一个页相关的加密块

    void sqlite3pager_free_codecarg(void *pArg)

    {

    if (pArg)

         DestroyCryptBlock((LPCryptBlock)pArg);

    }

     

    #endif //#ifdef SQLITE_HAS_CODEC

      

    、       后记

    写此教程,可不是一个累字能解释。

    但是我还是觉得欣慰的,因为我很久以前就想写 sqlite 的教程,一来自己备忘,二而已造福大众,大家不用再走弯路。

    本人第一次写教程,不足的地方请大家指出。

     

    本文可随意转载、修改、引用。但无论是转载、修改、引用,都请附带我的名字:董淳光。以示对我劳动的肯定。


  • 相关阅读:
    2020年终将过去
    Opus从入门到精通(一):简介
    0907 RTCP FB
    ClickHouse源码笔记6:探究列式存储系统的排序
    C++雾中风景17:模板的非推断语境与std::type_identity
    ClickHouse源码笔记5:聚合函数的源码再梳理
    ClickHouse源码笔记4:FilterBlockInputStream, 探寻where,having的实现
    ClickHouse源码笔记3:函数调用的向量化实现
    Doris开发手记1:解决蛋疼的MySQL 8.0连接问题
    声音克隆_论文翻译:2019_Transfer Learning from Speaker Verification to Multispeaker Text-To-Speech Synthesis
  • 原文地址:https://www.cnblogs.com/iapp/p/3631771.html
Copyright © 2011-2022 走看看