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
测试程序:
封装类的基类
干活用的子类,方便调用者, 构造起来很简单.
AesKey参数接口
子类用的AesKey参数类, 从接口 IAesKeyParam继承
但是原始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()); }
相关文章推荐
- VS2013中Image Watch插件的使用(OpenCV)
- MessageFormat(动态文本)
- error C2660: ‘Create’ : function does not take 2 parameters
- VS2013中Image Watch插件的使用(OpenCV)
- 安卓5.0宣告了ARM平台全面进入64位时代
- apt-get 与 yum 的区别
- iOS阶段学习第13天笔记(多态)
- 如何体现业务流程的执行力、效率和效益?
- 手游帧同步的研究
- Linux crontab定时执行任务 命令格式与详细例子
- python 文件对象的继承
- C#类的继承,方法的重载和覆写
- 汉字注音符号学习(引用自维基百科)
- Android程序:使用系统服务*1.获取网络状态 * 2.打开关闭wifi * 3.获取系统音量 * 4.获取运行程序的包名
- Protocol_OSPF
- E - windy数
- Spring MVC讲解
- errorC2440:CMainFrame 无法从 NMTOOLBARA 转换为 NMHDR
- Java之单例模式
- important information!