使用 Visual C++创建Crypto加/解密组件

80酷酷网    80kuku.com

  c++|visual|创建|解密 
使用 Visual C++创建Crypto/解密组件
简介
这篇文章将教你如何使用 Visual C++ 和 ATL 工具和 Microsoft CryptoAPI 建立一个能加/解密数据的组件。
Crypto 101
本文使用Microsoft® Cryptographic Application Programming Interface (CryptoAPI),将苦涩难懂的逻辑算法操作隐藏起来,如果想知道详细信息请参看MSDN Library.如果想知道更多的密码系统,我推荐你看看这本书 Bruce Schneier's Applied Cryptography: Protocols, Algorithms, and Source Code in C

建立组件
首先,用"ATL COM AppWizard”建立一个新project。在这个例子中,我将其命名为”CryptoProj”。在 server type中选择”Dynamic Link Library (DLL)”,点按”Finish”继续。

定义界面
在 insert 菜单中点按"New ATL Object...",选择 “Simple Object”,然后按 Next。

在 “Names” 栏中,设 short name 为 “Crypto”,其他项照下面的填写。

在 Attributes  栏,确定 Apartment Threading Model 被选上,Support IsupportErrorInfo 选项勾上,然后按 OK.

按右键点击 Icrypto ,点”Add Method”加一个方法.

将该方法取名为”Encrypt”,在参数栏输入"[in] BSTR bstrPlainText, [in] BSTR bstrPassword, [out, retval] VARIANT *vCipherText".

再加一个方法,取名为”Decrypt”,参数为"[in] VARIANT vCipherText, [in] BSTR bstrPassword, [out, retval] BSTR *bstrPlainText"

实现加密方法
需要包括 CryptoAPI 库,在 Crypto.cpp 头加一句:

#include <wincrypt.h>

现在来定义我们需要的各种变量。
STDMETHODIMP CCrypto::Encrypt(BSTR bstrPlainText,
                              BSTR bstrPassword,
                              VARIANT *vCipherText)
{
        BYTE *pbData;
        BYTE *pbPassword;
        SAFEARRAY* psa;
        HCRYPTPROV hProv   = 0;
        HCRYPTHASH hHash   = 0;
        HCRYPTKEY hKey     = 0;
        DWORD dwCryptDataLen = 0;
        DWORD dwDataLen = 0;
        DWORD dwError = 0;
        char  buffer[200];
 
        USES_CONVERSION;

由于许多CryptoAPI 调用要用注册表,所以需要执行一句RevertToSelf().
RevertToSelf();

下一步,我们需要将输入变量转化为我们能用的格式。
dwDataLen = SysStringLen(bstrPlainText);
pbData = (BYTE*)OLE2A(bstrPlainText);
pbPassword = (BYTE*)OLE2A(bstrPassword);

然后,用CryptAcquireContext function取得省缺 Crypto provider的句柄。
// Get handle to the default provider.
if (! CryptAcquireContext(&hProv,
   "aspZoneCryptoComponent\0", MS_DEF_PROV, 
   PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
{
        if (! CryptAcquireContext(&hProv,
           "aspZoneCryptoComponent\0", MS_DEF_PROV,
           PROV_RSA_FULL, (CRYPT_NEWKEYSET |
           CRYPT_MACHINE_KEYSET)))
        {
               dwError = GetLastError();
               sprintf(buffer, "Error %x during CryptAcquireContext",
                  dwError);
               return Error(buffer);
        }
}

我们通过创建一个 one-way-hash密码得到session key。
// Create a hash object.
if ( ! CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
        dwError = GetLastError();
        sprintf(buffer, "Error %x during CryptCreateHash", dwError);
        return Error(buffer);
}
 
// Hash in the password.
if ( ! CryptHashData(hHash, pbPassword, S

分享到
  • 微信分享
  • 新浪微博
  • QQ好友
  • QQ空间
点击: