因为工作之故,需要用到3des加密.以前没有接触过,查了半天资料,只知道3des是des的变种,用k1和k2两个密要,加长了密钥长度,密文是用k1加密,k2解密,然后再用k1加密生成的.但是理论的东西毕竟太抽象,后来也不知道听谁说的,vc或是.net里直接有类似的函数可以调用,搜索了一下,在vc6的include的文件夹找到了一个wincrypt.h的文件.里面有两个看上去很美的东东,
#define CALG_3DES_112 (ALG_CLASS_DATA_ENCRYPT ¦ALG_TYPE_BLOCK ¦ALG_SID_3DES_112)
#define CALG_3DES (ALG_CLASS_DATA_ENCRYPT ¦ALG_TYPE_BLOCK ¦ALG_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(&hProv,
4"aspZoneCryptoComponent\0", MS_DEF_PROV,
5PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
6{
7if (! CryptAcquireContext(&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, &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, &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, &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*)&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->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->vt == (VT_ARRAY ¦ VT_VARIANT))
6SafeArrayCopy(vCipherText.pvarVal->parray, &psa);
7else
8{
9if (vCipherText.pvarVal->vt == (VT_ARRAY ¦ VT_VARIANT ¦ VT_BYREF))
10SafeArrayCopy(*(vCipherText.pvarVal->pparray), &psa);
11}
12}
13else
14{
15if (vCipherText.vt == (VT_ARRAY ¦ VT_VARIANT ¦ VT_BYREF))
16SafeArrayCopy(*(vCipherText.pparray), &psa);
17else
18{
19if (vCipherText.vt == (VT_ARRAY ¦ VT_VARIANT))
20SafeArrayCopy(vCipherText.parray, &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*)&pVar);
4SafeArrayGetLBound(psa, 1, &lBound);
5SafeArrayGetUBound(psa, 1, &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 <= uBound; i++){ if( ! (pVar[i].vt & 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(&hProv, "aspZoneCryptoComponent\0",
4MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
5{
6if (! CryptAcquireContext(&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, &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, &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>