谁用过wincrypt.h文件

因为工作之故,需要用到3des加密.以前没有接触过,查了半天资料,只知道3des是des的变种,用k1和k2两个密要,加长了密钥长度,密文是用k1加密,k2解密,然后再用k1加密生成的.但是理论的东西毕竟太抽象,后来也不知道听谁说的,vc或是.net里直接有类似的函数可以调用,搜索了一下,在vc6的include的文件夹找到了一个wincrypt.h的文件.里面有两个看上去很美的东东,
#define CALG_3DES_112 (ALG_CLASS_DATA_ENCRYPT &brvbarALG_TYPE_BLOCK &brvbarALG_SID_3DES_112)
#define CALG_3DES (ALG_CLASS_DATA_ENCRYPT &brvbarALG_TYPE_BLOCK &brvbarALG_SID_3DES)
有谁以前用过?那位大侠可以告诉俺这两东东怎么用吗?
用vc和vb都可以
---------------------------------------------------------------

使用 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

1<p>建立组件   
2首先,用"ATL COM AppWizard”建立一个新project。在这个例子中,我将其命名为”CryptoProj”。在 server type中选择”Dynamic Link Library (DLL)”,点按”Finish”继续。</p>
1<p>定义界面   
2在 insert 菜单中点按"New ATL Object...",选择 “Simple Object”,然后按 Next。</p>
1<p>在 “Names” 栏中,设 short name 为 “Crypto”,其他项照下面的填写。</p>
1<p>在 Attributes 栏,确定 Apartment Threading Model 被选上,Support IsupportErrorInfo 选项勾上,然后按 OK.</p>
1<p>按右键点击 Icrypto ,点”Add Method”加一个方法.</p>
1<p>将该方法取名为”Encrypt”,在参数栏输入"[in] BSTR bstrPlainText, [in] BSTR bstrPassword, [out, retval] VARIANT *vCipherText".</p>
1<p>再加一个方法,取名为”Decrypt”,参数为"[in] VARIANT vCipherText, [in] BSTR bstrPassword, [out, retval] BSTR *bstrPlainText"</p>
1<p>实现加密方法   
2需要包括 CryptoAPI 库,在 Crypto.cpp 头加一句: #include <wincrypt.h></wincrypt.h></p>
 1<p>   
 2现在来定义我们需要的各种变量。STDMETHODIMP CCrypto::Encrypt(BSTR bstrPlainText,   
 3BSTR bstrPassword,   
 4VARIANT *vCipherText)   
 5{   
 6BYTE *pbData;   
 7BYTE *pbPassword;   
 8SAFEARRAY* psa;   
 9HCRYPTPROV hProv = 0;   
10HCRYPTHASH hHash = 0;   
11HCRYPTKEY hKey = 0;   
12DWORD dwCryptDataLen = 0;   
13DWORD dwDataLen = 0;   
14DWORD dwError = 0;   
15char buffer[200];</p>
1<p>USES_CONVERSION;</p>
1<p>   
2由于许多CryptoAPI 调用要用注册表,所以需要执行一句RevertToSelf().RevertToSelf();</p>
1<p>   
2下一步,我们需要将输入变量转化为我们能用的格式。dwDataLen = SysStringLen(bstrPlainText);   
3pbData = (BYTE*)OLE2A(bstrPlainText);   
4pbPassword = (BYTE*)OLE2A(bstrPassword);</p>
 1<p>   
 2然后,用CryptAcquireContext function取得省缺 Crypto provider的句柄。// Get handle to the default provider.   
 3if (! CryptAcquireContext(&amp;hProv,   
 4"aspZoneCryptoComponent\0", MS_DEF_PROV,   
 5PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))   
 6{   
 7if (! CryptAcquireContext(&amp;hProv,   
 8"aspZoneCryptoComponent\0", MS_DEF_PROV,   
 9PROV_RSA_FULL, (CRYPT_NEWKEYSET ¦   
10CRYPT_MACHINE_KEYSET)))   
11{   
12dwError = GetLastError();   
13sprintf(buffer, "Error %x during CryptAcquireContext",   
14dwError);   
15return Error(buffer);   
16}   
17}</p>
 1<p>   
 2  
 3\---------------------------------------------------------------   
 4  
 5我们通过创建一个 one-way-hash密码得到session key。 // Create a hash object.   
 6if ( ! CryptCreateHash(hProv, CALG_MD5, 0, 0, &amp;hHash)) {   
 7dwError = GetLastError();   
 8sprintf(buffer, "Error %x during CryptCreateHash", dwError);   
 9return Error(buffer);   
10}</p>
1<p>// Hash in the password.   
2if ( ! CryptHashData(hHash, pbPassword, SysStringLen(bstrPassword), 0)) {   
3dwError = GetLastError();   
4sprintf(buffer, "Error %x during CryptHashData", dwError);   
5return Error(buffer);   
6}</p>
1<p>// Derive a session key from the hash object.   
2if ( ! CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &amp;hKey)) {   
3dwError = GetLastError();   
4sprintf(buffer, "Error %x during CryptDeriveKey", dwError);   
5return Error(buffer);   
6}</p>
1<p>// Destroy hash object.   
2CryptDestroyHash(hHash);   
3hHash = 0;</p>
1<p>   
2现在来加密我们的数据。// Encrypt the Data.   
3dwCryptDataLen = dwDataLen;   
4if ( ! CryptEncrypt(hKey, 0, true, 0, pbData, &amp;dwCryptDataLen, dwDataLen)) {   
5dwError = GetLastError();   
6sprintf(buffer, "Error %x during CryptEncrypt", dwError);   
7return Error(buffer);   
8}</p>
1<p>   
2我们将加密后的数据放入一个数组中,而不是一个string里,因为它可能会包含null。虽然 BSTR 能处理null的情况,但不能保证用户调用环境能正确处理,所以一个数组是最好的选择。// Place Encrypted Data into a VARIANT SAFEARRAY of VARIANT BYTE   
3SAFEARRAYBOUND rgsabound[] = {dwCryptDataLen, 0};   
4psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);   
5VARIANT* rgElems;   
6SafeArrayAccessData(psa, (LPVOID*)&amp;rgElems);   
7for(DWORD i=0;i<dwcryptdatalen;i++){ rgelems[i].uival="pbData[i];" rgelems[i].vt="VT_UI1;" safearrayunaccessdata(psa);="" variantinit(&rgelems[i]);="" variantinit(vciphertext);="" vciphertext-="" }="">vt = (VT_ARRAY ¦ VT_VARIANT) ;   
8vCipherText-&gt;parray = psa;</dwcryptdatalen;i++){></p>
1<p>   
2稍微整理一下,搞定。// Destroy session key.   
3if(hKey) CryptDestroyKey(hKey);</p>
1<p>// Release provider handle.   
2if(hProv) CryptReleaseContext(hProv, 0);</p>
1<p>return S_OK;</p>
 1<p>   
 2实现解密方法   
 3首先定义变量。STDMETHODIMP CCrypto::Decrypt(VARIANT vCipherText,   
 4BSTR bstrPassword,   
 5BSTR *bstrPlainText)   
 6{   
 7HCRYPTPROV hProv = 0;   
 8HCRYPTHASH hHash = 0;   
 9HCRYPTKEY hKey = 0;   
10SAFEARRAY* psa;   
11VARIANT HUGEP *pVar;   
12BYTE *pbData;   
13BYTE *pbPassword;   
14long lBound, uBound;   
15DWORD dwCryptDataLen = 0;   
16DWORD dwOffset = 0;   
17DWORD dwError = 0;   
18char buffer[200];</p>
1<p>USES_CONVERSION;</p>
1<p>   
2同样的原因,我们要调用RevertToSelf()RevertToSelf();</p>
 1<p>   
 2现在,当接收一个数组参数作为变量,该数组可能藏在结构中的某个地方,所以需要一个判断嵌套。//Get the safe array out of the Variant.   
 3if (vCipherText.vt == (VT_VARIANT ¦ VT_BYREF))   
 4{   
 5if (vCipherText.pvarVal-&gt;vt == (VT_ARRAY ¦ VT_VARIANT))   
 6SafeArrayCopy(vCipherText.pvarVal-&gt;parray, &amp;psa);   
 7else   
 8{   
 9if (vCipherText.pvarVal-&gt;vt == (VT_ARRAY ¦ VT_VARIANT ¦ VT_BYREF))   
10SafeArrayCopy(*(vCipherText.pvarVal-&gt;pparray), &amp;psa);   
11}   
12}   
13else   
14{   
15if (vCipherText.vt == (VT_ARRAY ¦ VT_VARIANT ¦ VT_BYREF))   
16SafeArrayCopy(*(vCipherText.pparray), &amp;psa);   
17else   
18{   
19if (vCipherText.vt == (VT_ARRAY ¦ VT_VARIANT))   
20SafeArrayCopy(vCipherText.parray, &amp;psa);   
21else   
22return DISP_E_TYPEMISMATCH;   
23}   
24}</p>
1<p>   
2需要密文和密码都是BYTE*类型。//Convert the SAFEARRAY into a form we can use.   
3SafeArrayAccessData(psa, (void HUGEP* FAR*)&amp;pVar);   
4SafeArrayGetLBound(psa, 1, &amp;lBound);   
5SafeArrayGetUBound(psa, 1, &amp;uBound);</p>
1<p>dwOffset = 0 - lBound;   
2dwCryptDataLen = uBound + dwOffset + 1;</p>
1<p>//Allocate memory   
2pbData = (BYTE *)malloc(dwCryptDataLen);</p>
1<p>//Copy the array   
2for(DWORD i = lBound; i &lt;= uBound; i++){ if( ! (pVar[i].vt &amp; VT_UI1)){ //Data Elements must be VT_UI1 (Bytes). free(pbData); return DISP_E_TYPEMISMATCH; } pbData[i + dwOffset]="pVar[i].uiVal;" } //Get Password pbPassword="(BYTE*)OLE2A(bstrPassword);</p>
 1<p>   
 2取得 Crypto Provider 的句柄。// Get handle to the default provider.   
 3if (! CryptAcquireContext(&amp;hProv, "aspZoneCryptoComponent\0",   
 4MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))   
 5{   
 6if (! CryptAcquireContext(&amp;hProv, "aspZoneCryptoComponent\0",   
 7MS_DEF_PROV, PROV_RSA_FULL, (CRYPT_NEWKEYSET ¦ CRYPT_MACHINE_KEYSET)))   
 8{   
 9dwError = GetLastError();   
10sprintf(buffer, "Error %x during CryptAcquireContext", dwError);   
11return Error(buffer);   
12}   
13}</p>
1<p>   
2从 password 中得到 session key.// Create a hash object.   
3if ( ! CryptCreateHash(hProv, CALG_MD5, 0, 0, &amp;hHash)) {   
4dwError = GetLastError();   
5sprintf(buffer, "Error %x during CryptCreateHash", dwError);   
6return Error(buffer);   
7}</p>
1<p>// Hash in the password.   
2if ( ! CryptHashData(hHash, pbPassword, SysStringLen(bstrPassword), 0)) {   
3dwError = GetLastError();   
4sprintf(buffer, "Error %x during CryptHashData", dwError);   
5return Error(buffer);   
6}</p>
1<p>// Derive a session key from the hash object.   
2if ( ! CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &amp;hKey)) {   
3dwError = GetLastError();   
4sprintf(buffer, "Error %x during CryptDeriveKey", dwError);   
5return Error(buffer);   
6}</p>
1<p>// Destroy hash object.   
2CryptDestroyHash(hHash);   
3hHash = 0;</p>
Published At
Categories with 服务器类
Tagged with
comments powered by Disqus