#ifndef CRYPOTRC4_H #define CRYPOTRC4_H #include <afxwin.h> #include <atlcoll.h> #include <wincrypt.h> class CCryptoRC4 : CObject { public: enum CryptoType { /// <summary>未知类型</summary> Unknown = 0, /// <summary>加密类型</summary> Encrypted = 1, /// <summary>解密类型</summary> Decrypted = 2 }; public: CCryptoRC4(const TCHAR* szPassword) { Initialization((BYTE*) szPassword, (DWORD) (_tcslen(szPassword) * sizeof(TCHAR))); } CCryptoRC4(const BYTE* pbPassword, DWORD cbPassword) { Initialization(pbPassword, cbPassword); } ~CCryptoRC4() { if (m_hCryptProv) CryptReleaseContext(m_hCryptProv, 0); if (m_hCryptHash) CryptDestroyHash(m_hCryptHash); if (m_hCryptKey) CryptDestroyKey(m_hCryptKey); } /// <summary>通过RC4可逆加密数据</summary> /// <param name="szPlaintext">需要加密的密文字符串</param> /// <return>加密之后的数据(可转BYTE*)</return> const TCHAR* Encrypt(const TCHAR* szPlaintext) { size_t cbPlaintext = _tcslen(szPlaintext) * sizeof(TCHAR); Encrypt((BYTE*) szPlaintext, (DWORD) cbPlaintext); for (int i = 0; i < (int) sizeof(TCHAR); i++) m_baCiphertext.Add(0); return reinterpret_cast<TCHAR*>(m_baCiphertext.GetData()); } /// <summary>通过RC4可逆加密数据</summary> /// <param name="pbPlaintext">需要加密的密文</param> /// <param name="cbPlaintext">需要加密的密文长度</param> /// <return>加密之后的数据(可转TCHAR*)</return> void Encrypt(const BYTE* pbPlaintext, DWORD cbPlaintext) { if (!m_baCiphertext.IsEmpty()) m_baCiphertext.RemoveAll(); m_baCiphertext.SetCount(cbPlaintext); // 重置密文数据长度 memcpy_s(m_baCiphertext.GetData(), cbPlaintext, pbPlaintext, cbPlaintext); m_lastCryptoType = CryptEncrypt(m_hCryptKey, NULL, TRUE, 0, m_baCiphertext.GetData(), &cbPlaintext, cbPlaintext) ? Encrypted : Unknown; } /// <summary>通过RC4可逆解密数据</summary> /// <param name="szCiphertext">需要解密的密文字符串</param> /// <return>解密之后的数据(可转BYTE*)</return> const TCHAR* Decrypt(const TCHAR* szCiphertext) { size_t cbCiphertext = _tcslen(szCiphertext) * sizeof(TCHAR); Decrypt((BYTE *)szCiphertext, (DWORD)cbCiphertext); for (int i = 0; i < (int) sizeof(TCHAR); i++) m_baPlaintext.Add(0); return reinterpret_cast<TCHAR*>(m_baPlaintext.GetData()); } /// <summary>通过RC4可逆解密数据</summary> /// <param name="pbCiphertext">需要解密的密文</param> /// <param name="cbCiphertext">需要解密的密文长度</param> /// <return>解密之后的数据(可转TCHAR*)</return> void Decrypt(const BYTE* szCiphertext, DWORD cbCiphertext) { if (!m_baPlaintext.IsEmpty()) m_baPlaintext.RemoveAll(); m_baPlaintext.SetCount(cbCiphertext); // 重置明文数据长度 memcpy_s(m_baPlaintext.GetData(), cbCiphertext, szCiphertext, cbCiphertext); m_lastCryptoType = CryptDecrypt(m_hCryptKey, 0, TRUE, 0, m_baPlaintext.GetData(), &cbCiphertext) ? Decrypted : Unknown; } /// <summary>获取最后一次运算数据</summary> /// <return>加密之后数据或解密之后数据</return> ATL::CAtlArray<BYTE>& GetCryptoData() { return GetCryptoData(m_lastCryptoType); } /// <summary>获取加密或解密运算数据</summary> /// <param name="tyCryptoType">加密或解密类型</param> /// <return>加密之后数据或解密之后数据</return> ATL::CAtlArray<BYTE>& GetCryptoData(CryptoType tyCryptoType) { if (tyCryptoType == Encrypted) return m_baCiphertext; if (tyCryptoType == Decrypted) return m_baPlaintext; AfxThrowInvalidArgException(); } private: /// <summary>禁止复制构造函数</summary> CCryptoRC4(const CCryptoRC4&) { } /// <summary>禁止拷贝构造函数</summary> void operator =(const CCryptoRC4&) { } /// <summary>RC4可逆加密初始化</summary> /// <param name="pbPassword">RC4可逆加密密钥</param> /// <param name="cbPassword">RC4可逆加密密钥长度</param> void Initialization(const BYTE* pbPassword, DWORD cbPassword) { m_hCryptProv = NULL, m_hCryptHash = NULL, m_hCryptKey = NULL; m_lastCryptoType = Unknown; // Get a handle to user default provider. CryptAcquireContext(&m_hCryptProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT); CryptCreateHash(m_hCryptProv, CALG_SHA, 0, 0, &m_hCryptHash); CryptHashData(m_hCryptHash, pbPassword, cbPassword, 0); CryptDeriveKey(m_hCryptProv, CALG_RC4, m_hCryptHash, CRYPT_EXPORTABLE, &m_hCryptKey); } private: /// <summary>解密之后得到的明文</summary> ATL::CAtlArray<BYTE> m_baPlaintext; /// <summary>加密之后得到的密文</summary> ATL::CAtlArray<BYTE> m_baCiphertext; /// <summary>最后一次加密类型</summary> CryptoType m_lastCryptoType; /// <summary>密码系统服务提供句柄</summary> HCRYPTPROV m_hCryptProv; /// <summary>密码系统哈希对象集句柄</summary> HCRYPTHASH m_hCryptHash; /// <summary>密码系统密钥集句柄</summary> HCRYPTKEY m_hCryptKey; }; #endif // CRYPOTRC4_H