您的位置:首页 > 其它

EF AES Library 的封装类

2015-07-04 17:20 288 查看
昨天要完成一个参数文件加密存储的子任务, 在CodeProject上找到一个 <<EF AES Library>>, 很易用.

但是原始Demo中, 那个文件操作,有点问题, 会导致报错. 需要再处理一下.

完成任务之后,今天又琢磨了一下,在<<EF AES Library>>基础上, 封装了一个更易用的文件AES加解密类.

如果要完成类似任务,只需要从 CDtoAesOptBase 继承一个子类, 实现3个虚函数就搞定了.

工程下载点: srcAesOpt_2015_0704_1807.zip

编译环境 : vs2010 vc++ + console

测试程序:

// srcAesOpt.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "aes_opt/dto_aes_opt.h"
#include "aes_opt/AesKeyParam_128Bit.h"

void fnTestAes(int iTaskSn);

int _tmain(int argc, _TCHAR* argv[])
{
    int iTaskSn = 0;
    int iDoCnt = 3;

    do 
    {
        fnTestAes(iTaskSn++);
    } while (--iDoCnt > 0);

    _tprintf(L"END, press any key to quit\r\n");
    getwchar();
	return 0;
}

void fnTestAes(int iTaskSn)
{
    BOOL bTmp = FALSE;

    CDtoAesOpt AesOpt; ///< 定义自己的CDtoAesOpt即可, 工作量很小.
    CAesKeyParam128Bit AesKeyParam;

    _tprintf(L"[%d]==>\r\n", iTaskSn);

    if (AesOpt.LoadFromDisk(&AesKeyParam))
    {
        bTmp = AesOpt.geter_ShowAlertOnce();
        _tprintf(L"load ok, AesOpt.geter_ShowAlertOnce() = %d\r\n", bTmp);
    }
    else
    {
        _tprintf(L"load err\r\n");
    }

    AesOpt.seter_ShowAlertOnce(!bTmp);
    if (AesOpt.SaveToDisk(&AesKeyParam))
    {
        _tprintf(L"save ok\r\n");
    }
    else
    {
        _tprintf(L"save err\r\n");
    }

    if (AesOpt.LoadFromDisk(&AesKeyParam))
    {
        bTmp = AesOpt.geter_ShowAlertOnce();
        _tprintf(L"load ok, AesOpt.geter_ShowAlertOnce() = %d\r\n", bTmp);
    }
    else
    {
        _tprintf(L"load err\r\n");
    }
}
运行结果:

[0]==>
load ok, AesOpt.geter_ShowAlertOnce() = 0
save ok
load ok, AesOpt.geter_ShowAlertOnce() = 1
[1]==>
load ok, AesOpt.geter_ShowAlertOnce() = 1
save ok
load ok, AesOpt.geter_ShowAlertOnce() = 0
[2]==>
load ok, AesOpt.geter_ShowAlertOnce() = 0
save ok
load ok, AesOpt.geter_ShowAlertOnce() = 1
END, press any key to quit


封装类的基类

/// @file       dto_aes_opt_base.h
/// @brief      数据传送类, 文件AES读写类的基类

#ifndef __DTO_AES_OPT_BASE_H__
#define __DTO_AES_OPT_BASE_H__

#include "stdafx.h"
#include "aes_opt/IAesKeyParam.h"

class CDtoAesOptBase
{
public:
    enum param
    {
        param_SizeMinBlock = 4096,
        param_SizeKey = 16,
    };

public:
    CDtoAesOptBase();
    virtual ~CDtoAesOptBase(void);

    // 成员函数
public:
    BOOL LoadFromDisk(IAesKeyParam* pOwner);
    BOOL SaveToDisk(IAesKeyParam* pOwner);

protected:
    virtual std::wstring GetLocalFilePathName() = 0;

    virtual BOOL Buffer2Member() = 0;
    virtual void Member2Buffer() = 0;

    void setBuffer(unsigned char* pBuf) {m_pBuffer = pBuf;}
    unsigned char* getBuffer() {return m_pBuffer;}

    void setBufferSize(size_t nLen) {m_nLenBuffer = nLen;}
    size_t getBufferSize() {return m_nLenBuffer;}

    void SetVersion(LONGLONG llVer) {m_llVersion = llVer;}
    LONGLONG GetVersion() {return m_llVersion;}

    void Lock() {m_Locker.enter(L"CDtoAesOptBase");}
    void UnLock() {m_Locker.leave();}

private:
    void AesKeyInit();

    // 成员变量
private:
    ns_base::CCriticalSection m_Locker;

    unsigned char* m_pBuffer;
    size_t m_nLenBuffer;
    LONGLONG m_llVersion;

    unsigned char m_cAesKey[CDtoAesOptBase::param_SizeKey];
    unsigned char m_cAesVector[CDtoAesOptBase::param_SizeKey];
};

#endif // #ifndef __DTO_AES_OPT_BASE_H__


/// @file       aes_opt\dto_aes_opt_base.cpp

#include "StdAfx.h"
#include <fcntl.h>
#include "dto_aes_opt_base.h"
#include "AES/EfAes.H"
#include "stringHelper/StringHelper.h"
#include "FileHelper/FileHelper.h"
#include "UtilityHelper/constDefine.h"
#include "UtilityHelper/UtilityHelper.h"

CDtoAesOptBase::CDtoAesOptBase() :
    m_llVersion(201507041540)
{
    AesKeyInit();
    m_pBuffer = NULL;
    m_nLenBuffer = 0;
}

CDtoAesOptBase::~CDtoAesOptBase(void)
{
}

void CDtoAesOptBase::AesKeyInit()
{
    int iIndex = 0;

    unsigned char key[CDtoAesOptBase::param_SizeKey]={
        0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
        0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88
    };

    unsigned char vector[CDtoAesOptBase::param_SizeKey]={
        0x1f,0x32,0x43,0x51,0x56,0x98,0xaf,0xed,
        0xab,0xc8,0x21,0x45,0x63,0x72,0xac,0xfc
    };

    for (iIndex = 0; iIndex < CDtoAesOptBase::param_SizeKey; iIndex++)
    {
        m_cAesKey[iIndex] = key[iIndex];
        m_cAesVector[iIndex] = vector[iIndex];
    }
}

BOOL CDtoAesOptBase::LoadFromDisk(IAesKeyParam* pOwner)
{
    HANDLE hfile = NULL;
    DWORD dwRdBk= 0;

    unsigned char* pDataBuf = NULL;

    BOOL bLoadDataOk = FALSE;
    size_t nPosDataBuf = 0;
    std::string strAesKeyA = "";
    int iMyKeyLen = 0;
    int iIndex = 0;

    int rdsz = 0;
    AesCtx context;
    unsigned char buff[param_SizeMinBlock];

    do 
    {
        if (NULL == pOwner)
            break;

        pDataBuf = getBuffer();
        if (NULL == pDataBuf)
            break;

        strAesKeyA = ns_base::W2Aex(pOwner->GetAesKey().c_str()).c_str();
        iMyKeyLen = pOwner->GetAesKeyLen();
        if (iMyKeyLen > CDtoAesOptBase::param_SizeKey)
            iMyKeyLen = CDtoAesOptBase::param_SizeKey;

        AesKeyInit();
        for (iIndex = 0; iIndex < iMyKeyLen; iIndex++)
        {
            m_cAesKey[iIndex] = strAesKeyA[iIndex];
        }

        AesSetKey(&context, AES_KEY_128BIT, BLOCKMODE_CRT, m_cAesKey, m_cAesVector);

        do 
        {
            if (!ns_base::OpenFileReadBinary(GetLocalFilePathName().c_str(), hfile))
                break;

            while (1)
            {
                rdsz = CDtoAesOptBase::param_SizeMinBlock;
                if (!ns_base::ReadFileBinary(hfile, buff, rdsz, dwRdBk))
                    break;

                // before last block , the block size
                // should always be the multiply of 16
                // the last block should be handled
                // if the size is not a multiply of 16

                AesDecryptCRT(&context , buff, buff, rdsz);
                rdsz = AesRoundSize( rdsz, CDtoAesOptBase::param_SizeKey);

                if ((nPosDataBuf + dwRdBk) > getBufferSize())
                {
                    break;
                }

                memcpy((char*)pDataBuf + nPosDataBuf, buff, dwRdBk); 
                nPosDataBuf += dwRdBk;
            }
            ns_base::CloseFileHandle(hfile);
        } while (0);

        bLoadDataOk = (nPosDataBuf == getBufferSize());
    } while (0);

    if (bLoadDataOk)
    {
        bLoadDataOk = Buffer2Member(); ///< 如果文件版本不对,算作载入失败
    }

    return bLoadDataOk;
}

BOOL CDtoAesOptBase::SaveToDisk(IAesKeyParam* pOwner)
{
    HANDLE hfile = NULL;

    BOOL bRc = FALSE;
    unsigned char* pDataBuf = NULL;
    size_t nPosDataBuf = 0;
    size_t nLeftDataBuf = 0;
    std::string strAesKeyA = "";
    int iMyKeyLen = 0;
    int iIndex = 0;

    int rdsz = 0;
    DWORD dwWrBk = 0;
    AesCtx context;
    unsigned char buff[CDtoAesOptBase::param_SizeMinBlock];

    do 
    {
        if (NULL == pOwner)
            break;

        pDataBuf = getBuffer();
        if (NULL == pDataBuf)
            break;

        Member2Buffer();

        strAesKeyA = ns_base::W2Aex(pOwner->GetAesKey().c_str()).c_str();
        iMyKeyLen = pOwner->GetAesKeyLen();
        if (iMyKeyLen > CDtoAesOptBase::param_SizeKey)
            iMyKeyLen = CDtoAesOptBase::param_SizeKey;

        AesKeyInit();
        for (iIndex = 0; iIndex < iMyKeyLen; iIndex++)
        {
            m_cAesKey[iIndex] = strAesKeyA[iIndex];
        }

        AesSetKey(&context, AES_KEY_128BIT, BLOCKMODE_CRT, m_cAesKey, m_cAesVector);
        if (!ns_base::OpenFileWriteBinary(GetLocalFilePathName().c_str(), hfile))
            break;

        nLeftDataBuf = getBufferSize();
        _ASSERT(0 == (nLeftDataBuf % CDtoAesOptBase::param_SizeMinBlock));

        nPosDataBuf = 0;
        while (nLeftDataBuf > 0)
        {
            rdsz = CDtoAesOptBase::param_SizeMinBlock;
            memcpy(buff, (char*)pDataBuf + nPosDataBuf, rdsz);

            // before last block , the block size
            // should always be the multiply of 16
            // the last block should be handled
            // if the size is not a multiply of 16
            AesEncryptCRT(&context , buff, buff, rdsz );
            rdsz = AesRoundSize( rdsz, CDtoAesOptBase::param_SizeKey);

            ns_base::WriteFileBinary(hfile, buff, rdsz, dwWrBk);

            nPosDataBuf += rdsz;
            nLeftDataBuf -= rdsz;
        }
        ns_base::CloseFileHandle(hfile);

        bRc = TRUE;
    } while (0);

    ns_base::SetFilePermissionToEveryOne_Real(GetLocalFilePathName().c_str());
    return bRc;
}


干活用的子类,方便调用者, 构造起来很简单.

/// @file       dto_aes_opt.h
/// @brief      数据传送类, 记录参数文件加密相关的数据

#ifndef __DTO_AES_OPT_H__
#define __DTO_AES_OPT_H__

#include "stdafx.h"
#include "dto_aes_opt_base.h"
#include "AesKeyParam_128Bit.h"

class CDtoAesOpt : public CDtoAesOptBase
{
public:
    typedef struct _tag_data_buf
    {
        union
        {
            char cArrReserve[CDtoAesOptBase::param_SizeMinBlock * 4];
            struct
            {
                LONGLONG llVer; ///< 必须设置版本号, 防止读入的数据不正确
                BOOL bUserChoiceNotAlert; ///< 用户选择不弹出提示框
                BOOL bShowAlertOnce; ///< 开机后, 已经显示过一次提示
            };
        };

        _tag_data_buf()
        {
            ZeroMemory(cArrReserve, sizeof(cArrReserve));

            llVer = 0;
            bUserChoiceNotAlert = FALSE;
            bShowAlertOnce = FALSE;
        }
    }TAG_DATA_BUF;

public:
    CDtoAesOpt();
    virtual ~CDtoAesOpt(void);

    // 成员函数
public:
    /// 必须实现的纯虚函数
    virtual std::wstring GetLocalFilePathName();

    virtual BOOL Buffer2Member();
    virtual void Member2Buffer();

    /// 自己的成员变量存取函数
    BOOL geter_UserChoiceNotAlert() {return m_bUserChoiceNotAlert;}
    void seter_UserChoiceNotAlert(BOOL bIn) {m_bUserChoiceNotAlert = bIn;}

    BOOL geter_ShowAlertOnce() {return m_bShowAlertOnce;}
    void seter_ShowAlertOnce(BOOL bIn) {m_bShowAlertOnce = bIn;}

private:
    /// 初始化函数
    void DataInit();
    void DataUnInit();

    // 成员变量
private:
    BOOL m_bUserChoiceNotAlert; ///< 用户选择不弹出提示框
    BOOL m_bShowAlertOnce; ///< 开机后, 已经显示过一次提示
};

#endif // #ifndef __DTO_AES_OPT_H__


/// @file       dto_aes_opt.cpp

#include "StdAfx.h"
#include <fcntl.h>
#include "dto_aes_opt.h"
#include "AES/EfAes.H"
#include "stringHelper/StringHelper.h"
#include "FileHelper/FileHelper.h"
#include "UtilityHelper/constDefine.h"
#include "UtilityHelper/UtilityHelper.h"

CDtoAesOpt::CDtoAesOpt()
{
    SetVersion(201507041552); ///< 必须设置自己的版本, 防止文件序列化后,读到的文件格式不符合预期
    DataInit();
}

CDtoAesOpt::~CDtoAesOpt(void)
{
    DataUnInit();
}

void CDtoAesOpt::DataInit()
{
    setBuffer((unsigned char*)(new TAG_DATA_BUF));
    setBufferSize(sizeof(TAG_DATA_BUF));

    if (NULL != getBuffer())
        ZeroMemory(getBuffer(), getBufferSize());

    m_bShowAlertOnce = FALSE;
    m_bUserChoiceNotAlert = FALSE;
}

void CDtoAesOpt::DataUnInit()
{
    unsigned char* pBuffer = getBuffer();

    SAFE_DELETE(pBuffer);
    setBuffer(pBuffer);
}

BOOL CDtoAesOpt::Buffer2Member()
{
    BOOL bRc = FALSE;

    do 
    {
        if (NULL == getBuffer())
            break;

        m_bUserChoiceNotAlert = ((TAG_DATA_BUF*)getBuffer())->bUserChoiceNotAlert;
        m_bShowAlertOnce = ((TAG_DATA_BUF*)getBuffer())->bShowAlertOnce;

        bRc = (GetVersion() == ((TAG_DATA_BUF*)getBuffer())->llVer);
    } while (0);

    return bRc;
}

void CDtoAesOpt::Member2Buffer()
{
    do 
    {
        if (NULL == getBuffer())
            break;

        ((TAG_DATA_BUF*)getBuffer())->llVer = GetVersion();
        ((TAG_DATA_BUF*)getBuffer())->bUserChoiceNotAlert = m_bUserChoiceNotAlert;
        ((TAG_DATA_BUF*)getBuffer())->bShowAlertOnce = m_bShowAlertOnce;
    } while (0);
}

std::wstring CDtoAesOpt::GetLocalFilePathName()
{
    std::wstring strCfgFilePathName = L"";

    Lock();
    /// 根据实际情况来, 这里假设文件为 APPDATA\test.dat
    ns_base::GetAppDataDir(strCfgFilePathName);
    strCfgFilePathName += L"test.dat";
    UnLock();

    return strCfgFilePathName;
}


AesKey参数接口

/// @file aes_opt\IAesKeyParam.h

#include "stdafx.h"
#include <objbase.h>

#ifndef __AES_OPT_IAESOPTOWNER_H__
#define __AES_OPT_IAESOPTOWNER_H__

interface IAesKeyParam
{
    virtual std::wstring GetAesKey() = 0;
    virtual size_t GetAesKeyLen() = 0;
};

#endif


子类用的AesKey参数类, 从接口 IAesKeyParam继承

/// @file aes_opt\AesKeyParam_128Bit.h

#ifndef __AES_OPT_AESOPTONWER_128BIT_H__
#define __AES_OPT_AESOPTONWER_128BIT_H__

#include "IAesKeyParam.h"

class CAesKeyParam128Bit :
    public IAesKeyParam
{
public:
    CAesKeyParam128Bit(void);
    virtual ~CAesKeyParam128Bit(void);

    virtual std::wstring GetAesKey();
    virtual size_t GetAesKeyLen();

private:
    const std::wstring m_strAesKey;
};

#endif // #ifndef __AES_OPT_AESOPTONWER_128BIT_H__


#include "StdAfx.h"
#include "AesKeyParam_128Bit.h"

CAesKeyParam128Bit::CAesKeyParam128Bit(void)
    : m_strAesKey(L"123456")
{
}

CAesKeyParam128Bit::~CAesKeyParam128Bit(void)
{
}

std::wstring CAesKeyParam128Bit::GetAesKey()
{
    /// 实际工程中, 口令是从别的途径来的
    /// 口令使用时, 会转成char*, 128Bit是8个字节
    /// 超过8个字节的口令内容用不到了
    return m_strAesKey;
}

size_t CAesKeyParam128Bit::GetAesKeyLen()
{
    return _tcslen(GetAesKey().c_str());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: