EF AES Library 的封装类
发布日期:2021-06-30 22:06:09 浏览次数:2 分类:技术文章

本文共 12622 字,大约阅读时间需要 42 分钟。

昨天要完成一个参数文件加密存储的子任务, 在CodeProject上找到一个 <<EF AES Library>>, 很易用.

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

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

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

工程下载点: 

编译环境 : 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() = 0save okload ok, AesOpt.geter_ShowAlertOnce() = 1[1]==>load ok, AesOpt.geter_ShowAlertOnce() = 1save okload ok, AesOpt.geter_ShowAlertOnce() = 0[2]==>load ok, AesOpt.geter_ShowAlertOnce() = 0save okload ok, AesOpt.geter_ShowAlertOnce() = 1END, 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 
#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 
#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 
#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());}

转载地址:https://lostspeed.blog.csdn.net/article/details/46756405 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:svn Bogus date
下一篇:zlib解压时, 文件夹的判断

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月14日 14时25分03秒